天堂之门

前置知识

Windows 架构概览

用户层 内核层
32 位或 64 位进程 始终为 64 位内核
  • Windows 的内核(ntoskrnl.exe)永远是 64 位
  • 即使运行的是 32 位程序,它也是通过 WOW64 子系统(Windows-on-Windows64) 模拟运行的

WOW64

WOW64 是 Windows x64 系统的一个兼容子系统,用于支持 32 位应用的运行。

在 64 位系统中为 32 位程序提供一个运行时环境。

WOW64 的三大组件:

模块 位数 作用
wow64.dll 32 位 桥接层,将 32 → 64 位参数封装
wow64win.dll 64 位 处理 GUI / 用户模式接口
wow64cpu.dll 64 位 CPU 上的 thunk 机制(切换执行模式)
  • 拦截 32 位程序对系统调用的请求
  • 转换成 64 位调用,并在内核中执行
  • 再把结果转换回 32 位,返回给原程序

CPU 分段模型

  • x86 CPU 使用段选择子(Segment Selector)控制代码在哪个段执行。

  • 每个代码段有一个描述符,控制:基址、权限、位数(32/64)等

    • 0x23是 32 位代码段(常见于用户层)

    • 0x33是 64 位代码段(WOW64 环境中的64段)

ret 与 retf

指令 功能
ret 只 pop 一个返回地址,返回当前代码段内
retf pop 返回地址 + 段选择子,返回其他段(跨段)
1
2
3
push 0x33         ; 64 位段选择子
push addr ; 目标RIP(64位代码地址)
retf ; --> 切换到 64 位代码段

改变 CS:RIP 为 0x33:addr,从而跳到 64 位模式

retf是32转64,retfq是64转32位。

Heaven’s Gate

定义

天堂之门Heaven’s Gate 是一种在32位WoW64进程中执行64位代码,以及直接调用64位WIN32 API函数的技术。

  • 在 32 位进程中执行 64 位系统调用
  • 绕过某些对 32 位 API Hook 的监控(例如 ntdll.dll inline hook)

原理

32 位程序执行过程

1
2
3
4
5
6
7
8
9
10
11
12
13
[32位程序]

user32.dll(32位)

kernel32.dll(32位)

ntdll.dll(32位) ← EDR经常hook这里

WOW64(模式切换)

ntdll.dll(64位) ← 真正执行 syscall

syscall → 内核函数
  • 在 32 位系统里,进入内核常用的是 int 0x2e
  • 在 64 位系统中,进入内核的是 syscall 指令

WOW64 切换流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   32位程序


ntdll.dll (32位)


wow64.dll (32位)

▼ ← 通过 INT 2E or Wow64Transition
CPU 切换到 64 位(via wow64cpu.dll)


ntdll.dll (64位)


syscall


ntoskrnl.exe(内核)

Wow64Transition:通过 CPU 特殊指令和上下文转换,让用户态线程从 32 位代码段跳入 64 位段执行

天堂之门的实现思路

1、将cs段寄存器设为0x33,切换到64位模式
2、从gs:0x60读取64位PEB
3、从64位PEB中定位64位ntdll基址
4、遍历ntdll64导出表,读取ZwOpenProcess函数地址
5、构造64位函数调用

如果需要调用的是ntdll之外的函数,以kernel32.dll中的CreateFile函数为例,还需要:
1、遍历ntdll64导出表,读取LdrLoadDll函数地址
2、调用LdrLoadDll(“kernel32.dll”)加载64位kernel32.dll
3、从64位的kernel32中读取GetProcAddress等函数,获取CreateFile函数地址
4、调用CreateFile函数

1
2
3
push 0x33         ; 64 位代码段
push offset_64 ; 64 位代码地址
retf ; 真正跳到 64 位执行

拜读文章:
[原创]天堂之门 (Heaven’s Gate) C语言实现
WoW64 内部结构
天堂之门

地狱之门

地狱之门是一种在64 位进程中主动构造系统调用指令 syscall 的方法,目的是绕过用户层 API(如 ntdll.dll)的 Hook 与监控。

传统的系统调用路径:

1
Program → ntdll.dll → syscall

地狱之门:

1
Program → 读取 ntdll.dll → 解析 syscall ID → 手动 syscall