简体   繁体   English

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

[英]Get 32bit PEB of another process from a x64 process

I have a 64 bit process that needs to read the 32bit PEB of a Wow64 process. 我有一个64位进程,需要读取Wow64进程的32位PEB。

I'm able to get it with NtQueryInformationProcess , but I realized that Wow64 processes have two PEBs (64 and 32 bit) and NtQueryInformationProcess returns the PEB corresponding to the bitness of the caller (64bit in my case), as @Anders commented in this solution: 我可以使用NtQueryInformationProcess来获取它,但是我意识到Wow64进程具有两个PEB(64位和32位),并且NtQueryInformationProcess返回与调用者的位数(在我的情况下为64bit)相对应的PEB,如@Anders所述。解:

How to get the Process Environment Block (PEB) from extern process? 如何从外部流程中获取流程环境块(PEB)?

That's my scenario: I'm trying to get the 32bit PEB of a Wow64 process, from inside a x64 process. 这就是我的情况:我正在尝试从x64进程内部获取Wow64进程的32位PEB。 Any suggestions that involve changing that scenario are useless. 任何涉及改变这种情况的建议都是没有用的。 I'm also aware that this kind of solution is not recommended for production and that's not my intention. 我也知道,不建议将这种解决方案用于生产环境,这不是我的意图。

Any ideas? 有任何想法吗?

Thanks in advance. 提前致谢。

If you read the NtQueryInterformationProcess() documentation on MSDN, there is a comment that says: 如果您阅读了MSDN上的NtQueryInterformationProcess()文档,则会有一条注释:

It appears that when querying a process running under wow64 in (at least) windows Vista the PebBaseAddress returned is actually for the 64-bit modules loaded under wow64. 看起来, 当查询(至少)在Windows Vista中在wow64下运行的进程时,返回的PebBaseAddress实际上是针对在wow64下加载的64位模块的。 From some initial investigations I've done it appears that the PEB which pertains to 32-bit modules can be found by taking the PebBaseAddress and subtracting one page (0x1000) from its value . 从一些初步的研究中,我似乎发现可以通过获取PebBaseAddress并从其值中减去一页(0x1000)来找到与32位模块有关的PEB I have minimally confirmed this hypothesis by inspecting the process's TIB's and following their PEB pointers back to an address which, so far, has always shown to be -0x1000 from the PebBaseAddress value returned by this function. 我已经通过检查进程的TIB并遵循其PEB指针返回到一个地址(到目前为止,从此函数返回的PebBaseAddress值始终显示为-0x1000)来最小化了这一假设。

Update: I just found this code that states the above will not work from Windows 8 onwards, but does provide an alternative solution: 更新:我刚刚发现这段代码 ,指出以上内容从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;
    }

    ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM