How to get the Process Environment Block (PEB) address using assembler (x64 OS)?
Solution 1
Just two comments.
No need to push/pop rax
because it's a scratch or volatile register on Windows, see the caller/callee saved registers. In particular, rax
will hold the return value for your function.
It often helps to step through the machine code when you call GetModuleHandle() and compare it with your own assembly code. You'll probably encounter something like this implementation.
Solution 2
If you don't mind C. Works in Microsoft Visual Studio 2015. Uses the "__readgsqword()" intrinsic.
#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;
Solution 3
I like Sirmabus' answer but I much prefer it with simple C casts and the offsetof macro:
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;
}
Solution 4
Get_Ldr_Addr didnt save your result.
you should not protect rax by push and pop because rax is the return value
Oriel Cochavi
Updated on June 05, 2022Comments
-
Oriel Cochavi almost 2 years
I'm trying to get PEB address of the current process with assembler.
the cpp file:
#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; }
the asm file:
.code Get_Ldr_Addr proc push rax mov rax, GS:[30h] mov rax, [rax + 60h] pop rax ret Get_Ldr_Addr endp end
But I get different addresses from the GetModuleHandle(0) and the Get_Ldr_Addr()!
what is the problem? doesn't is suppose to be the same?
Q: If the function is external, it will check the PEB of the process that called it or of the function's dll (it suppose to be a dll)?
Tnx