最新消息:图 床

HOOK NtCreateThreadEx 導致 0xC00000F2

COOL IAM 237浏览 0评论

作者:Leeqwind
作者博客:https://xiaodaozhi.com/kernel/31.html

近期在研究和開發基於虛擬化的虛擬 HOOK 技術。在 Windows 7 x64 環境開發實測期間,發現針對 NtCreateThreadEx 函數的 HOOK 存在問題:該函數大部分情況下變得只返回 0xC00000F2 (STATUS_INVALID_PARAMETER_4) 第 4 個參數無效的狀態碼。這導致系統出現很多問題,大部分的新線程都無法成功創建。為了解決這個問題,在這篇文章中對問題進行追溯,查找到底是哪裡導致的。

經過追蹤:發現位於在 NtAllocateVirtualMemory 中如下位置賦值了提到的錯誤狀態碼:

kd> p
nt! ?? ::NNGAKEGL::`string'+0x47703:
fffff800`041e171e b8f20000c0      mov     eax,0C00000F2h

調用棧如下:

kd> k
 # Child-SP          RetAddr           Call Site
00 fffff880`028e7470 fffff800`03e918d3 nt! ?? ::NNGAKEGL::`string'+0x47703
01 fffff880`028e7610 fffff800`03e8de70 nt!KiSystemServiceCopyEnd+0x13
02 fffff880`028e7818 fffff800`04180a63 nt!KiServiceLinkage
03 fffff880`028e7820 fffff800`03e918d3 nt!NtSetInformationProcess+0x4c6
04 fffff880`028e7b70 fffff800`03e8de70 nt!KiSystemServiceCopyEnd+0x13
05 fffff880`028e7d08 fffff800`04180226 nt!KiServiceLinkage
06 fffff880`028e7d10 fffff800`0417e84d nt!RtlCreateUserStack+0x122
07 fffff880`028e7e00 fffff800`0417e47e nt!PspAllocateThread+0x299
08 fffff880`028e8020 fffff800`04182385 nt!PspCreateThread+0x1d2
09 fffff880`028e82a0 fffff880`03ea22ee nt!NtCreateThreadEx+0x25d
0a fffff880`028e89f0 fffff800`03e918d3 DetectModule!Handle_SSDT_NtCreateThreadEx+0x9e 
0b fffff880`028e8a70 00000000`76e51d9a nt!KiSystemServiceCopyEnd+0x13
0c 00000000`0366af18 000007fe`fd01b4a3 ntdll!NtCreateThreadEx+0xa
0d 00000000`0366af20 00000000`76bf65b6 KernelBase!CreateRemoteThreadEx+0x163
0e 00000000`0366b3e0 000007fe`f57f7186 kernel32!CreateThreadStub+0x36
0f 00000000`0366b430 00000000`00000000 0x000007fe`f57f7186

具體的調用鏈:

NtCreateThreadEx > PspCreateThread > PspAllocateThread > RtlCreateUserStack > ZwSetInformationProcess > NtSetInformationProcess > ZwAllocateVirtualMemory > NtAllocateVirtualMemory

最終在 NtAllocateVirtualMemory 函數中因其第4個參數的問題導致了 0xC00000F2 的狀態碼。報錯誤碼的指令前面的 10 條執行指令如下:

eb05            jmp     nt!NtAllocateVirtualMemory+0x119 (fffff800`04189da9)
488b056092f3ff  mov     rax,qword ptr [nt!MmHighestUserAddress (fffff800`040c3010)]
48050000ffff    add     rax,0FFFFFFFFFFFF0000h
483bd8          cmp     rbx,rax
0f8755790500    ja      nt! ?? ::NNGAKEGL::`string'+0x476f9 (fffff800`041e1714)
488b054a92f3ff  mov     rax,qword ptr [nt!MmHighestUserAddress (fffff800`040c3010)]
482bc3          sub     rax,rbx
482dffff0000    sub     rax,0FFFFh
493bc7          cmp     rax,r15
0f8246790500    jb      nt! ?? ::NNGAKEGL::`string'+0x47703 (fffff800`041e171e)
b8f20000c0      mov     eax,0C00000F2h

通過 IDA Hex 插件查看:

if ( v147 > MmHighestUserAddress - 0x10000 )
    return 0xC00000F0i64;
if ( MmHighestUserAddress - v147 - 0xFFFF < v19 )
    return 0xC00000F2i64;

在上面的第二個 if 判斷命中條件,返回了 0xC00000F2 狀態碼。

在 Windbg 中捕獲的該函數的指令執行路徑如下,在分析時由於篇幅關係,在下面的指令片段中均把機器碼左側 64 位地址的高 32 位隱去:

nt!NtAllocateVirtualMemory:
`04189c90 4c894c2420      mov     qword ptr [rsp+20h],r9
`04189c95 4c89442418      mov     qword ptr [rsp+18h],r8
`04189c9a 4889542410      mov     qword ptr [rsp+10h],rdx
`04189c9f 48894c2408      mov     qword ptr [rsp+8],rcx
`04189ca4 53              push    rbx
`04189ca5 56              push    rsi
`04189ca6 57              push    rdi
`04189ca7 4154            push    r12
`04189ca9 4155            push    r13
`04189cab 4156            push    r14
`04189cad 4157            push    r15
`04189caf 4881ec60010000  sub     rsp,160h
`04189cb6 4d8bd1          mov     r10,r9
`04189cb9 498bc0          mov     rax,r8
`04189cbc 4c8bca          mov     r9,rdx
`04189cbf 4c8be9          mov     r13,rcx
`04189cc2 4d85c0          test    r8,r8
`04189cc5 0f8523080000    jne     nt!NtAllocateVirtualMemory+0x85e (`0418a4ee)
`0418a4ee 4883f820        cmp     rax,20h
`0418a4f2 0f8223710500    jb      nt! ?? ::NNGAKEGL::`string'+0x475f0 (`041e161b)
`0418a4f8 488bc8          mov     rcx,rax
`0418a4fb e82002ceff      call    nt!RtlFindMostSignificantBit (`03e6a720)
`0418a500 440fbec0        movsx   r8d,al
`0418a504 b83f000000      mov     eax,3Fh
`0418a509 412bc0          sub     eax,r8d
`0418a50c 4898            cdqe
`0418a50e 48898424b0010000 mov     qword ptr [rsp+1B0h],rax
`0418a516 4883f835        cmp     rax,35h
`0418a51a 0f86abf7ffff    jbe     nt!NtAllocateVirtualMemory+0x3b (`04189ccb)
`04189ccb 4533c0          xor     r8d,r8d
`04189cce 418bf8          mov     edi,r8d
`04189cd1 654c8b242588010000 mov   r12,qword ptr gs:[188h]
`04189cda 4d8b5c2470      mov     r11,qword ptr [r12+70h]
`04189cdf 4c895c2478      mov     qword ptr [rsp+78h],r11
`04189ce4 8bb424c0010000  mov     esi,dword ptr [rsp+1C0h]
`04189ceb 448bf6          mov     r14d,esi
`04189cee 4183e67f        and     r14d,7Fh
`04189cf2 0fb7050f93f3ff  movzx   eax,word ptr [nt!KeNumberNodes (`040c3008)]
`04189cf9 443bf0          cmp     r14d,eax
`04189cfc 0f8734790500    ja      nt! ?? ::NNGAKEGL::`string'+0x4760b (`041e1636)
`04189d02 83e680          and     esi,0FFFFFF80h
`04189d05 f7c6ffcf07df    test    esi,0DF07CFFFh
`04189d0b 0f852f790500    jne     nt! ?? ::NNGAKEGL::`string'+0x47615 (`041e1640)
`04189d11 f7c600300800    test    esi,83000h
`04189d17 0f842d790500    je      nt! ?? ::NNGAKEGL::`string'+0x4761f (`041e164a)
`04189d1d f7c60000e820    test    esi,20E80000h
`04189d23 0f85e2090000    jne     nt!NtAllocateVirtualMemory+0xa7b (`0418a70b)
`04189d29 8b8424c8010000  mov     eax,dword ptr [rsp+1C8h]
`04189d30 89442460        mov     dword ptr [rsp+60h],eax
`04189d34 8bc8            mov     ecx,eax
`04189d36 e8c5bcd1ff      call    nt!MiMakeProtectionMask (`03ea5a00)
`04189d3b 89442474        mov     dword ptr [rsp+74h],eax
`04189d3f 83f8ff          cmp     eax,0FFFFFFFFh
`04189d42 0f84c2790500    je      nt! ?? ::NNGAKEGL::`string'+0x476ef (`041e170a)
`04189d48 410fb69424f6010000 movzx edx,byte ptr [r12+1F6h]
`04189d51 88542470        mov     byte ptr [rsp+70h],dl
`04189d55 84d2            test    dl,dl
`04189d57 7436            je      nt!NtAllocateVirtualMemory+0xff (`04189d8f)
`04189d8f 498b19          mov     rbx,qword ptr [r9]
`04189d92 48899c24a0000000 mov     qword ptr [rsp+0A0h],rbx
`04189d9a 4d8b3a          mov     r15,qword ptr [r10]
`04189d9d 4c897c2468      mov     qword ptr [rsp+68h],r15
`04189da2 eb05            jmp     nt!NtAllocateVirtualMemory+0x119 (`04189da9)
`04189da9 488b056092f3ff  mov     rax,qword ptr [nt!MmHighestUserAddress (`040c3010)]
`04189db0 48050000ffff    add     rax,0FFFFFFFFFFFF0000h
`04189db6 483bd8          cmp     rbx,rax
`04189db9 0f8755790500    ja      nt! ?? ::NNGAKEGL::`string'+0x476f9 (`041e1714)
`04189dbf 488b054a92f3ff  mov     rax,qword ptr [nt!MmHighestUserAddress (`040c3010)]
`04189dc6 482bc3          sub     rax,rbx
`04189dc9 482dffff0000    sub     rax,0FFFFh
`04189dcf 493bc7          cmp     rax,r15
`04189dd2 0f8246790500    jb      nt! ?? ::NNGAKEGL::`string'+0x47703 (`041e171e)
`041e171e b8f20000c0      mov     eax,0C00000F2h

根據上面的指令執行路徑可知,關鍵的寄存器是 r9 寄存器。但在函數稍開始位置將第二個參數寄存器 rdx 的值賦值給 r9 寄存器。

參數4:在賦值 r9 之前,函數將 r9 寄存器賦值給 r10 寄存器;在函數稍後位置將 r10 寄存器存儲的值作為地址取指針長度的值賦值給 r15 寄存器,並且在最後作為 cmp 比較的依據之一,即代碼中的 v19 變量。

參數2:在將 rdx 的值賦值 r9 寄存器之後,在稍後位置將 r9 寄存器的值作為地址取指針長度的值賦值 rbx 寄存器,並通過將 MmHighestUserAddress-rbx-0xFFFF 獲得的值與前面的 r15 寄存器進行大小比較。

函數原型:

NTSTATUS
NTAPI
NtAllocateVirtualMemory(
    IN     HANDLE      ProcessHandle,
    IN OUT PVOID      *BaseAddress,
    IN     ULONG_PTR   ZeroBits,
    IN OUT PSIZE_T     RegionSize,
    IN     ULONG       AllocationType,
    IN     ULONG       Protect
    );

MmHighestUserAddress 初值:

mov     rax, 7FFFFFEFFFFh
lea     rdx, aSafeboot_0 ; "SAFEBOOT:"
mov     cs:MmHighestUserAddress, rax
mov     rax, 7FFFFFF0000h
mov     cs:MmUserProbeAddress, rax

如果前面相減得到的 rax 值小於 r15 值,那麼報錯。

if ( MmHighestUserAddress - *BaseAddress - 0xFFFF < *RegionSize )
    return 0xC00000F2i64;

在報錯指令位置下斷點,截獲到一次報錯的上下文,判斷的兩個寄存器值如下:

kd> r rax, r15
rax=000007fffffe0000 r15=fffffa8000000000

顯而易見地,問題出在 r15 寄存器的值,而 r15 寄存器的值是由 r10 寄存器存儲的指針指向地址的值賦值的。

kd> r r10
r10=fffff880030f8918
kd> dq fffff880030f8918 l1
fffff880`030f8918  fffffa80`00000000

顯而易見地這是一個非常離譜的值,通常此處通過 RegionSize 參數指向域的值確定分配虛擬內存的區域大小,而 0xfffffa8000000000 顯然超過了正常用戶地址空間的範圍。

至於為什麼會傳入這樣無效的值,繼續向上探究:

nt!NtSetInformationProcess:
`041d659c fff3            push    rbx
kd> r rdx
rdx=0000000000000029
kd> p
nt!NtSetInformationProcess+0x2:
`041d659e 56              push    rsi
`041d659f 57              push    rdi
`041d65a0 4154            push    r12
`041d65a2 4155            push    r13
`041d65a4 4156            push    r14
`041d65a6 4157            push    r15
`041d65a8 4881ec10030000  sub     rsp,310h
`041d65af 488b052a44e8ff  mov     rax,qword ptr [nt!_security_cookie (`0405a9e0)]
`041d65b6 4833c4          xor     rax,rsp
`041d65b9 4889842400030000 mov     qword ptr [rsp+300h],rax
`041d65c1 458bf9          mov     r15d,r9d
`041d65c4 4d8be0          mov     r12,r8
`041d65c7 4c8bd1          mov     r10,rcx
`041d65ca 48894c2458      mov     qword ptr [rsp+58h],rcx
`041d65cf 4c898424b0000000 mov     qword ptr [rsp+0B0h],r8
`041d65d7 44897c2474      mov     dword ptr [rsp+74h],r15d
`041d65dc 654c8b342588010000 mov   r14,qword ptr gs:[188h] ;; Get _KTHREAD pointer
`041d65e5 4c89b42480000000 mov     qword ptr [rsp+80h],r14
`041d65ed 418abef6010000  mov     dil,byte ptr [r14+1F6h] ;; PreviousMode
`041d65f4 33f6            xor     esi,esi
`041d65f6 403afe          cmp     dil,sil ;; PreviousMode == KernelMode
`041d65f9 0f8461030000    je      nt!NtSetInformationProcess+0x3c3 (`041d6960)
`041d6960 bb08000000      mov     ebx,8
`041d6965 448d6bf9        lea     r13d,[rbx-7]
`041d6969 e949fdffff      jmp     nt!NtSetInformationProcess+0x11a (`041d66b7)
`041d66b7 83fa17          cmp     edx,17h
`041d66ba 0f8f76010000    jg      nt!NtSetInformationProcess+0x299 (`041d6836)
`041d6836 83fa27          cmp     edx,27h
`041d6839 0f8e2f010000    jle     nt!NtSetInformationProcess+0x3d1 (`041d696e)
`041d683f 83ea28          sub     edx,28h
`041d6842 0f84c95f0600    je      nt! ?? ::NNGAKEGL::`string'+0x4ce75 (`0423c811)
`041d6848 412bd5          sub     edx,r13d ; r13d=029h
`041d684b 0f8573030000    jne     nt!NtSetInformationProcess+0x627 (`041d6bc4)
`041d6851 4883cbff        or      rbx,0FFFFFFFFFFFFFFFFh
`041d6855 4c3bd3          cmp     r10,rbx
`041d6858 0f850b5f0600    jne     nt! ?? ::NNGAKEGL::`string'+0x4cdbf (`0423c769)
`041d685e 4183ff28        cmp     r15d,28h
`041d6862 0f85155f0600    jne     nt! ?? ::NNGAKEGL::`string'+0x4cdd3 (`0423c77d)
`041d6868 403afe          cmp     dil,sil
`041d686b 0f85d8030000    jne     nt!NtSetInformationProcess+0x6ac (`041d6c49)
`041d6871 4c8bfe          mov     r15,rsi
`041d6874 458b3424        mov     r14d,dword ptr [r12]
`041d6878 4183fe40        cmp     r14d,40h
`041d687c 0f87f15e0600    ja      nt! ?? ::NNGAKEGL::`string'+0x4cdc9 (`0423c773)
`041d6882 418b44240c      mov     eax,dword ptr [r12+0Ch]
`041d6887 410b442408      or      eax,dword ptr [r12+8]
`041d688c 410b442404      or      eax,dword ptr [r12+4]
`041d6891 0f85dc5e0600    jne     nt! ?? ::NNGAKEGL::`string'+0x4cdc9 (`0423c773)
`041d6897 4983c410        add     r12,10h
`041d689b 49393424        cmp     qword ptr [r12],rsi
kd> r r12
r12=fffff88003aefd98
kd> p
`041d689f 0f84215f0600    je      nt! ?? ::NNGAKEGL::`string'+0x4ce23 (`0423c7c6)
`041d68a5 49ba1400000080f7ffff mov r10,0FFFFF78000000014h
`041d68af 4d8b12          mov     r10,qword ptr [r10]
`041d68b2 0f31            rdtsc
`041d68b4 48c1e220        shl     rdx,20h
`041d68b8 480bc2          or      rax,rdx
`041d68bb 4c03d0          add     r10,rax
`041d68be 4183e21f        and     r10d,1Fh
`041d68c2 4503d5          add     r10d,r13d
`041d68c5 4d8b1c24        mov     r11,qword ptr [r12] ;; 從r12指向地址取值賦給r11
`041d68c9 4c899c24f8000000 mov     qword ptr [rsp+0F8h],r11 ;; [rsp+0F8h]變量賦值
`041d68d1 65488b042588010000 mov   rax,qword ptr gs:[188h]
`041d68da 488b4870        mov     rcx,qword ptr [rax+70h]
`041d68de 0fbaa13c04000011 bt      dword ptr [rcx+43Ch],11h
`041d68e6 0f823e010000    jb      nt!NtSetInformationProcess+0x48d (`041d6a2a)
`041d68ec 4d8b4c2408      mov     r9,qword ptr [r12+8]
`041d68f1 4c3bce          cmp     r9,rsi
`041d68f4 0f85d65e0600    jne     nt! ?? ::NNGAKEGL::`string'+0x4ce2d (`0423c7d0)
`0423c7d0 4983f920        cmp     r9,20h
`0423c7d4 7217            jb      nt! ?? ::NNGAKEGL::`string'+0x4ce51 (`0423c7ed)
`0423c7d6 498bc9          mov     rcx,r9
`0423c7d9 e8423fc8ff      call    nt!RtlFindMostSignificantBit (`03ec0720)
`0423c7de 0fbec8          movsx   ecx,al
`0423c7e1 b83f000000      mov     eax,3Fh
`0423c7e6 2bc1            sub     eax,ecx
`0423c7e8 4c63c8          movsxd  r9,eax
`0423c7eb eb04            jmp     nt! ?? ::NNGAKEGL::`string'+0x4ce55 (`0423c7f1)
`0423c7f1 4983f935        cmp     r9,35h
`0423c7f5 0f8739a2f9ff    ja      nt!NtSetInformationProcess+0x497 (`041d6a34)
`0423c7fb e9faa0f9ff      jmp     nt!NtSetInformationProcess+0x35d (`041d68fa)
`041d68fa 4d8d6c2410      lea     r13,[r12+10h]
`041d68ff 4c896c2420      mov     qword ptr [rsp+20h],r13
`041d6904 4533c0          xor     r8d,r8d
`041d6907 498bd3          mov     rdx,r11
`041d690a 418bca          mov     ecx,r10d
`041d690d e8863e0000      call    nt!MiScanUserAddressSpace (`041da798)
`041d6912 8bc8            mov     ecx,eax
`041d6914 3bc6            cmp     eax,esi
`041d6916 7c28            jl      nt!NtSetInformationProcess+0x3a3 (`041d6940)
`041d6940 3bce            cmp     ecx,esi
`041d6942 0f8cec000000    jl      nt!NtSetInformationProcess+0x497 (`041d6a34)
`041d6a34 498d542410      lea     rdx,[r12+10h]
`041d6a39 488932          mov     qword ptr [rdx],rsi
`041d6a3c 410fbaee0d      bts     r14d,0Dh
`041d6a41 c744242804000000 mov     dword ptr [rsp+28h],4
`041d6a49 4489742420      mov     dword ptr [rsp+20h],r14d
`041d6a4e 4c8d8c24f8000000 lea     r9,[rsp+0F8h] ;; [rsp+0F8h]變量的地址給r9寄存器
`041d6a56 4d8b442408      mov     r8,qword ptr [r12+8]
`041d6a5b 488bcb          mov     rcx,rbx
`041d6a5e e87da4d0ff      call    nt!ZwAllocateVirtualMemory (`03ee0ee0)
kd> p
nt!NtSetInformationProcess+0x4c6:
`041d6a63 8bc8            mov     ecx,eax
kd> r rax
rax=00000000c00000f2
kd> r rsp
rsp=fffff88003aef820
kd> dq rsp+0x0f8 l1
fffff880`03aef918  fffff800`00000000
kd> dq fffff88003aefd98 l1
fffff880`03aefd98  fffff800`00000000

函數定義:

NTSTATUS
NTAPI
NtSetInformationProcess (
    IN HANDLE           ProcessHandle,
    IN PROCESSINFOCLASS ProcessInformationClass,
    IN PVOID            ProcessInformation,
    IN ULONG            ProcessInformationLength
    );

其中第二個參數是定義設置進程信息的類型。根據上面的指令執行路徑得知,這次調用傳遞給該函數的第二個參數值為0x29,根據 PROCESSINFOCLASS 定義:

typedef enum _PROCESSINFOCLASS {
    ...
    ProcessThreadStackAllocation = 0x29, // 0x29, 41
    ...
} PROCESSINFOCLASS;

進程信息類型為 0x29 時表示設置進程的線程棧分配信息。

在這次 NtSetInformationProcess 函數調用中,可以看到傳入 ZwAllocateVirtualMemory 函數的第四個參數來自它自身第三個參數 r8 寄存器指向的結構體對象基址 +10 偏移的域值。

第三個參數是 ProcessInformation,指向一個由調用者分配的緩衝區,作為用於提供指定的進程信息類型所需的各種數據的結構。

在該函數調用初期查看這個緩衝區中的數據:

kd> dq 0xfffff880`03aefd88
fffff880`03aefd88  00000000`00000000 00000000`00000000
fffff880`03aefd98  fffff880`00000000 00000000`00000000
fffff880`03aefda8  00000000`00000000 00000000`00000000

可以確定的是上級函數傳入 NtSetInformationProcess 的第三個參數時緩衝區中的數據就是這樣的,就是說偏移為 +10h 位置的域其值為 0xFFFFF88000000000 這種異常的值。

所以此時繼續向上探究。在 nt!RtlCreateUserStack 函數首地址下斷點捕獲其調用路徑:

nt!RtlCreateUserStack:
`041cf104 4c89442418      mov     qword ptr [rsp+18h],r8
`041cf109 4889542410      mov     qword ptr [rsp+10h],rdx
`041cf10e 48894c2408      mov     qword ptr [rsp+8],rcx
`041cf113 53              push    rbx
`041cf114 56              push    rsi
`041cf115 4154            push    r12
`041cf117 4155            push    r13
`041cf119 4156            push    r14
`041cf11b 4157            push    r15
`041cf11d 4881ecb8000000  sub     rsp,0B8h
`041cf124 4d8be9          mov     r13,r9
`041cf127 488bf2          mov     rsi,rdx
`041cf12a 488bd9          mov     rbx,rcx
`041cf12d 4d8bf9          mov     r15,r9
`041cf130 49c1ef38        shr     r15,38h
`041cf134 44887c2430      mov     byte ptr [rsp+30h],r15b
`041cf139 48b8ffffffffffffff00 mov rax,0FFFFFFFFFFFFFFh
`041cf143 4c23e8          and     r13,rax
`041cf146 4c89ac2408010000 mov     qword ptr [rsp+108h],r13
`041cf14e 4180ff40        cmp     r15b,40h
`041cf152 0f8764060400    ja      nt! ?? ::NNGAKEGL::`string'+0x7020 (`0420f7bc)
`041cf158 4b8d446d00      lea     rax,[r13+r13*2]
`041cf15d 4889442460      mov     qword ptr [rsp+60h],rax
`041cf162 65488b042588010000 mov   rax,qword ptr gs:[188h]
`041cf16b 488b4870        mov     rcx,qword ptr [rax+70h]
`041cf16f 4c8bb138030000  mov     r14,qword ptr [rcx+338h]
`041cf176 4c89742458      mov     qword ptr [rsp+58h],r14
`041cf17b 4885db          test    rbx,rbx
`041cf17e 0f848b010000    je      nt!RtlCreateUserStack+0x20b (`041cf30f)
`041cf184 4885d2          test    rdx,rdx
`041cf187 0f8482010000    je      nt!RtlCreateUserStack+0x20b (`041cf30f)
`041cf18d b800400000      mov     eax,4000h
`041cf192 4885db          test    rbx,rbx
`041cf195 480f44d8        cmove   rbx,rax
`041cf199 483bde          cmp     rbx,rsi
`041cf19c 0f832c060400    jae     nt! ?? ::NNGAKEGL::`string'+0x7032 (`0420f7ce)
`0420f7ce 488db3ffff0f00  lea     rsi,[rbx+0FFFFFh]
`0420f7d5 4881e60000f0ff  and     rsi,0FFFFFFFFFFF00000h
`0420f7dc e9c1f9fbff      jmp     nt!RtlCreateUserStack+0x9e (`041cf1a2)
`041cf1a2 498d4dff        lea     rcx,[r13-1]
`041cf1a6 48f7d1          not     rcx
`041cf1a9 4e8d642bff      lea     r12,[rbx+r13-1]
`041cf1ae 4c23e1          and     r12,rcx
`041cf1b1 4881c6ffff0000  add     rsi,0FFFFh
`041cf1b8 4881e60000ffff  and     rsi,0FFFFFFFFFFFF0000h
`041cf1bf 498b8618030000  mov     rax,qword ptr [r14+318h]
`041cf1c6 48898424a0000000 mov     qword ptr [rsp+0A0h],rax
`041cf1ce eb05            jmp     nt!RtlCreateUserStack+0xd1 (`041cf1d5)
`041cf1d5 4885c0          test    rax,rax
`041cf1d8 0f8503060400    jne     nt! ?? ::NNGAKEGL::`string'+0x7045 (`0420f7e1)
`041cf1de 410fb6c7        movzx   eax,r15b
`041cf1e2 89442478        mov     dword ptr [rsp+78h],eax
`041cf1e6 8364247c00      and     dword ptr [rsp+7Ch],0
`041cf1eb 83a4248400000000 and     dword ptr [rsp+84h],0
`041cf1f3 83a4248000000000 and     dword ptr [rsp+80h],0
`041cf1fb 4889b42488000000 mov     qword ptr [rsp+88h],rsi ; assign-> RegionSize
`041cf203 4c89842490000000 mov     qword ptr [rsp+90h],r8
`041cf20b 41b928000000    mov     r9d,28h
`041cf211 4c8d442478      lea     r8,[rsp+78h]
`041cf216 418d5101        lea     edx,[r9+1]
`041cf21a 4983cfff        or      r15,0FFFFFFFFFFFFFFFFh
`041cf21e 498bcf          mov     rcx,r15
`041cf221 e83aadd0ff      call    nt!ZwSetInformationProcess (`03ed9f60)
kd> r r8
r8=fffff8800422bd88
kd> dq [r8]
fffff880`0422bd88  00000000`00000000 00000000`00000000
fffff880`0422bd98  fffff880`00100000 00000000`00000000
fffff880`0422bda8  00000000`00000384 00000000`00000000
fffff880`0422bdb8  00000000`00000018 fffff880`0422bdd0
kd> r
rax=0000000000000000 rbx=fffff88000002000 rcx=ffffffffffffffff
rdx=0000000000000029 rsi=fffff88000100000 rdi=0000000000000000
rip=fffff800041cf221 rsp=fffff8800422bd10 rbp=fffffa8004170b30
 r8=fffff8800422bd88  r9=0000000000000028 r10=0000000000000001
r11=fffff8800422bde0 r12=fffff88000002000 r13=0000000000001000
r14=000007fffffd7000 r15=ffffffffffffffff
iopl=0         nv up ei ng nz na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b  efl=00000286

根據執行路徑可知,傳入給 ZwSetInformationProcess 的第三個參數指針指向的是位於 RtlCreateUserStack 棧區域的局部結構體變量。在將結構體地址賦值給 r8 寄存器之前,函數執行對結構體 6 個域賦值操作,其中需要關注的是第 5 個域,即在前面一直追尋的指示 RegionSize 的來源的域,這個域是通過 rsi 寄存器賦值的。

向上追溯,發現在 rsi 寄存器取 rbx+0xFFFFF 地址之後,再經過幾次邏輯與運算:

lea     rsi,[rbx+0FFFFFh]
and     rsi,0FFFFFFFFFFF00000h
add     rsi,0FFFFh
and     rsi,0FFFFFFFFFFFF0000h

此時 rbx 的值是 0xFFFFF88000002000,而 rbx 是在函數執行開始時由 rcx 寄存器直接賦值的,而 rcx 寄存器是作為函數的第 1 個參數傳入的。該函數原型如下:

NTSTATUS
NTAPI
RtlCreateUserStack (
    _In_opt_ SIZE_T       CommittedStackSize,
    _In_opt_ SIZE_T       MaximumStackSize,
    _In_opt_ ULONG_PTR    ZeroBits,
    _In_     SIZE_T       PageSize,
    _In_     ULONG_PTR    ReserveAlignment,
    _Out_    PINITIAL_TEB InitialTeb
);

其中第一個參數是 CommittedStackSize,作為棧的初始提交大小。顯然地在這裡傳入該函數的這個參數就是不尋常的值。那麼繼續向上探究:

nt!PspAllocateThread:
`041cd5b4 488bc4          mov     rax,rsp
`041cd5b7 4c894820        mov     qword ptr [rax+20h],r9
`041cd5bb 44884018        mov     byte ptr [rax+18h],r8b
`041cd5bf 48895010        mov     qword ptr [rax+10h],rdx
`041cd5c3 48894808        mov     qword ptr [rax+8],rcx
`041cd5c7 53              push    rbx
`041cd5c8 56              push    rsi
`041cd5c9 57              push    rdi
`041cd5ca 4154            push    r12
`041cd5cc 4155            push    r13
`041cd5ce 4156            push    r14
`041cd5d0 4157            push    r15
`041cd5d2 4881ece0010000  sub     rsp,1E0h
`041cd5d9 458ad0          mov     r10b,r8b
`041cd5dc 4c8be9          mov     r13,rcx
`041cd5df 33ff            xor     edi,edi
`041cd5e1 48897c2470      mov     qword ptr [rsp+70h],rdi
`041cd5e6 4c3bcf          cmp     r9,rdi
`041cd5e9 740b            je      nt!PspAllocateThread+0x42 (`041cd5f6)
`041cd5eb 410fba210f      bt      dword ptr [r9],0Fh
`041cd5f0 0f823c0ff6ff    jb      nt! ?? ::NNGAKEGL::`string'+0x241f0 (`0412e532)
`041cd5f6 4c8ba42460020000 mov     r12,qword ptr [rsp+260h]
`041cd5fe 65488b042588010000 mov   rax,qword ptr gs:[188h]
`041cd607 4889842498000000 mov     qword ptr [rsp+98h],rax
`041cd60f 4c8b842478020000 mov     r8,qword ptr [rsp+278h]
`041cd617 4189b878010000  mov     dword ptr [r8+178h],edi
`041cd61e 4588907c010000  mov     byte ptr [r8+17Ch],r10b
`041cd625 4c8bb42440020000 mov     r14,qword ptr [rsp+240h]
`041cd62d 4c3bf7          cmp     r14,rdi
`041cd630 0f848a060000    je      nt!PspAllocateThread+0x70b (`041cdcc0)
`041cd636 483b0df349f4ff  cmp     rcx,qword ptr [nt!PsInitialSystemProcess (`04112030)]
`041cd63d 0f841a0ff6ff    je      nt! ?? ::NNGAKEGL::`string'+0x2421f (`0412e55d)
`041cd643 483bd7          cmp     rdx,rdi
`041cd646 0f851a040000    jne     nt!PspAllocateThread+0x4b2 (`041cda66)
`041cd64c 498b85c8010000  mov     rax,qword ptr [r13+1C8h]
`041cd653 48f7d8          neg     rax
`041cd656 1bf6            sbb     esi,esi
`041cd658 83e658          and     esi,58h
`041cd65b 41bf98040000    mov     r15d,498h
`041cd661 4103f7          add     esi,r15d
`041cd664 488d442458      lea     rax,[rsp+58h]
`041cd669 4889442440      mov     qword ptr [rsp+40h],rax
`041cd66e 89742438        mov     dword ptr [rsp+38h],esi
`041cd672 897c2430        mov     dword ptr [rsp+30h],edi
`041cd676 89742428        mov     dword ptr [rsp+28h],esi
`041cd67a 48897c2420      mov     qword ptr [rsp+20h],rdi
`041cd67f 458aca          mov     r9b,r10b
`041cd682 4c8bc2          mov     r8,rdx
`041cd685 488b15c449f4ff  mov     rdx,qword ptr [nt!PsThreadType (`04112050)]
`041cd68c 418aca          mov     cl,r10b
`041cd68f e84cd60000      call    nt!ObCreateObject (`041dace0)
`041cd694 8bd8            mov     ebx,eax
`041cd696 89442450        mov     dword ptr [rsp+50h],eax
`041cd69a 3bc7            cmp     eax,edi
`041cd69c 0f8cc00ef6ff    jl      nt! ?? ::NNGAKEGL::`string'+0x24224 (`0412e562)
`041cd6a2 448bc6          mov     r8d,esi
`041cd6a5 33d2            xor     edx,edx
`041cd6a7 488b5c2458      mov     rbx,qword ptr [rsp+58h]
`041cd6ac 488bcb          mov     rcx,rbx
`041cd6af e8dc61d1ff      call    nt!memset (`03ee3890)
`041cd6b4 413bf7          cmp     esi,r15d
`041cd6b7 0f87b40ef6ff    ja      nt! ?? ::NNGAKEGL::`string'+0x24233 (`0412e571)
`041cd6bd 4889bb30040000  mov     qword ptr [rbx+430h],rdi
`041cd6c4 488d8bb0030000  lea     rcx,[rbx+3B0h]
`041cd6cb 48898c2480000000 mov     qword ptr [rsp+80h],rcx
`041cd6d3 498b8580010000  mov     rax,qword ptr [r13+180h]
`041cd6da 488901          mov     qword ptr [rcx],rax
`041cd6dd 41f6042404      test    byte ptr [r12],4
`041cd6e2 0f85c00ef6ff    jne     nt! ?? ::NNGAKEGL::`string'+0x2426a (`0412e5a8)
`041cd6e8 488db338040000  lea     rsi,[rbx+438h]
`041cd6ef 48893e          mov     qword ptr [rsi],rdi
`041cd6f2 c7834004000007000000 mov dword ptr [rbx+440h],7
`041cd6fc 488d8bc0030000  lea     rcx,[rbx+3C0h]
`041cd703 33d2            xor     edx,edx
`041cd705 448d4201        lea     r8d,[rdx+1]
`041cd709 e88e56d0ff      call    nt!KeInitializeSemaphore (`03ed2d9c)
`041cd70e 488d8b68030000  lea     rcx,[rbx+368h]
`041cd715 48894908        mov     qword ptr [rcx+8],rcx
`041cd719 488909          mov     qword ptr [rcx],rcx
`041cd71c 488d83e8030000  lea     rax,[rbx+3E8h]
`041cd723 48894008        mov     qword ptr [rax+8],rax
`041cd727 488900          mov     qword ptr [rax],rax
`041cd72a 4889bb80040000  mov     qword ptr [rbx+480h],rdi
`041cd731 4889bb98030000  mov     qword ptr [rbx+398h],rdi
`041cd738 488d83a0030000  lea     rax,[rbx+3A0h]
`041cd73f 48894008        mov     qword ptr [rax+8],rax
`041cd743 488900          mov     qword ptr [rax],rax
`041cd746 48a11400000080f7ffff mov rax,qword ptr [FFFFF78000000014h]
`041cd750 488b4c2458      mov     rcx,qword ptr [rsp+58h]
`041cd755 48898160030000  mov     qword ptr [rcx+360h],rax
`041cd75c 48898c24b8000000 mov     qword ptr [rsp+0B8h],rcx
`041cd764 89bc24c0000000  mov     dword ptr [rsp+0C0h],edi
`041cd76b f0480fba2e00    lock bts qword ptr [rsi],0
`041cd771 0f823d0ef6ff    jb      nt! ?? ::NNGAKEGL::`string'+0x24276 (`0412e5b4)
`041cd777 4c8b7c2458      mov     r15,qword ptr [rsp+58h]
`041cd77c 498d9fb8030000  lea     rbx,[r15+3B8h]
`041cd783 48899c24b0000000 mov     qword ptr [rsp+0B0h],rbx
`041cd78b 488d9424b8000000 lea     rdx,[rsp+0B8h]
`041cd793 488b0d2eb4ebff  mov     rcx,qword ptr [nt!PspCidTable (`04088bc8)]
`041cd79a e8a5050000      call    nt!ExCreateHandle (`041cdd44)
`041cd79f 488903          mov     qword ptr [rbx],rax
`041cd7a2 483bc7          cmp     rax,rdi
`041cd7a5 0f84170ef6ff    je      nt! ?? ::NNGAKEGL::`string'+0x24284 (`0412e5c2)
`041cd7ab 4c3bf7          cmp     r14,rdi
`041cd7ae 0f8429050000    je      nt!PspAllocateThread+0x728 (`041cdcdd)
`041cd7b4 668bf7          mov     si,di
`041cd7b7 89742460        mov     dword ptr [rsp+60h],esi
`041cd7bb 41f6042480      test    byte ptr [r12],80h
`041cd7c0 0f8592020000    jne     nt!PspAllocateThread+0x4a4 (`041cda58)
`041cd7c6 41f6042402      test    byte ptr [r12],2
`041cd7cb 0f85dc040000    jne     nt!PspAllocateThread+0x6f8 (`041cdcad)
`041cd7d1 41b808000000    mov     r8d,8
`041cd7d7 4c8ba42470020000 mov     r12,qword ptr [rsp+270h]
`041cd7df 4c3be7          cmp     r12,rdi
`041cd7e2 0f84c90ef6ff    je      nt! ?? ::NNGAKEGL::`string'+0x2437b (`0412e6b1)
`041cd7e8 4939bd20030000  cmp     qword ptr [r13+320h],rdi
`041cd7ef 0f8512030000    jne     nt!PspAllocateThread+0x552 (`041cdb07)
`041cd7f5 41f6042401      test    byte ptr [r12],1
`041cd7fa 0f858e0ef6ff    jne     nt! ?? ::NNGAKEGL::`string'+0x24358 (`0412e68e)
`041cd800 bb00100000      mov     ebx,1000h
`041cd805 41397c2420      cmp     dword ptr [r12+20h],edi
`041cd80a 0f853e0ef6ff    jne     nt! ?? ::NNGAKEGL::`string'+0x24318 (`0412e64e)
`041cd810 488d942450010000 lea     rdx,[rsp+150h]
`041cd818 498bcd          mov     rcx,r13
`041cd81b e8f04bd4ff      call    nt!KeStackAttachProcess (`03f12410)
`041cd820 4c8bb42448020000 mov     r14,qword ptr [rsp+248h]
`041cd828 4c89742428      mov     qword ptr [rsp+28h],r14
`041cd82d 48c744242000000100 mov   qword ptr [rsp+20h],10000h
`041cd836 4c8bcb          mov     r9,rbx
`041cd839 4d8b442408      mov     r8,qword ptr [r12+8]
`041cd83e 498b542418      mov     rdx,qword ptr [r12+18h]
`041cd843 498b4c2410      mov     rcx,qword ptr [r12+10h]
`041cd848 e8b7180000      call    nt!RtlCreateUserStack (`041cf104)
kd> r
rax=0000000000000000 rbx=0000000000001000 rcx=fffff88000002000
rdx=000007fe00000000 rsi=fffffa8003020000 rdi=0000000000000000
rip=041cd848 rsp=fffff8800422be00 rbp=fffffa8004170b30
 r8=0000000000000000  r9=0000000000001000 r10=0000000000000001
r11=fffff8800422bde0 r12=fffff8800422c310 r13=fffffa8004170b30
r14=fffff8800422c340 r15=fffffa8003028b60
kd> dq [rsp+270h] l1
fffff880`0422c070  fffff880`0422c310
kd> dq fffff880`0422c310 l4
fffff880`0422c310  00000000`00000000 00000000`00000000
fffff880`0422c320  fffff880`00002000 000007fe`00000000

根據上面的執行路徑,傳入 RtlCreateUserStack 函數的第一個參數 rcx 寄存器是由 qword ptr [r12+10h] 賦值的。而 r12 寄存器在稍早時候取 [rsp+270h] 指向地址的指針長度的值。

[rsp+270h] 是調用者傳遞給該函數的第 11 個參數。繼續向上追溯:

nt!PspCreateThread:
`041cd2ac 48895c2410      mov     qword ptr [rsp+10h],rbx
`041cd2b1 55              push    rbp
`041cd2b2 56              push    rsi
`041cd2b3 57              push    rdi
`041cd2b4 4154            push    r12
`041cd2b6 4155            push    r13
`041cd2b8 4156            push    r14
`041cd2ba 4157            push    r15
`041cd2bc 4881ec40020000  sub     rsp,240h
`041cd2c3 488b051667e8ff  mov     rax,qword ptr [nt!_security_cookie (`040539e0)]
`041cd2ca 4833c4          xor     rax,rsp
`041cd2cd 4889842430020000 mov     qword ptr [rsp+230h],rax
`041cd2d5 4c8bac24c0020000 mov     r13,qword ptr [rsp+2C0h]
`041cd2dd 488bbc24a0020000 mov     rdi,qword ptr [rsp+2A0h]
`041cd2e5 4c8bb424a8020000 mov     r14,qword ptr [rsp+2A8h]
`041cd2ed 4c8bbc24c8020000 mov     r15,qword ptr [rsp+2C8h]
`041cd2f5 65488b1c2588010000 mov   rbx,qword ptr gs:[188h]
`041cd2fe 48898c2480000000 mov     qword ptr [rsp+80h],rcx
`041cd306 488b8c24b0020000 mov     rcx,qword ptr [rsp+2B0h]
`041cd30e 4c89842488000000 mov     qword ptr [rsp+88h],r8
`041cd316 4533c0          xor     r8d,r8d
`041cd319 48898c2490000000 mov     qword ptr [rsp+90h],rcx
`041cd321 488b8c24b8020000 mov     rcx,qword ptr [rsp+2B8h]
`041cd329 498bc1          mov     rax,r9
`041cd32c 48898c2498000000 mov     qword ptr [rsp+98h],rcx
`041cd334 488b8c24e8020000 mov     rcx,qword ptr [rsp+2E8h]
`041cd33c 89542464        mov     dword ptr [rsp+64h],edx
`041cd340 458ae0          mov     r12b,r8b
`041cd343 48894c2470      mov     qword ptr [rsp+70h],rcx
`041cd348 4d3be8          cmp     r13,r8
`041cd34b 7407            je      a8 (`041cd354)
`041cd34d 448aa3f6010000  mov     r12b,byte ptr [rbx+1F6h]
`041cd354 4c89442468      mov     qword ptr [rsp+68h],r8
`041cd359 be080000c0      mov     esi,0C0000008h
`041cd35e 493bc0          cmp     rax,r8
`041cd361 0f842a020000    je      2e5 (`041cd591)
`041cd367 4c89442430      mov     qword ptr [rsp+30h],r8
`041cd36c 4c8b05ad4cf4ff  mov     r8,qword ptr [nt!PsProcessType (`04112020)]
`041cd373 488d4c2478      lea     rcx,[rsp+78h]
`041cd378 48894c2428      mov     qword ptr [rsp+28h],rcx
`041cd37d 458acc          mov     r9b,r12b
`041cd380 ba02000000      mov     edx,2
`041cd385 488bc8          mov     rcx,rax
`041cd388 c744242044666c74 mov     dword ptr [rsp+20h],746C6644h
`041cd390 e84ba10000      call    nt!ObReferenceObjectByHandleWithTag (`041d74e0)
`041cd395 488b6c2478      mov     rbp,qword ptr [rsp+78h]
`041cd39a 4533c0          xor     r8d,r8d
`041cd39d 413bc0          cmp     eax,r8d
`041cd3a0 0f8c9a010000    jl      294 (`041cd540)
`041cd3a6 453ae0          cmp     r12b,r8b
`041cd3a9 0f85bc010000    jne     2bf (`041cd56b)
`041cd56b 483b2dbe4af4ff  cmp     rbp,qword ptr [nt!PsInitialSystemProcess (`04112030)]
`041cd572 0f8537feffff    jne     103 (`041cd3af)
`041cd3af 8b8c24d0020000  mov     ecx,dword ptr [rsp+2D0h]
`041cd3b6 41b901000000    mov     r9d,1
`041cd3bc 418bc0          mov     eax,r8d
`041cd3bf 4184c9          test    r9b,cl
`041cd3c2 410f45c1        cmovne  eax,r9d
`041cd3c6 f6c102          test    cl,2
`041cd3c9 0f85ba010000    jne     2dd (`041cd589)
`041cd3cf 89442460        mov     dword ptr [rsp+60h],eax
`041cd3d3 f6c104          test    cl,4
`041cd3d6 0f855e200500    jne     nt! ?? ::NNGAKEGL::`string'+0x2a7ca (`0421f43a)
`041cd3dc f6c108          test    cl,8
`041cd3df 0f8598010000    jne     2d1 (`041cd57d)
`041cd3e5 66ff8bc4010000  dec     word ptr [rbx+1C4h]
`041cd3ec 0f0d8d78010000  prefetchw [rbp+178h]
`041cd3f3 488b8578010000  mov     rax,qword ptr [rbp+178h]
`041cd3fa 4883e0fe        and     rax,0FFFFFFFFFFFFFFFEh
`041cd3fe 488d4802        lea     rcx,[rax+2]
`041cd402 f0480fb18d78010000 lock cmpxchg qword ptr [rbp+178h],rcx
`041cd40b 0f8535200500    jne     nt! ?? ::NNGAKEGL::`string'+0x2a7d6 (`0421f446)
`041cd411 488bcd          mov     rcx,rbp
`041cd414 e8d70ad2ff      call    nt!ObfReferenceObject (`03eedef0)
`041cd419 488b442470      mov     rax,qword ptr [rsp+70h]
`041cd41e 488b942488000000 mov     rdx,qword ptr [rsp+88h]
`041cd426 4c8d9c24a0000000 lea     r11,[rsp+0A0h]
`041cd42e 4d8bce          mov     r9,r14
`041cd431 458ac4          mov     r8b,r12b
`041cd434 4c895c2458      mov     qword ptr [rsp+58h],r11
`041cd439 4889442450      mov     qword ptr [rsp+50h],rax
`041cd43e 488d442468      lea     rax,[rsp+68h]
`041cd443 4889442448      mov     qword ptr [rsp+48h],rax
`041cd448 488d442460      lea     rax,[rsp+60h]
`041cd44d 488bcd          mov     rcx,rbp
`041cd450 4889442440      mov     qword ptr [rsp+40h],rax
`041cd455 488b8424e0020000 mov     rax,qword ptr [rsp+2E0h]
`041cd45d 4889442438      mov     qword ptr [rsp+38h],rax
`041cd462 488b8424d8020000 mov     rax,qword ptr [rsp+2D8h]
`041cd46a 4889442430      mov     qword ptr [rsp+30h],rax
`041cd46f 4c897c2428      mov     qword ptr [rsp+28h],r15
`041cd474 4c896c2420      mov     qword ptr [rsp+20h],r13
`041cd479 e836010000      call    nt!PspAllocateThread (`041cd5b4)
kd> dq [rsp+50h] l1
fffff880`04286070  fffff880`04286310
kd> dq fffff880`04286310 l4
fffff880`04286310  00000000`00000000 00000000`00000000
fffff880`04286320  fffff880`00000000 00000144`00000000

觀察上面的執行路徑不難發現傳遞給 PspAllocateThread 函數的第 11 個參數來自 PspCreateThread 函數的 [rsp+2E8h] 第 14 個參數,而在當前函數中沒有進行任何修改和取值訪問。

而在 NtCreateThreadEx 函數中由於虛擬化設置問題暫時無法進行單步追蹤。所以通過 IDA 對其彙編代碼進行分析,再加上通過 PspAllocateThread 函數返回后的上下文,對運行現場的環境進一步的追蹤:

`403701DF loc_1403701DF:
`403701DF    mov     [rsp+748h+var_6D8], bl
`403701E3    mov     rax, [rsp+748h+arg_40]
`403701EB    mov     [rsp+748h+var_6C8], rax
`403701F3    mov     rax, [rsp+748h+arg_48]
`403701FB    mov     [rsp+748h+var_6C0], rax
`40370203    mov     rax, [rsp+748h+arg_38]
`4037020B    mov     [rsp+748h+var_6D0], rax
`40370210    mov     [rsp+748h+var_6B8], ebx
`40370217    xor     edx, edx        ; Val
`40370219    mov     r8d, 150h       ; Size
`4037021F    lea     rcx, [rsp+748h+var_198] ; Dst
`40370227    call    memset
`4037022C    test    rdi, rdi
`4037022F    jz      short loc_140370285
`40370231    mov     rax, gs:188h
`4037023A    lea     r9, [rsp+748h+var_198]
`40370242    mov     r8d, 1
`40370248    mov     dl, [rax+1F6h]
`4037024E    mov     rcx, rdi
`40370251    call    PspBuildCreateProcessContext
`40370256    test    eax, eax
`40370258    js      loc_140370396
`4037025E    lea     rax, [rsp+748h+var_70]
`40370266    bt      dword ptr [rsp+748h+var_198], 0Ch
`4037026F    cmovnb  rax, rbx
`40370273    mov     rbx, rax
`40370276    bt      dword ptr [rsp+748h+var_198], 0Eh
`4037027F    jb      loc_1403C8D38
`40370285
`40370285 loc_140370285:
`40370285    mov     [rsp+748h+var_638], 10000Bh
`40370290    mov     rax, cs:PspUserThreadStart
`40370297    mov     [rsp+748h+var_570], rax
`4037029F    mov     rax, [rsp+748h+arg_20]
`403702A7    mov     [rsp+748h+var_5E8], rax
`403702AF    mov     rax, [rsp+748h+arg_28]
`403702B7    mov     [rsp+748h+var_5E0], rax
`403702BF    mov     ecx, 2Bh
`403702C4    mov     [rsp+748h+var_62E], cx
`403702CC    mov     [rsp+748h+var_62C], cx
`403702D4    lea     eax, [rcx+28h]
`403702D7    mov     [rsp+748h+var_62A], ax
`403702DF    mov     [rsp+748h+var_628], cx
`403702E7    mov     [rsp+748h+var_626], cx
`403702EF    lea     eax, [rcx+8]
`403702F2    mov     [rsp+748h+var_630], ax
`403702FA    mov     ecx, 1F80h
`403702FF    mov     [rsp+748h+var_634], ecx
`40370306    mov     eax, 27Fh
`4037030B    mov     [rsp+748h+var_568], ax
`40370313    mov     [rsp+748h+var_550], ecx
`4037031A    lea     rax, [rsp+748h+var_6D8]
`4037031F    mov     [rsp+748h+var_6E0], rax
`40370324    and     [rsp+748h+var_6E8], 0
`4037032A    and     [rsp+748h+var_6F0], 0
`40370330    mov     dword ptr [rsp+748h+var_6F8], r12d ; __int64
`40370335    lea     rax, [rsp+748h+var_6A8]
`4037033D    mov     [rsp+748h+var_700], rax ; __int64
`40370342    lea     rax, [rsp+748h+var_668]
`4037034A    mov     [rsp+748h+var_708], rax ; __int64
`4037034F    mov     rax, qword ptr [rsp+748h+var_190]
`40370357    mov     qword ptr [rsp+748h+var_710], rax ; int
`4037035C    mov     qword ptr [rsp+748h+var_718], rbx ; int
`40370361    lea     rax, [rsp+748h+var_198]
`40370369    mov     [rsp+748h+var_720], rax ; __int64
`4037036E    and     [rsp+748h+var_728], 0
`40370374    mov     r9, r15         ; __int64
`40370377    mov     r8, r14         ; __int64
`4037037A    mov     edx, r13d       ; __int64
`4037037D    mov     rcx, rsi        ; PVOID
`40370380    call    PspCreateThread

上面的反彙編指令片段是在 IDA 中截取的。根據彙編代碼顯示,[rsp+748h+var_6E0] 是傳入 PspCreateThread 函數的第 14 個參數。其取值為 [rsp+748h+var_6D8] 局部變量的地址。var_6D8 是位於棧上的一個結構體對象,需要關注的是其中 +10 偏移的域,在稍早時候對結構體賦初值,這個域由第 9 個參數 [rsp+748h+arg_40] 賦值。

`403701DF    mov     [rsp+748h+var_6D8], bl
`403701E3    mov     rax, [rsp+748h+arg_40]
`403701EB    mov     [rsp+748h+var_6C8], rax

由第 9 個參數賦初值,那就說明這個值是由 NtCreateThreadEx 的調用者傳入的。該函數原型如下:

NTSTATUS
NTAPI
Handle_SSDT_NtCreateThreadEx(
    OUT PHANDLE                  ThreadHandle,
    IN  ACCESS_MASK              DesiredAccess,
    IN  POBJECT_ATTRIBUTES       ObjectAttributes,
    IN  HANDLE                   ProcessHandle,
    IN  LPTHREAD_START_ROUTINE   StartAddress,
    IN  LPVOID                   Parameter,
    IN  BOOL                     CreateSuspended,
    IN  ULONG                    StackZeroBits,
    IN  ULONG                    SizeOfStackCommit,
    IN  ULONG                    SizeOfStackReserve,
    OUT LPVOID                   BytesBuffer
);

第 9 個參數是 SizeOfStackCommit,但我在 Hook 處理函數中監控這個參數,它的值始終是處於正常範圍的數值,從未出現前面分析中的 0xFFFFF88000000000 這樣的數據。突然注意到在 Hook 處理函數中調用原函數時對棧上的參數進行賦值的代碼:

`050721af 488b8424d0000000 mov     rax,qword ptr [rsp+0D0h]
`050721b7 4889442450       mov     qword ptr [rsp+50h],rax
`050721bc 8b8424c8000000   mov     eax,dword ptr [rsp+0C8h]
`050721c3 89442448         mov     dword ptr [rsp+48h],eax
`050721c7 8b8424c0000000   mov     eax,dword ptr [rsp+0C0h]
`050721ce 89442440         mov     dword ptr [rsp+40h],eax
`050721d2 8b8424b8000000   mov     eax,dword ptr [rsp+0B8h]
`050721d9 89442438         mov     dword ptr [rsp+38h],eax
`050721dd 8b8424b0000000   mov     eax,dword ptr [rsp+0B0h]
`050721e4 89442430         mov     dword ptr [rsp+30h],eax
`050721e8 488b8424a8000000 mov     rax,qword ptr [rsp+0A8h]
`050721f0 4889442428       mov     qword ptr [rsp+28h],rax
`050721f5 488b8424a0000000 mov     rax,qword ptr [rsp+0A0h]
`050721fd 4889442420       mov     qword ptr [rsp+20h],rax
`05072202 4c8b8c2498000000 mov     r9,qword ptr [rsp+98h]
`0507220a 4c8b842490000000 mov     r8,qword ptr [rsp+90h]
`05072212 8b942488000000   mov     edx,dword ptr [rsp+88h]
`05072219 488b8c2480000000 mov     rcx,qword ptr [rsp+80h]
`05072221 ff542468         call    qword ptr [rsp+68h]

上面代碼中 mov dword ptr [rsp+40h], eax 這條指令對 SizeOfStackCommit 參數進行傳值。在傳值之前我無意中看了一下 rsp+40h 地址的原值:

kd> dq [rsp+40h] l1
fffff880`0310ea30  fffff880`0310ea98

原來如此,由於 Hook 處理函數和原函數指針類型定義失誤,將這個參數定義成了 ULONG32 類型,所以在傳參時只通過 eax 進行賦值,棧上的參數位置高 32 位被忽略並保持原值;但在實際的 NtCreateThreadEx 函數中,應是將這個參數作為 ULONG_PTR 進行解析,在 64 位下應是 ULONG64 寬度,所以將參數中沒有清零的高 32 位也作為參數值的一部分了,這就最終導致了前面的錯誤狀態碼。而這次的錯誤和虛擬化無關。

真是一次坑爹的分析。


转载请注明:IAMCOOL » HOOK NtCreateThreadEx 導致 0xC00000F2

0 0 vote
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x