Как использовать ZwQueryInformationProcess для получения ProcessImageFileName в драйвере ядра? - PullRequest
9 голосов
/ 14 сентября 2010

Я пишу простой драйвер ядра для своего приложения (представьте себе очень простое приложение для защиты от вредоносных программ).

Я подключил ZwOpenFile() и использовал PsGetCurrentProcess(), чтобы получить указатель навызывающий процесс.

Возвращает структуру PEPROCESS:

PEPROCESS proc = PsGetCurrentProcess();

Я использую ZwQueryInformationProcess(), чтобы получить PID и ImageFileName:

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

и пытаюсь получить процесс FullPath таким образом (но я получаю 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);

DbgView Output

Как видите, str.Buffer пусто или заполнено мусором.Возможно переполнение буфера при заполнении str через ZwQueryInformationProcess() вызывает BSOD.

alt text

Любая помощь приветствуется.

Ответы [ 3 ]

6 голосов
/ 14 сентября 2010

Документы MSDN для этого API указывают, что

Когда параметром ProcessInformationClass является ProcessImageFileName, буфер, на который указывает параметр ProcessInformation, должен быть достаточно большим, чтобы содержать структуру UNICODE_STRING, а также саму строку,Строка, хранящаяся в элементе Buffer, является именем файла file.file.

Учитывая это, я предлагаю вам попробовать изменить структуру буфера следующим образом:

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);

Кроме того, ваш код должен проверять и обрабатывать ошибки, описанные в документации здесь.Это может быть причиной того, что вы пропустили случай триггера BSOD.

Если буфер слишком маленький, функция завершается ошибкой с кодом ошибки STATUS_INFO_LENGTH_MISMATCH, а для параметра ReturnLength задан требуемый размер буфера.

2 голосов
/ 09 ноября 2016

// Объявляем этот фрагмент кода в заголовочном файле, если он доступен, перед определением функции.

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;

// Определение функции

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;
}

// Вызов функции. Запишите этот фрагмент кода в PreOperation Callback, и IRQ должен быть 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);

в переменной fullPath указан полный путь процесса. Например, если процесс представляет собой explorer.exe, путь будет выглядеть следующим образом: -

\Device\HarddiskVolume3\Windows\explorer.exe

Примечание: - \ Device \ HarddiskVolume3 Путь может быть изменен из-за компьютера и другого тома на жестком диске, это пример в моем случае.

0 голосов
/ 26 мая 2014

ZwQueryInformationProcess нужен HANDLE, а не PROCESS!Вы должны использовать ObOpenObjectByPointer, чтобы сначала получить ручку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...