我有一个64位进程,需要读取Wow64进程的32位PEB。
我可以用NtQueryInformationProcess
得到它,但我意识到Wow64进程有两个PEB(64和32位),NtQueryInformationProcess
返回与调用方的位(在我的情况下是64位)相对应的PEB,正如@Anders在这个解决方案中评论的那样:
如何从外部流程中获取流程环境块(PEB)?
这就是我的场景:我试图从x64进程内部获得Wow64进程的32位PEB。任何涉及改变这种情况的建议都是无用的。我也知道这种解决方案不建议用于生产,这不是我的本意。
有什么想法吗?
提前谢谢。
如果您阅读MSDN上的NtQueryInterformationProcess()
文档,会有一条注释:
看起来在(至少)windows Vista中查询在wow64下运行的进程时,返回的PebBaseAddress实际上是在wow64下加载的64位模块。根据我所做的一些初步调查,似乎可以通过获取PebBaseAddress并从其值中减去一页(0x1000)来找到属于32位模块的PEB。我通过检查进程的TIB并跟随它们的PEB指针返回到一个地址来最低限度地证实了这一假设,到目前为止,该地址始终显示为该函数返回的PebBaseAddress值的0x1000。
更新:我刚刚发现了这段代码,该代码指出,从Windows 8以后,上述内容将不起作用,但它确实提供了一个替代解决方案:
#define TEB32OFFSET 0x2000
void interceptNtDll32(HANDLE hProcess)
{
THREAD_BASIC_INFORMATION tbi;
NTSTATUS ntrv;
TEB32 teb32;
void *teb32addr;
PEB_LDR_DATA32 ldrData;
PEB32 peb32;
LIST_ENTRY32 *pMark = NULL;
LDR_DATA_TABLE_ENTRY32 ldrDataTblEntry;
size_t bytes_read;
HANDLE hThread = getThreadHandle(hProcess);
/* Used to be able to get 32 bit PEB from PEB64 with 0x1000 offset but
Windows 8 changed that so we do it indirectly from the TEB */
if(!hThread)
return;
/* Get thread basic information to get 64 bit TEB */
ntrv = NtQueryInformationThread(hThread, ThreadBasicInformation, &tbi, sizeof(tbi), NULL);
if(ntrv != 0){
goto out;
}
/* Use magic to find 32 bit TEB */
teb32addr = (char *)tbi.TebBaseAddress + TEB32OFFSET; // Magic...
ntrv = NtReadVirtualMemory(hProcess, teb32addr, &teb32, sizeof(teb32), NULL);
if(ntrv != 0 || teb32.NtTib.Self != (DWORD)teb32addr){ // Verify magic...
goto out;
}
/* TEB32 has address for 32 bit PEB.*/
ntrv = NtReadVirtualMemory(hProcess, (void *)teb32.ProcessEnvironmentBlock, &peb32, sizeof(peb32), NULL);
if(ntrv != 0){
goto out;
}
...
您可以使用NtQueryInformationProcess
参见https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess#ulong_ptr
将ProcessInformationClass设置为ProcessWow64Information
设置一个指针以接收ProcessInformation的值
当调用api时,ProcessInformation的值将是wow64进程的pebBaseAddr,如果它不是零