分析最近TrickBot的马时遇到了32位进程通过0x33段进入64位环境执行一段64位shellcode,直接让我放弃了用x32调试器继续调试的想法,指令、寄存器面目全非。以此开始了解了名为“HEAVEN’S GATE”的技术。
首先先了解一下什么是wow64。

WOW64

Windows on Windows64:64位进程中的32位子系统(https://zh.wikipedia.org/wiki/WoW64)。

  • 完整的子系统包括32位主映像、32位DLL,都运行在进程的32位地址空间中。
  • 通过NTDLL、其他DLL与64位环境通信,使WOW64子系统兼容于64位进程中。

    WOW64如何工作

  • 每个WoW64进程都包含NTDLL的本机版本,WoW64使用三个动态链接库(wow64.dll、wow64cpu.dll、wow64win.dll)实现兼容必需的接口。

  • 32位ntdll不以任何方式发送系统调用或直接与操作系统通信。 相反,它调用这些作为兼容的DLL,它们启动一系列调用和跳转,切换到64位模式,并修改函数参数以使它们兼容64位。
  • 在64位NTDLL内部的API调用中调度syscall,完成调用。

    跟踪跳转

    查看一个32位进程模块列表,其中有前面提到了3个wow64接口dll,并且存在俩个NTDLL.dll,其中之一位于64位地址空间中。
    image.png

在32位API函数中放置一个断点,并查看它的调用(https://docs.microsoft.com/en-us/windows/win32/winprog64/debugging-wow64):

  1. 0:000>.reload /f
  2. 0:000>.load wow64exts
  3. 0:000> !wow64exts.sw
  4. Switched to Guest (WoW) mode
  5. 0:000:x86> bp NtAllocateVirtualMemory
  6. ...
  7. ntdll_77a90000!NtAllocateVirtualMemory:
  8. 77afde70 b818000000 mov eax,18h
  9. 0:000:x86> u
  10. ntdll_77a90000!NtAllocateVirtualMemory:
  11. 77afde70 b818000000 mov eax,18h
  12. 77afde75 ba3024b177 mov edx,offset ntdll_77a90000!Wow64SystemServiceCall (77b12430)
  13. 77afde7a ffd2 call edx
  14. 77afde7c c21800 ret 18h

API函数没有执行syscall,而是调用Wow64SystemServiceCall:

  1. 0:000:x86> u ntdll_77a90000!Wow64SystemServiceCall
  2. ntdll_77a90000!Wow64SystemServiceCall:
  3. 77b12430 ff251812ba77 jmp dword ptr [ntdll_77a90000!Wow64Transition (77ba1218)]

导出函数Wow64Transition指向wow64cpu!KiFastSystemCall,该函数实现从x86到x64模式的转换(https://bbs.pediy.com/thread-189808.htm)。

  1. 0:000:x86> u poi(ntdll_77a90000!Wow64Transition)
  2. wow64cpu!KiFastSystemCall:
  3. 729f7000 ea09709f723300 jmp 0033:729F7009
  4. 729f7007 0000 add byte ptr [eax],al
  5. 729f7009 41 inc ecx
  6. 729f700a ffa7f8000000 jmp dword ptr [edi+0F8h]

跳转CS:0x33,下面继续单步。

  1. 0:000:x86> p
  2. wow64cpu!KiFastSystemCall:
  3. 6e967000 ea0970966e3300 jmp 0033:6E967009
  4. 0:000:x86> p
  5. wow64cpu!KiFastSystemCall+0x9:
  6. 00000000`6e967009 41ffa7f8000000 jmp qword ptr [r15+0F8h] ds:00000000`6e9646c8={wow64cpu!CpupReturnFromSimulatedCode (00000000`6e961cb6)}
  7. 0:000> u
  8. wow64cpu!KiFastSystemCall+0x9:
  9. 00000000`6e967009 41ffa7f8000000 jmp qword ptr [r15+0F8h]
  10. 00000000`6e967010 0000 add byte ptr [rax],al
  11. 00000000`6e967012 0000 add byte ptr [rax],al
  12. 00000000`6e967014 0000 add byte ptr [rax],al
  13. 00000000`6e967016 0000 add byte ptr [rax],al
  14. 00000000`6e967018 0000 add byte ptr [rax],al
  15. 00000000`6e96701a 0000 add byte ptr [rax],al
  16. 00000000`6e96701c 0000 add byte ptr [rax],al

现在开始使用单步(p)和运行到分支(ph)命令执行寻找NtAllocateVirtualMemory。

  1. 0:000:x86> p
  2. wow64cpu!KiFastSystemCall+0x9:
  3. 00000000`6e967009 41ffa7f8000000 jmp qword ptr [r15+0F8h] ds:00000000`6e9646c8={wow64cpu!CpupReturnFromSimulatedCode (00000000`6e961cb6)}
  4. 0:000> p
  5. wow64cpu!CpupReturnFromSimulatedCode:
  6. 00000000`6e961cb6 4987e6 xchg rsp,r14
  7. 0:000> ph
  8. wow64cpu!TurboDispatchJumpAddressStart+0x5:
  9. 00000000`6e961ce8 41ff24cf jmp qword ptr [r15+rcx*8] ds:00000000`6e9645d0={wow64cpu!ServiceNoTurbo (00000000`6e961cec)}
  10. 0:000> p
  11. wow64cpu!ServiceNoTurbo:
  12. 00000000`6e961cec 8bc8 mov ecx,eax
  13. 0:000> u
  14. wow64cpu!ServiceNoTurbo:
  15. 00000000`6e961cec 8bc8 mov ecx,eax
  16. 00000000`6e961cee 498bd3 mov rdx,r11
  17. 00000000`6e961cf1 ff1569240000 call qword ptr [wow64cpu!_imp_Wow64SystemServiceEx (00000000`6e964160)]
  18. 00000000`6e961cf7 41894534 mov dword ptr [r13+34h],eax
  19. 00000000`6e961cfb e9dffeffff jmp wow64cpu!RunSimulatedCode+0x2f (00000000`6e961bdf)
  20. wow64cpu!ThunkNone:
  21. 00000000`6e961d00 cc int 3
  22. wow64cpu!GetCurrentProcessorNumber:
  23. 00000000`6e961d01 b853000000 mov eax,53h
  24. 00000000`6e961d06 0f03c0 lsl eax,eax
  25. 0:000> ph
  26. wow64cpu!ServiceNoTurbo+0x5:
  27. 00000000`6e961cf1 ff1569240000 call qword ptr [wow64cpu!_imp_Wow64SystemServiceEx (00000000`6e964160)] ds:00000000`6e964160={wow64!Wow64SystemServiceEx (00000000`6e976d50)}
  28. 0:000> t
  29. wow64!Wow64SystemServiceEx:
  30. 00000000`6e976d50 48895c2418 mov qword ptr [rsp+18h],rbx ss:00000000`0009ef80=0000000000500fe8
  31. 0:000> ph
  32. wow64!Wow64SystemServiceEx+0x7b:
  33. 00000000`6e976dcb 0f87883c0100 ja wow64!Wow64KiUserCallbackDispatcher+0x2c09 (00000000`6e98aa59) [br=0]
  34. 0:000> ph
  35. wow64!Wow64SystemServiceEx+0xa1:
  36. 00000000`6e976df1 740a je wow64!Wow64SystemServiceEx+0xad (00000000`6e976dfd) [br=0]
  37. 0:000> ph
  38. wow64!Wow64SystemServiceEx+0xa3:
  39. 00000000`6e976df3 0f88513c0100 js wow64!Wow64KiUserCallbackDispatcher+0x2bfa (00000000`6e98aa4a) [br=0]
  40. 0:000> ph
  41. wow64!Wow64SystemServiceEx+0x112:
  42. 00000000`6e976e62 756a jne wow64!Wow64SystemServiceEx+0x17e (00000000`6e976ece) [br=0]
  43. 0:000> ph
  44. wow64!Wow64SystemServiceEx+0x121:
  45. 00000000`6e976e71 7438 je wow64!Wow64SystemServiceEx+0x15b (00000000`6e976eab) [br=0]
  46. 0:000> ph
  47. wow64!Wow64SystemServiceEx+0x12d:
  48. 00000000`6e976e7d 7433 je wow64!Wow64SystemServiceEx+0x162 (00000000`6e976eb2) [br=0]
  49. 0:000> ph
  50. wow64!Wow64SystemServiceEx+0x139:
  51. 00000000`6e976e89 742e je wow64!Wow64SystemServiceEx+0x169 (00000000`6e976eb9) [br=0]
  52. 0:000> ph
  53. wow64!Wow64SystemServiceEx+0x145:
  54. 00000000`6e976e95 7429 je wow64!Wow64SystemServiceEx+0x170 (00000000`6e976ec0) [br=0]
  55. 0:000> ph
  56. wow64!Wow64SystemServiceEx+0x151:
  57. 00000000`6e976ea1 7424 je wow64!Wow64SystemServiceEx+0x177 (00000000`6e976ec7) [br=0]
  58. 0:000> ph
  59. wow64!Wow64SystemServiceEx+0x153:
  60. 00000000`6e976ea3 ffd6 call rsi {wow64!whNtAllocateVirtualMemory (00000000`6e976a40)}

单步,看到call [wow64cpu!_imp_Wow64SystemServiceEx],步入,运行到call中断。

  1. 0:000> pc
  2. wow64!Wow64SystemServiceEx+0x153:
  3. 00000000`6e976ea3 ffd6 call rsi {wow64!whNtAllocateVirtualMemory (00000000`6e976a40)}

运行到分支处中断:_imp_NtAllocateVirtualMemory

  1. 0:000> ph
  2. wow64!whNtAllocateVirtualMemory+0xa2:
  3. 00000000`6e976ae2 ff15c8f50200 call qword ptr [wow64!_imp_NtAllocateVirtualMemory (00000000`6e9a60b0)] ds:00000000`6e9a60b0={ntdll!NtAllocateVirtualMemory (00007ffc`b1555150)}

查看地址指向的汇编指令:_imp_NtAllocateVirtualMemory,在这里调用**syscall**。

  1. 0:000> u poi(wow64!_imp_NtAllocateVirtualMemory)
  2. ntdll!NtAllocateVirtualMemory:
  3. 00007ffc`b1555150 4c8bd1 mov r10,rcx
  4. 00007ffc`b1555153 b818000000 mov eax,18h
  5. 00007ffc`b1555158 f604250803fe7f01 test byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1
  6. 00007ffc`b1555160 7503 jne ntdll!NtAllocateVirtualMemory+0x15 (00007ffc`b1555165)
  7. 00007ffc`b1555162 0f05 syscall
  8. 00007ffc`b1555164 c3 ret
  9. 00007ffc`b1555165 cd2e int 2Eh
  10. 00007ffc`b1555167 c3 ret

查看堆栈有如下调用关系

  1. 0:000> t
  2. ntdll!NtAllocateVirtualMemory:
  3. 00007ffc`b1555150 4c8bd1 mov r10,rcx
  4. 0:000> k
  5. # Child-SP RetAddr Call Site
  6. 00 00000000`0009e5f8 00000000`6e976ae8 ntdll!NtAllocateVirtualMemory
  7. 01 00000000`0009e600 00000000`6e976ea5 wow64!whNtAllocateVirtualMemory+0xa8
  8. 02 00000000`0009e6b0 00000000`6e961cf7 wow64!Wow64SystemServiceEx+0x155
  9. 03 00000000`0009ef70 00000000`6e98bfa1 wow64cpu!ServiceNoTurbo+0xb
  10. 04 00000000`0009f020 00000000`6e97cbb0 wow64!Wow64KiUserCallbackDispatcher+0x4151
  11. 05 00000000`0009f0a0 00007ffc`b1541791 wow64!Wow64LdrpInitialize+0x120
  12. 06 00000000`0009f350 00007ffc`b1577b28 ntdll!LdrpInitializeProcess+0x1551
  13. 07 00000000`0009f750 00007ffc`b1528d6e ntdll!_LdrpInitialize+0x4ed64
  14. 08 00000000`0009f7d0 00000000`00000000 ntdll!LdrInitializeThunk+0xe

image.png

jmp 0x33

在64位窗口上的每个进程中有2个代码段:

  • 0x23=x86模式
  • 0x33=x64模式

这里call far 33:xxxx,使处理器切换到x64。 从这里开始,我们可以与64位函数通信并执行syscall。
HEAVEN'S GATE - 图3

应用程序怎么知道天堂之门在哪里的:通过FS寄存器,FS:0xC0 or TIB + 0xC0(https://en.wikipedia.org/wiki/Win32_Thread_Information_Block)。
image.png

利用方式

许多安全产品都了安装钩子来监视系统函数,在WoW64进程中,这些钩子只安装在32位函数上,WoW64过渡的整个阶段是不受监控的。

HEAVEN’S GATE

写入成功
image.png

火绒剑监控事件如下
image.png

hook

hook HEAVEN’S GATE,判断调用号筛选目标函数
image.png
缓解措施

  • Kernel hooks
  • Kernel callbacks
  • Hook 64-bit NTDLL