我有一个 64 位进程需要读取 Wow64 进程的 32 位 PEB。
我可以使用NtQueryInformationProcess,但我意识到 Wow64 进程有两个 PEB(64 位和 32 位)并NtQueryInformationProcess返回与调用者的位数(在我的情况下为64 位)相对应的 PEB,正如@Anders 在此解决方案中所评论的:
这就是我的场景:我试图从 x64 进程内部获取 Wow64 进程的 32 位 PEB。任何涉及改变该场景的建议都是无用的。我也知道这种解决方案不推荐用于生产,这不是我的意图。
有任何想法吗?
提前致谢。
如果您阅读NtQueryInterformationProcess()MSDN 上的文档,有一条评论说:
似乎在(至少)Windows Vista 中查询在 wow64 下运行的进程时,返回的 PebBaseAddress 实际上是针对在 wow64 下加载的 64 位模块。根据我所做的一些初步调查,似乎可以通过获取 PebBaseAddress 并从其 value 中减去一页 (0x1000) 来找到与 32 位模块有关的 PEB。我通过检查进程的 TIB 并跟随它们的 PEB 指针返回到一个地址,到目前为止,该地址始终显示为 -0x1000(与此函数返回的 PebBaseAddress 值相比),从而最低限度地证实了这一假设。
更新:我刚刚发现这段代码表明上述内容从 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;
}
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4224 次 |
| 最近记录: |