如何使用汇编程序(x64 OS)获取进程环境块(PEB)地址?

Posted

技术标签:

【中文标题】如何使用汇编程序(x64 OS)获取进程环境块(PEB)地址?【英文标题】:How to get the Process Environment Block (PEB) address using assembler (x64 OS)? 【发布时间】:2016-05-18 00:26:42 【问题描述】:

我正在尝试使用汇编程序获取当前进程的 PEB 地址。

cpp 文件:

#include <iostream>
//#include <windows.h>

extern "C" int* __ptr64 Get_Ldr_Addr();

int main(int argc, char **argv)

    std::cout << "asm     " << Get_Ldr_Addr() << "\n";
    //std::cout <<"peb     "<< GetModuleHandle(0) << "\n";

    return 0;

asm 文件:

.code

Get_Ldr_Addr proc
    push rax
    mov rax, GS:[30h]
    mov rax, [rax + 60h]
    pop rax
    ret
Get_Ldr_Addr endp

end

但我从 GetModuleHandle(0) 和 Get_Ldr_Addr() 得到不同的地址!

有什么问题?不应该是一样的吗?

问:如果函数是外部的,它会检查调用它的进程或函数的dll(假设是dll)的PEB?

Tnx

【问题讨论】:

你把你的返回值放在哪里?显然你正在将它加载到 RAX 中,但随后它被 pop 覆盖。检查您应该如何返回 ABI 中的值。 我删除了推送/弹出。这是根据某些指令返回值的方法。 deviorel.wordpress.com/2015/01/19/… 获得指向任何进程的PEB 的指针的另一种方法是使用NtQueryInformationProcess(): "ProcessInformationClass 参数为@987654329 @,ProcessInformation 参数指向的缓冲区应该足够大以容纳单个PROCESS_BASIC_INFORMATION 结构... [其] PebBaseAddress 成员指向PEB 结构。" 有关处理 32 位与 64 位 PEB 和 Windows 8+(更改 32 位 PEB 的位置)的更多详细信息,请参阅 How to get the Process Environment Block (PEB) from extern process?。 不知道你是如何得到GetModuleHandle返回PEB的印象。 【参考方案1】:

如果您不介意 C. 在 Microsoft Visual Studio 2015 中工作。 使用“__readgsqword()”内在函数。

#include <winnt.h>
#include <winternl.h>

// Thread Environment Block (TEB)
#if defined(_M_X64) // x64
PTEB tebPtr = reinterpret_cast<PTEB>(__readgsqword(reinterpret_cast<DWORD_PTR>(&static_cast<NT_TIB*>(nullptr)->Self)));
#else // x86
PTEB tebPtr = reinterpret_cast<PTEB>(__readfsdword(reinterpret_cast<DWORD_PTR>(&static_cast<NT_TIB*>(nullptr)->Self)));
#endif

// Process Environment Block (PEB)
PPEB pebPtr = tebPtr->ProcessEnvironmentBlock;

【讨论】:

【参考方案2】:

只有两个厘米。

无需推送/弹出rax,因为它是 Windows 上的临时寄存器或易失性寄存器,请参阅caller/callee saved registers。特别是,rax 将保存您的函数的返回值。

当您调用GetModuleHandle() 并将其与您自己的汇编代码进行比较时,单步执行机器代码通常会有所帮助。您可能会遇到类似this implementation 的内容。

【讨论】:

我现在去看看。 tnx 我正在尝试做同样的事情,但对于 x64。但是 VS 不允许/支持 x64 汇编器,所以我把它放在不同的文件(.asm)中。也许PEB地址和处理程序地址不同? x86 和 x64 的 gs/fs 结构的格式不同(部分反映了指针大小不同的事实)。【参考方案3】:

Get_Ldr_Addr 没有保存您的结果。

你不应该通过 push 和 pop 来保护 rax,因为 rax 是返回值

【讨论】:

【参考方案4】:

我喜欢 Sirmabus 的回答,但我更喜欢简单的 C 转换和 offsetof 宏:

PPEB get_peb()

#if defined(_M_X64) // x64
    PTEB tebPtr = (PTEB)__readgsqword(offsetof(NT_TIB, Self));
#else // x86
    PTEB tebPtr = (PTEB)__readfsdword(offsetof(NT_TIB, Self));
#endif
    return tebPtr->ProcessEnvironmentBlock;

【讨论】:

以上是关于如何使用汇编程序(x64 OS)获取进程环境块(PEB)地址?的主要内容,如果未能解决你的问题,请参考以下文章

[OS-Linux]详解Linux的进程2(进程的优先级,环境变量,程序地址空间,进程地址空间,进程调度队列)

进程管理 os编程

Linux x64 -- 内核程序(驱动程序)读取任意进程数据实现

线程基础

爬虫 - scrapy框架设置代理

网络爬虫之scrapy框架设置代理