C 如何从Windows内核空间中的任意地址获取模块映像名?
我试图了解如何从内核代码的任意地址获取加载的模块映像名 在用户模式下,我将执行以下操作:C 如何从Windows内核空间中的任意地址获取模块映像名?,c,windows,kernel,portable-executable,C,Windows,Kernel,Portable Executable,我试图了解如何从内核代码的任意地址获取加载的模块映像名 在用户模式下,我将执行以下操作: 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
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?这可以通过ZwQuerySystemInformation和SystemModuleInformation创建所有已加载模块的列表来实现
ZWQUERYSYSYSTEMINFORMATION或Nt*依赖于前面的模式和系统模块信息,并通过RTL_进程_模块在您称之为它的线程上进行迭代?内核模式线程没有TEB。它是0。所以我假设您在内核模式的上下文中调用它thread@RbMm是的,内核模式。那么PEB呢?还有一个附带问题。如果没有TEB,为什么会有nt!PsGetCurrentThreadTeb函数?因为PsGetCurrentThreadTeb返回当前线程的TEB值。这里有什么不清楚的?那么PEB呢关于什么过程?看起来你不明白。我的意思是在你所说的线程的上下文中。不是从内核或用户模式。仅存在内核模式线程。存在用户模式线程。谢谢!顺便说一句,这是一种在循环中进行内存分配的非常聪明的方法。您的方法非常适合检索所有加载的驱动程序。我还考虑对内核模式代码的用户模式地址做同样的处理。在等待的时候,我正在研究自己的方法。我把它贴在上面的问题上。你知道我为什么会在那里得到一个空的teb吗?顺便说一句,上面代码中没有记录的结构。
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);
}