Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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

I've hooked ZwOpenFile() and used PsGetCurrentProcess() to get a handle to the caller process.

It returns a PEPROCESS structure:

PEPROCESS proc = PsGetCurrentProcess();

I'm using ZwQueryInformationProcess() to get the PID and ImageFileName:

DbgPrint("ZwOpenFile Called...\n");
DbgPrint("PID: %d\n", PsGetProcessId(proc));
DbgPrint("ImageFileName: %.16s\n", PsGetProcessImageFileName(proc));

and trying to get the process FullPath this way (but I get BSOD):

WCHAR strBuffer[260];
UNICODE_STRING str;
//initialize
str.Buffer = strBuffer;
str.Length = 0x0;
str.MaximumLength = sizeof(strBuffer);
//note that the seconds arg (27) is ProcessImageFileName
ZwQueryInformationProcess(proc, 27, &str, sizeof(str), NULL);
DbgPrint("FullPath: %wZ\n", str.Buffer);
  

When the ProcessInformationClass parameter is ProcessImageFileName, the buffer pointed to by the ProcessInformation parameter should be large enough to hold a UNICODE_STRING structure as well as the string itself. The string stored in the Buffer member is the name of the image file.file.

With this in mind, I suggest you try modifying your buffer structure like this:

WCHAR strBuffer[(sizeof(UNICODE_STRING) / sizeof(WCHAR)) + 260];
UNICODE_STRING str;
str = (UNICODE_STRING*)&strBuffer;
//initialize
str.Buffer = &strBuffer[sizeof(UNICODE_STRING) / sizeof(WCHAR)];
str.Length = 0x0;
str.MaximumLength = 260 * sizeof(WCHAR);
//note that the seconds arg (27) is ProcessImageFileName
ZwQueryInformationProcess(proc, 27, &strBuffer, sizeof(strBuffer), NULL);

Additionally, your code needs to check and handle the error case described in the docs here. This may be why you missed the BSOD trigger case.

If the buffer is too small, the function fails with the STATUS_INFO_LENGTH_MISMATCH error code and the ReturnLength parameter is set to the required buffer size.

//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.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.