Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Windows stores the TEB in FS (32bit) or GS (64bit) segment register. In a program using NtCurrentPeb() the x86 instruction is mov rax, gs:60h . The 0x60 value is offsetof(TEB, ProcessEnvironmentBlock) .

To use this in a program I've to include both Windows.h and Winternl.h header file which has bunch of other #define . As the question said I want to use the function without these header file and by directly accessing the segment register. I've also made a separate header file with the TEB and PEB structure. So how can I do that? I was thinking with __asm keyword and a typedef NtCurrentTeb() or something.

you want programming for windows without windows header files ? wwhy you not want include windows.h ? you of course can use __readfsdword and __readgsqword , etc. but what sense in all this ? RbMm Oct 2, 2018 at 21:02 __readfsdword not macro but inline function for cl compiler. how not use windows headers or __readfsdword help you to deep dive in API and ABI. ? RbMm Oct 2, 2018 at 21:15 You have this marked as both 'assembly' and 'c.' Does that mean you are coding in assembler? Using VStudio? Gcc? Using hardware specific features (like gs: or fs: ) isn't going to have a generic solution. David Wohlferd Oct 2, 2018 at 22:35

I really do not understand why you answered your own question incompletely. This confuses further readers because you did not provide the appropriate answer to the question itself .

You do not need to use ASM for this, you can use intrinsic functions like so:

#ifdef _M_X64
    auto pPEB = (PPEB)__readgsqword(0x60);
#elif _M_IX86
    auto pPEB = (PPEB)__readfsdword(0x30);
#else
    #error "PPEB Architecture Unsupported"
#endif

But to answer the actual question, here is how to do is via ASM:

x64 ASM (TEB/PEB):

GetTEBAsm64 proc
    mov rax, qword ptr gs:[00000030h]
GetTEBAsm64 endp
GetPEBAsm64 proc
    mov rax, qword ptr gs:[00000060h]
GetPEBAsm64 endp

x86 - PEB:

__asm
    mov eax, dword ptr fs : [00000030h]
    mov peb, eax

x86 - TEB:

__asm
        mov eax, dword ptr fs : [00000018h]
        mov teb, eax

I strongly hope that my answer is clear and that someone else in the future can benefit from it.

Why not make GetTEBAsm64 look like mov rax, qword ptr gs:[00000030h] ret . A lot of unnecessary code. Same for GetPEBAsm64 – Michael Petch Jul 17, 2022 at 1:10 @MichaelPetch Well... I don't even like using ASM in projects. I find intrinsic nicer. But the OP needed a solution so... :) – Mecanik Jul 17, 2022 at 3:17 I agree about the intrinsics and it is the best way to do it. I was just curious about the bloat in the asm. No problem. I only came across your answer as the code was referenced in another question today. – Michael Petch Jul 17, 2022 at 4:02 for what need link against ntdll.dll ? NtCurrentTeb() not require this. if implement NtCurrentPeb() by read ProcessEnvironmentBlock value from teb - again - for what ntdll.dll here if we nothing call from it ? – RbMm Oct 3, 2018 at 0:01 @RbMm NtCurrentTeb is not only an inline function from the Windows headers, but it also exists as a public function with the same name in ntdll.dll (but only in the 32 bit version of the DLL). – dialer Jul 18, 2022 at 13:45 @dialer really exist in 32bit version of the DLL (but not in 64). not view any sense use this import, when exist macro and for both 32/64 – RbMm Jul 18, 2022 at 15:03 @RbMm The public symbol allows interop from other programming languages and technologies which cannot access fs and gs directly. But the fact that it doesn't exist in 64bit is very limiting, of course. – dialer Jul 18, 2022 at 15:08

To read from gs or fs segment register, I have used this assembly in Visual Studio. Create a C/C++ empty project in Visual Studio with these settings enabled. fs or gs segment register provides NT_TIB structure in 32 bit and 64 bit Windows respectively. TEB is at 0x30 offset in NT_TIB structure. So the assembly in 64 bit will be: mov rax, gs:[30h].

Here is a sample source code to get current directory of an executable file:

  • ProcParam.asm:
  • mov rax, gs:[30h] ; TEB from gs in 64 bit only mov rax, [rax+60h] ; PEB mov rax, [rax+20h] ; RTL_USER_PROCESS_PARAMETERS ProcParam ENDP
  • main.c:
  • typedef struct _RTL_USER_PROCESS_PARAMETERS { unsigned int MaximumLength; unsigned int Length; unsigned int Flags; unsigned int DebugFlags; void* ConsoleHandle; unsigned int ConsoleFlags; void* StandardInput; void* StandardOutput; void* StandardError; CURDIR CurrentDirectory; /*Many more*/ } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; PRTL_USER_PROCESS_PARAMETERS ProcParam(void); int main(void) wprintf(L"%s\n", ProcParam()->CurrentDirectory.DosPath.Buffer);

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.