获取进程TEB、PEB的方法


Thread Environment Block

NtCurrentTeb

ntdll.dll导出的函数,文档显示要求Win7以上系统:https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-ntcurrentteb

PTEB teb = ::NtCurrentTeb();

从寄存器获取

查看MSVCSTL实现,发现NtCurrentTeb并未直接调用ntdll中导出的函数,而是从寄存器获取的,因为这样更高效,并且可以在Win7以下系统中工作。

#define PcTeb 0x18
...
__inline struct _TEB * NtCurrentTeb( void ) { return (struct _TEB *) (ULONG_PTR) __readfsdword (PcTeb); }

根据前人总结的信息,可以得出

#ifdef _WIN64
    PTEB teb = (PTEB)__readgsqword(0x30);
#else
    PTEB teb = (PTEB)__readfsdword(0x18);
#endif

Process Environment Block

RtlGetCurrentPeb

这是在ntdll.dll中导出的函数,虽然没有文档化,不过可以直接引用符号。

#include 

EXTERN_C PPEB NTAPI RtlGetCurrentPeb(VOID);

#pragma comment(lib, "ntdll.lib");

PPEB peb = ::RtlGetCurrentPeb();

NtQueryInformationProcess

调用 NtQueryInformationProcess 方法,第二个参数传递ProcessBasicInformation

PROCESS_BASIC_INFORMATION info{ 0 };
NTSTATUS status = NtQueryInformationProcess(handle, ProcessBasicInformation, &info, sizeof(info), &len);

PebBaseAddress指向PEB地址

typedef struct _PROCESS_BASIC_INFORMATION {
    PVOID Reserved1;
    PPEB PebBaseAddress;
    PVOID Reserved2[2];
    ULONG_PTR UniqueProcessId;
    PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;
typedef PROCESS_BASIC_INFORMATION *PPROCESS_BASIC_INFORMATION;

从寄存器获取

32位进程从fs寄存器获取,64位进程从gs寄存器获取。

#ifdef _WIN64
    PPEB peb = (PPEB)__readgsqword(0x60);
#else
    PPEB peb = (PPEB)__readfsdword(0x30);
#endif

相关阅读

枚举windows进程模块的几种方法—PEB内核结构详解
探索 PEB