1. 程式人生 > >從FILE_OBJECT裡獲取完整NT路徑和DOS路徑

從FILE_OBJECT裡獲取完整NT路徑和DOS路徑

原作者:Tesla.Angela

連結:http://www.m5home.com/bbs/thread-8896-1-1.html

眾所周知在FILE_OBJECT.FileName的路徑是不帶碟符的,於是網上各種QUICK AND DIRTY的程式碼就乾脆直接從FileName裡取得“無頭路徑”。
這種噁心的做法自然是要不得的,現在分享一下從這個結構體裡取完整路徑的方法。區區40行程式碼(還包括空行和註釋),即可支援XP到WIN10。

本帖隱藏的內容

  1. //通過FILE_OBJECT拿到檔名
  2. BOOLEAN QueryFileObjectNtName(PFILE_OBJECT pFileObject, PWCHAR *OutputBufferFreeByCaller)
  3. {
  4.         NTSTATUS status;
  5.         ULONG returnedLength;
  6.         BOOLEAN foundCompleteName = FALSE;
  7.         PUNICODE_STRING pObjectName = NULL;
  8.         status = ObQueryNameString(pFileObject, (POBJECT_NAME_INFORMATION)pObjectName, 0, &returnedLength );
  9.         if(status == STATUS_INFO_LENGTH_MISMATCH)
  10.         {
  11.                 pObjectName = ExAllocatePoolWithTag(PagedPool, returnedLength, 'XXOO');
  12.                 status = ObQueryNameString(pFileObject, (POBJECT_NAME_INFORMATION)pObjectName, returnedLength, &returnedLength );
  13.                 if(NT_SUCCESS(status))
  14.                 {
  15.                         *OutputBufferFreeByCaller = ExAllocatePool(PagedPool,pObjectName->Length+2);
  16.                         RtlZeroMemory(*OutputBufferFreeByCaller,pObjectName->Length+2);
  17.                         memcpy(*OutputBufferFreeByCaller,pObjectName->Buffer,pObjectName->Length);
  18.                         foundCompleteName = TRUE;
  19.                 }
  20.                 ExFreePoolWithTag(pObjectName, 'XXOO');
  21.         }
  22.         return foundCompleteName;
  23. }

  24. //通過FILE_OBJECT拿到檔名
  25. BOOLEAN QueryFileObjectDosName(PFILE_OBJECT pFileObject, PWCHAR *OutputBufferFreeByCaller)
  26. {
  27.         UNICODE_STRING volumeDosName = {0};
  28.         //初始化輸出路徑
  29.         *OutputBufferFreeByCaller = ExAllocatePool(PagedPool, pFileObject->FileName.Length+32);
  30.         RtlZeroMemory(*OutputBufferFreeByCaller, pFileObject->FileName.Length+32);
  31.         //取得碟符DOS名
  32.         RtlInitEmptyUnicodeString(&volumeDosName,NULL,0);
  33.         if(!NT_SUCCESS(IoVolumeDeviceToDosName(pFileObject->DeviceObject, &volumeDosName)))
  34.                 return FALSE;
  35.         memcpy(*OutputBufferFreeByCaller, volumeDosName.Buffer, volumeDosName.Length);
  36.         //連線檔名
  37.         memcpy((PUCHAR)*OutputBufferFreeByCaller + volumeDosName.Length, pFileObject->FileName.Buffer, pFileObject->FileName.Length);
  38.         return TRUE;
  39. }
複製程式碼
不知道啥時候這段程式碼會出現在某些“大牛”的工程裡然後標為“原創”。哈哈。



最後補充一下:這個pFileObject 的獲取

可以看我的另一篇文章

NT5/NT6上的獲取程序全路徑

http://blog.csdn.net/zhuhuibeishadiao/article/details/51136650  

也可以參考以下連結 第八個男人 很難訪問 趕緊備份下

連結:http://www.debugman.com/archiver/tid/4223 (我的第八個男人啊~~~)

論壇 ›  Native Code 綜合討論 › EPROCESS獲取FileObject

JeTus 發表於 2010-1-2 13:44:07

EPROCESS獲取FileObject

1,通過PsGetCurrentProcess獲取EPROCESS,EPROCESS->SectionObject->Segment->ControlArea->FileObject,不過貌似wdk的EPROCESS被定義成了KPROCESS,這個EPROCESS的結構就不一樣了;
2,通過獲取process的Handle,然後呼叫ObReferenceObjectByHandle, ObjectType 填寫IoFileObjectType,然後獲取其FileObject;

目前只想到上面兩種方法,不知道還有沒有其他更簡單點的辦法。
PS:用的框架是檔案過濾驅動。

先謝謝了

JeTus 發表於 2010-1-2 14:18:26

寫了驗證一下,第二個方法好像行不通,不知道是不是process的handle不能用IoFileObjectType來獲取FileObject。
第一個方法因為沒有wdk定義的結構體,暫時不想使用哪個方法。

MJ0011 發表於 2010-1-2 15:05:29

ZwQueryInformationProcess, ZwCreateFile , ObReferenceObjectByHandle

JeTus 發表於 2010-1-2 16:49:20

謝謝MJ。
網上找的一段程式碼,貼出來留給後面的同學看看。

// 注: 當函式返回TRUE時,引數pImageName所指向的 PANSI_STRING 物件需要用RtlFreeAnsiString()釋放。

// 否則,標記為 "Strg" 的記憶體池會產生洩露。

typedef NTSTATUS (*QUERY_INFO_PROCESS) (
    __in HANDLE ProcessHandle,
    __in PROCESSINFOCLASS ProcessInformationClass,
    __out_bcount(ProcessInformationLength) PVOID ProcessInformation,
    __in ULONG ProcessInformationLength,
    __out_opt PULONG ReturnLength
    ); 

QUERY_INFO_PROCESS ZwQueryInformationProcess;


#define ProcessImageFileName 27

BOOLEAN GetProcessImageName(PANSI_STRING pImageName)
{
    KIRQL        CurIRQL ;
    NTSTATUS     status;
    ULONG        returnedLength;
    ULONG        bufferLength;
    PVOID        buffer;
    PUNICODE_STRING imageName;
    BOOLEAN      bRet = FALSE ;
    
    PAGED_CODE(); // this eliminates the possibility of the IDLE Thread/Process

    CurIRQL = KeGetCurrentIrql() ;
    DbgPrint ("Current IRQL is %d\\r\\n", CurIRQL) ;
    if (PASSIVE_LEVEL != CurIRQL)
    {   
        return FALSE ;
    }

    try
    {
        if ( ! MmIsAddressValid (pImageName))
        {
            return FALSE ;
        }

        pImageName->Length = 0 ;
        pImageName->MaximumLength = 0 ;
        pImageName->Buffer = NULL ;
    }
    except (EXCEPTION_EXECUTE_HANDLER)
    {
        return FALSE ;
    }

    if (NULL == ZwQueryInformationProcess) {

        UNICODE_STRING routineName;

        RtlInitUnicodeString(&routineName, L"ZwQueryInformationProcess");

        ZwQueryInformationProcess = 
               (QUERY_INFO_PROCESS) MmGetSystemRoutineAddress(&routineName);

        if (NULL == ZwQueryInformationProcess) {

            DbgPrint("Cannot resolve ZwQueryInformationProcess\\n");
            return FALSE ;
        }
    }
    //
    // Step one - get the size we need
    //
    status = ZwQueryInformationProcess( NtCurrentProcess(), 
                                        ProcessImageFileName,
                                        NULL, // buffer
                                        0, // buffer size
                                        &returnedLength);

    if (STATUS_INFO_LENGTH_MISMATCH != status) {

        return FALSE;

    }

    //
    // Is the passed-in buffer going to be big enough for us?  
    // This function returns a single contguous buffer model...
    //
    bufferLength = returnedLength - sizeof(UNICODE_STRING);

    //
    // If we get here, the buffer IS going to be big enough for us, so 
    // let's allocate some storage.
    //
    buffer = ExAllocatePoolWithTag(PagedPool, returnedLength, 'ipgD');

    if (NULL == buffer) {
        return FALSE ;        
    }

    try
    {
        //
        // Now lets go get the data
        //
        status = ZwQueryInformationProcess( NtCurrentProcess(), 
                    ProcessImageFileName,
                    buffer,
                    returnedLength,
                    &returnedLength);

        if (NT_SUCCESS(status)) {
            //
            // Ah, we got what we needed
            //
            imageName = (PUNICODE_STRING) buffer;

            //       RtlCopyUnicodeString(ProcessImageName, imageName);
            //RtlZeroMemory (pBuffer, cbBuffer) ;
            //if (((size_t)-1) != wcstombs (pBuffer, imageName->Buffer, cbBuffer))
            //{
            // bRet = TRUE ;
            //}

            //KdPrint (("Current ProcessImageFileName: \\"%s\\"\\r\\n", pBuffer)) ;

            if (STATUS_SUCCESS != RtlUnicodeStringToAnsiString (pImageName, imageName, TRUE))
            {
                bRet = FALSE ;
                KdPrint (("Current ProcessImageFileName: Unknow\\r\\n")) ;
            }
            else
            {
                bRet = TRUE ;
                KdPrint (("Current ProcessImageFileName: \\"%s\\"\\r\\n", pImageName->Buffer)) ;
            }
        }
    }
    except (EXCEPTION_EXECUTE_HANDLER)
    {
        bRet = FALSE ;
    }

    //
    // free our buffer
    //

    ExFreePool(buffer);

    //
    // And tell the caller what happened.
    //    
    return bRet ;    
}