Как получить имя образа модуля с произвольного адреса в пространстве ядра Windows? - PullRequest
0 голосов
/ 02 июля 2018

Я пытаюсь понять, как я могу получить имя загруженного модуля по произвольному адресу из кода ядра.

В пользовательском режиме я бы сделал это:

void* pAddr;
VOID* pBase;
WCHAR buff[MAX_PATH] = {0};

//Get address of some function in some module (just to test it)
pAddr = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetCurrentProcess");

//Get module base address
RtlPcToFileHeader(pAddr, &pBase);

//Get module image file name
GetModuleFileNameEx(GetCurrentProcess(), (HMODULE)pBase, buff, SIZEOF(buff));

Есть ли способ сделать то же самое в режиме ядра, если у меня есть pAddr, который может указывать на какой-либо адрес в пространстве ядра или пользователя?


РЕДАКТИРОВАТЬ: В ожидании ответа я придумал свой собственный код (используя недокументированный способ обхода PEB):

#ifdef CALLING_FROM_KERNEL_MODE
//Kernel mode
TEB* pTEB = (TEB*)PsGetCurrentThreadTeb();

#else
//User mode

#if defined(_M_X64)
//64-bit
TEB* pTEB = reinterpret_cast<TEB*>(__readgsqword(reinterpret_cast<DWORD_PTR>(&static_cast<NT_TIB*>(nullptr)->Self)));
#else
//32-bit
TEB* pTEB = reinterpret_cast<TEB*>(__readfsdword(reinterpret_cast<DWORD_PTR>(&static_cast<NT_TIB*>(nullptr)->Self)));
#endif

#endif

PEB* p_PEB = pTEB->ProcessEnvironmentBlock;
PEB_LDR_DATA* pPLD = p_PEB->Ldr;

const WCHAR* pModName = NULL;

LIST_ENTRY* pLE = &pPLD->InMemoryOrderModuleList;
LIST_ENTRY* pLE_Head = pLE;
while(pLE_Head != pLE->Flink)
{
    PLDR_DATA_TABLE_ENTRY pLDTE = CONTAINING_RECORD(pLE, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);

    size_t szcbSizeOfImg = (size_t)pLDTE->Reserved3[1];
    if((size_t)pAddr - (size_t)pLDTE->DllBase < szcbSizeOfImg)
    {
        pModName = pLDTE->FullDllName.Buffer;

        break;
    }

    pLE = pLE->Flink;
}

Проблема в том, что, хотя он работает из пользовательского режима, из режима ядра PsGetCurrentThreadTeb(), похоже, возвращает NULL. Означает ли это, что потоки ядра не имеют TEB?

1 Ответ

0 голосов
/ 02 июля 2018

это можно сделать, создав список всех загруженных модулей через ZwQuerySystemInformation с SystemModuleInformation

void fgt(PVOID *Callers, ULONG Count)
{
    NTSTATUS status;

    ULONG cb = 0x10000;
    do 
    {
        status = STATUS_INSUFFICIENT_RESOURCES;

        if (PRTL_PROCESS_MODULES prpm = (PRTL_PROCESS_MODULES)ExAllocatePool(PagedPool, cb))
        {
            if (0 <= (status = NtQuerySystemInformation(SystemModuleInformation, prpm, cb, &cb)))
            {
                do 
                {
                    PVOID Caller = *Callers++;

                    if (ULONG NumberOfModules = prpm->NumberOfModules)
                    {
                        PRTL_PROCESS_MODULE_INFORMATION Modules = prpm->Modules;

                        do 
                        {
                            if ((SIZE_T)Caller - (SIZE_T)Modules->ImageBase < Modules->ImageSize)
                            {
                                DbgPrint("%p> %s\n", Caller, Modules->FullPathName);
                                break;
                            }
                        } while (Modules++, --NumberOfModules);
                    }

                } while (--Count);
            }
            ExFreePool(prpm);
        }

    } while (status == STATUS_INFO_LENGTH_MISMATCH);
}
...