C++ 从x64进程获取另一进程的32位PEB

C++ 从x64进程获取另一进程的32位PEB,c++,winapi,C++,Winapi,我有一个64位进程,需要读取Wow64进程的32位PEB 我可以通过NtQueryInformationProcess获得它,但我意识到Wow64进程有两个PEB(64位和32位),并且NtQueryInformationProcess返回与调用者的位对应的PEB(在我的例子中是64位),正如@Anders在这个解决方案中所评论的: #define TEB32OFFSET 0x2000 void interceptNtDll32(HANDLE hProcess) { THREAD_BA

我有一个64位进程,需要读取Wow64进程的32位PEB

我可以通过
NtQueryInformationProcess
获得它,但我意识到Wow64进程有两个PEB(64位和32位),并且
NtQueryInformationProcess
返回与调用者的位对应的PEB(在我的例子中是64位),正如@Anders在这个解决方案中所评论的:

#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;
    }

    ...

这就是我的场景:我试图从x64进程内部获取Wow64进程的32位PEB。任何涉及改变这种情况的建议都是无用的。我也知道,这种解决方案不推荐用于生产,这不是我的意图

有什么想法吗

提前感谢。

如果您阅读了MSDN上的文档,会有一条评论说:

似乎在(至少)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;
    }

    ...
这也是我发现的:我刚刚在Windows10中测试并确认第一个(PEB64-0x1000)不起作用。我正在尝试你提到的代码。谢谢