【问题标题】:How to use NtCurrentTeb() without Windows header files?如何在没有 Windows 头文件的情况下使用 NtCurrentTeb()?
【发布时间】:2023-03-30 03:53:01
【问题描述】:

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

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

【问题讨论】:

  • 您想在没有 windows 头文件的情况下为 windows 编程吗?为什么你不想包含 windows.h ?你当然可以使用__readfsdword__readgsqword 等,但这有什么意义呢?
  • __asm 在 64 位版本中不受支持
  • __readfsdword 不是宏,而是 cl 编译器的内联函数。如何不使用 Windows 标头或__readfsdword 帮助您深入了解 API 和 ABI。
  • 您已将此标记为“程序集”和“c”。这是否意味着您正在使用汇编程序进行编码?使用 VStudio?海合会?使用硬件特定功能(如gs:fs:)不会有通用的解决方案。

标签: c winapi assembly


【解决方案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】:

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

    【讨论】:

    • 对于 ntdll.dll 需要什么链接? NtCurrentTeb() 不需要这个。如果通过从 teb 读取 ProcessEnvironmentBlock 值来实现 NtCurrentPeb() - 再次 - 如果我们没有从中调用 ntdll.dll 呢?
    【解决方案3】:

    为了从gsfs 段寄存器读取,我在Visual Studio 中使用了这个程序集。在 Visual Studio 中使用these settings enabled 创建一个 C/C++ 空项目。 fsgs 段寄存器分别在 32 位和 64 位 Windows 中提供 NT_TIB 结构。 TEB 位于 NT_TIB 结构中的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);
    }
    

    【讨论】:

      猜你喜欢
      • 2023-04-07
      • 2014-06-04
      • 2016-03-10
      • 1970-01-01
      • 2016-05-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-13
      相关资源
      最近更新 更多