Получение BSOD После При Попытке Напечатать Имя Следующего Процесса В Списке LIST_ENTRY

#c #c #winapi #driver #winappdriver

Вопрос:

Я пытаюсь напечатать следующее имя процесса после моего процесса в LIST_ENTRY списке. Но я всегда получаю BSOD.

 #include <Ntifs.h>
#include <ntddk.h>
#include <WinDef.h>

void SampleUnload(_In_ PDRIVER_OBJECT DriverObject) {

    UNREFERENCED_PARAMETER(DriverObject);
    DbgPrint("Sample driver Unload calledn");
}


extern "C"
NTSTATUS
DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) {
    UNREFERENCED_PARAMETER(RegistryPath);
    DriverObject->DriverUnload = SampleUnload;
    DbgPrint("Sample driver Load calledn");

    PEPROCESS EP;
    if (::PsLookupProcessByProcessId(::PsGetCurrentProcessId(), amp;EP) == STATUS_INVALID_PARAMETER) {
        DbgPrint("Can't get EPROCESS");
        return STATUS_INVALID_PARAMETER;
    }

    LIST_ENTRY list_entry = *((LIST_ENTRY*)(LPBYTE)EP   0x448);
    UCHAR* fileName;
    fileName = ((UCHAR*)(LPBYTE)list_entry.Flink - 0x448   0x5a8);

    for (int i = 0; i < 15; i  )
        DbgPrint("%u" , fileName[i]);

    DbgPrint("Finish");

    return STATUS_SUCCESS;
}
 

В EPROCESS структуре есть LIST_ENTRY объект в 0x448 смещении.
Поэтому я создал LIST_ENTRY объект и назначил ему адрес EPROCESS 0x448 , а затем добавил 0x5a8-0x448 к LIST_ENTRY.FLINK нему .
Это предполагает попадание в ImageFileName массив в 0x5a8 смещении.

Но по какой-то причине это не работает.

Комментарии:

1. Какая строка кода запускает BSOD?

2. Я не знаю, я очень хорошо разбираюсь в мире водителей. Как я могу проверить?

3. Используйте отладчик ядра — docs.microsoft.com/en-us/windows-hardware/drivers/debugger/…

4. *((LIST_ENTRY*)(LPBYTE)EP 0x448); Вы можете попытаться добавить несколько скобок вокруг (LPBYTE)EP 0x448 , чтобы убедиться, что арифметика указателей выполнена до приведения к LIST_ENTRY*

5. Теперь я получаю защищенную систему в ascii. как я могу преобразовать это в строку?

Ответ №1:

У вас есть несколько бессмысленных приведений в коде:

 *((LIST_ENTRY*)(LPBYTE)EP   0x448);
 

и

 ((UCHAR*)(LPBYTE)list_entry.Flink - 0x448   0x5a8);
 

Это означает, например, преобразование EP (а не его адрес) в байтовый указатель, а затем (поскольку приведения имеют ассоциативность справа налево) немедленно забудьте о преобразовании в байтовый указатель и вместо этого преобразуйте в a LIST_ENTRY* . Затем, когда вы закончите колебаться, какой тип использовать, выполните арифметику указателей на LIST_ENTRY объекты. Это 0x448 * sizeof(LIST_ENTRY) байты.

Я думаю, ты действительно хотел это сделать:

 LPBYTE lpb = (LPBYTE)amp;EP   0x448;
LIST_ENTRY list_entry = *(LIST_ENTRY*)lpb;
 

Хотя, возможно, это ошибка с нарушением строгого сглаживания. Или ошибка выравнивания.

Комментарии:

1. только (LPBYTE)EP 0x448 без amp; . это, конечно, не имеет никакого отношения к «строгому нарушению псевдонимов», но весь рассматриваемый код бессмыслен и полон ошибок

2.@тантан 1 PsLookupProcessByProcessId(::PsGetCurrentProcessId()) — бессмысленно. используйте PsGetCurrentProcess 2 проверка ошибок на наличие PsLookupProcessByProcessId ошибок 3 ObfDereferenceObject(EP) не вызывается 4 используйте жестко закодированные смещения всегда неправильно

3. Эй, @RbMm , как я могу избежать использования жестко закодированных смещений?