如何在没有Windows头文件的情况下使用NtCurrentTeb()?

时间:2018-10-02 20:52:02

标签: c winapi assembly

Windows将TEB存储在FS(32位)或GS(64位)段寄存器中。在使用NtCurrentPeb()的程序中,x86指令为mov rax, gs:60h0x60的值为offsetof(TEB, ProcessEnvironmentBlock)

要在程序中使用此文件,我必须同时包含Windows.hWinternl.h头文件,该文件还有其他#define一堆。正如问题所说,我想在没有这些头文件的情况下使用该函数,并直接访问段寄存器。我还用TEB和PEB结构制作了一个单独的头文件。那我该怎么办呢?我在考虑使用__asm关键字和一个typedef NtCurrentTeb()之类的东西。

3 个答案:

答案 0 :(得分:1)

声明函数原型并链接到ntdll.dll。

答案 1 :(得分:1)

我真的不明白您为什么不完全回答自己的问题。这使更多的读者感到困惑,因为您没有为问题本身提供适当的答案。

您无需为此使用ASM,可以像这样使用intrinsic functions

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

但是要回答实际问题,这是通过ASM进行的操作:

x64 ASM(TEB / PEB):

GetTEBAsm64 proc
    push rbx
    xor rbx,rbx
    xor rax,rax
    mov rbx, qword ptr gs:[00000030h]
    mov rax, rbx
    pop rbx
    ret
GetTEBAsm64 endp

GetPEBAsm64 proc
    push rbx
    xor rbx,rbx
    xor rax,rax
    mov rbx, qword ptr gs:[00000060h]
    mov rax, rbx
    pop rbx
    ret
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
    }

我强烈希望我的回答很清楚,希望将来有人能从中受益。

答案 2 :(得分:0)

要读取gsfs段寄存器,我在Visual Studio中使用了此程序集。使用these settings enabled在Visual Studio中创建一个C / C ++空项目。 fsgs段寄存器分别在32位和64位Windows中提供NT_TIB结构。在NT_TIB结构中,TEB在0x30处偏移。因此,采用64位的程序集将是:mov rax, gs:[30h]

以下是获取可执行文件当前目录的示例源代码:

  • ProcParam.asm:
.code

ProcParam PROC

mov rax, gs:[30h]      ; TEB from gs in 64 bit only
mov rax, [rax+60h]     ; PEB
mov rax, [rax+20h]     ; RTL_USER_PROCESS_PARAMETERS
ret

ProcParam ENDP

end
  • main.c:
#include <stdio.h>

typedef struct _UNICODE_STRING {
    unsigned short Length;
    unsigned short MaximumLength;
    wchar_t* Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _CURDIR {
    UNICODE_STRING DosPath;
    void* Handle;
} CURDIR, *PCURDIR;

/*Extracted from ntdll.pdb file*/

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);
}