How to use ZwQueryInformationProcess to get ProcessImageFileName in a kernel driver?

后端 未结 3 707
忘掉有多难
忘掉有多难 2021-02-14 07:57

I\'m writing a simple kernel driver for my application (think of a very simple anti-malware application.)

I\'ve hooked ZwOpenFile() and used PsGetCurr

3条回答
  •  长情又很酷
    2021-02-14 08:37

    //Declare this piece of code in header file if available otherwise before the Function definition..

    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;
    

    //Function Definition

    NTSTATUS GetProcessImageName(HANDLE processId, PUNICODE_STRING ProcessImageName)
    {
    NTSTATUS status;
    ULONG returnedLength;
    ULONG bufferLength;
    HANDLE hProcess;
    PVOID buffer;
    PEPROCESS eProcess;
    PUNICODE_STRING imageName;
    
    PAGED_CODE(); // this eliminates the possibility of the IDLE Thread/Process
    
    status = PsLookupProcessByProcessId(processId, &eProcess);
    
    if(NT_SUCCESS(status))
    {
        status = ObOpenObjectByPointer(eProcess,0, NULL, 0,0,KernelMode,&hProcess);
        if(NT_SUCCESS(status))
        {
        } else {
            DbgPrint("ObOpenObjectByPointer Failed: %08x\n", status);
        }
        ObDereferenceObject(eProcess);
    } else {
        DbgPrint("PsLookupProcessByProcessId Failed: %08x\n", status);
    }
    
    
    if (NULL == ZwQueryInformationProcess) {
    
        UNICODE_STRING routineName;
    
        RtlInitUnicodeString(&routineName, L"ZwQueryInformationProcess");
    
        ZwQueryInformationProcess =
               (QUERY_INFO_PROCESS) MmGetSystemRoutineAddress(&routineName);
    
        if (NULL == ZwQueryInformationProcess) {
            DbgPrint("Cannot resolve ZwQueryInformationProcess\n");
        }
    }
    
    /* Query the actual size of the process path */
    status = ZwQueryInformationProcess( hProcess,
                                        ProcessImageFileName,
                                        NULL, // buffer
                                        0, // buffer size
                                        &returnedLength);
    
    if (STATUS_INFO_LENGTH_MISMATCH != status) {
        return status;
    }
    
    /* Check there is enough space to store the actual process
       path when it is found. If not return an error with the
       required size */
    bufferLength = returnedLength - sizeof(UNICODE_STRING);
    if (ProcessImageName->MaximumLength < bufferLength)
    {
        ProcessImageName->MaximumLength = (USHORT) bufferLength;
        return STATUS_BUFFER_OVERFLOW;   
    }
    
    /* Allocate a temporary buffer to store the path name */
    buffer = ExAllocatePoolWithTag(NonPagedPool, returnedLength, 'uLT1');
    
    if (NULL == buffer) 
    {
        return STATUS_INSUFFICIENT_RESOURCES;   
    }
    
    /* Retrieve the process path from the handle to the process */
    status = ZwQueryInformationProcess( hProcess,
                                        ProcessImageFileName,
                                        buffer,
                                        returnedLength,
                                        &returnedLength);
    
    if (NT_SUCCESS(status)) 
    {
        /* Copy the path name */
        imageName = (PUNICODE_STRING) buffer;
        RtlCopyUnicodeString(ProcessImageName, imageName);
    }
    
    /* Free the temp buffer which stored the path */
    ExFreePoolWithTag(buffer, 'uLT1');
    
    return status;
    }
    

    //Function Call.. Write this piece of code in PreOperation Call back and IRQ should be PASSIVE_LEVEL

    PEPROCESS objCurProcess=NULL;
    HANDLE hProcess;
    UNICODE_STRING fullPath;
    
    objCurProcess=IoThreadToProcess(Data->Thread);//Note: Date is type of FLT_CALLBACK_DATA which is in PreOperation Callback as argument
    
    hProcess=PsGetProcessID(objCurProcess);
    
    fullPath.Length=0;
    fullPath.MaximumLength=520;
    fullPath.Buffer=(PWSTR)ExAllocatePoolWithTag(NonPagedPool,520,'uUT1');
    
    GetProcessImageName(hProcess,&fullPath);
    

    in fullPath variable there is Full Path of Process .. Like if the process is explorer.exe then path will be look like this:-

    \Device\HarddiskVolume3\Windows\explorer.exe
    

    Note:- \Device\HarddiskVolume3 Path might be changed due to Machine and different volume in hard disk this is an example in my case.

提交回复
热议问题