主动堆栈欺骗
字数 1725 2025-08-29 22:41:01
主动堆栈欺骗技术详解
1. 核心概念
主动堆栈欺骗(Active Stack Spoofing)是一种高级的反调试和反检测技术,其核心在于通过伪造多个栈帧,使栈回溯时呈现出函数被多次调用的假象,而实际上这些调用并未真实发生。
关键特点:
- 伪造多个栈帧结构
- 修改RSP寄存器指向伪造的栈帧
- 利用系统函数的固定偏移量
- 保持堆栈平衡以避免崩溃
2. 基本原理
2.1 栈帧结构
在x64架构中,函数调用时:
- 调用者将返回地址压入栈中
- 被调用函数通常通过
sub rsp, X分配栈空间 - 函数返回时通过
add rsp, X释放空间并ret返回
2.2 伪造原理
- 手动构造看似合法的栈帧
- 将RSP指向伪造的栈帧顶部
- 包含伪造的返回地址链
- 保持堆栈平衡(分配与释放的空间一致)
3. 技术实现细节
3.1 准备工作
-
获取关键函数地址:
RtlUserThreadStart及其偏移量(示例中为+0x21)BaseThreadInitThunk- 目标函数地址(如
printf)
-
计算栈空间大小:
- 通过
.pdata段的PRUNTIME_FUNCTION和UNWIND_INFO解析 - 处理各种
UWOP_*操作码计算总栈大小
- 通过
3.2 关键数据结构
typedef struct _UNWIND_HISTORY_TABLE {
ULONG Count;
UCHAR Search;
ULONG LowAddress;
ULONG HighAddress;
PRUNTIME_FUNCTION Entry[MAX_UNWIND_HISTORY_TABLE_ENTRIES];
} UNWIND_HISTORY_TABLE, *PUNWIND_HISTORY_TABLE;
3.3 栈空间计算逻辑
- 检查
pRuntimeFunction有效性 - 解析
UnwindData获取PUNWIND_INFO - 遍历
UnwindCode处理不同操作码:UWOP_PUSH_NONVOLUWOP_ALLOC_SMALLUWOP_ALLOC_LARGEUWOP_SET_FPREG
- 处理
UNW_FLAG_CHAININFO标志的级联函数 - 返回总栈大小(包括8字节返回地址)
4. 具体实现步骤
4.1 跳板准备
- 查找
jmp [rbx]指令(机器码\xFF\x23) - 存储跳板地址到
p.trampoline
4.2 Spoof函数实现
Spoof proc
pop rax ; 保存返回地址到rax
mov rdi, [rsp+20h] ; 获取结构体指针
mov rsi, [rsp+28h] ; 获取目标函数地址
; ... 其他实现细节
Spoof endp
4.3 参数处理
- 前四个参数通过
rcx, rdx, r8, r9传递 - 其余参数通过栈传递(影子空间预留0x20字节)
- 多参数处理:
- 使用
r11记录已处理参数数量 - 通过
r13定位额外参数位置 - 计算所需栈空间并调整
rsp
- 使用
4.4 伪造栈帧
- 分配200字节空间
push 0截断真实返回地址- 构造伪造的返回地址链:
RtlUserThreadStart帧BaseThreadInitThunk帧- 跳板帧
- 保存真实返回地址到
r12(非易失性寄存器)
4.5 执行流程
- 将跳板地址(
jmp rbx)压入伪造栈帧顶部 - 执行目标函数(如
printf) - 函数返回时跳转到跳板地址
- 通过
jmp rbx返回到修复代码
5. 关键点解析
5.1 返回地址处理
- 正常
call指令会压入返回地址 - 使用
jmp时需手动压入伪造返回地址 - 通过精确控制
rsp确保执行流正确返回
5.2 堆栈平衡
- 每个伪造的栈帧必须保持分配与释放的空间一致
- 考虑影子空间(0x20字节)的影响
- 确保
ret时rsp指向正确的伪造返回地址
5.3 系统调用处理
- 直接传递
syscall地址(如pNtAllocateVirtualMemory + 0x12) - 模拟内核函数调用前的准备工作
6. 实际应用示例
6.1 LoudSunRun项目分析
- 获取
printf地址 - 查找
jmp [rbx]跳板 - 计算各函数栈大小
- 构造伪造调用链:
Gadget Frame (jmp rbx) BaseThreadInitThunk RtlUserThreadStart
6.2 多参数处理示例
mov r13, rsp
add r13, 30h ; 定位第七个参数
mov r14, 200h + 8 ; 基础空间 + push 0
add r14, [三个函数栈大小] ; 添加各函数栈空间
sub r14, 20h ; 减去影子空间
; ... 参数复制逻辑
7. 注意事项
-
系统版本差异:
- 关键函数偏移量随系统版本变化
- 需动态获取或针对特定版本调整
-
寄存器使用:
- 使用非易失性寄存器(
r12-r15)保存关键值 - 易失性寄存器可能在调用中被修改
- 使用非易失性寄存器(
-
调试器兼容性:
- 某些汇编写法在x64dbg中不合法
- 依赖汇编器的语法容错能力
8. 总结
主动堆栈欺骗是一种高级的调用栈操纵技术,通过精心构造伪造的栈帧和精确控制执行流,可以实现:
- 隐藏真实调用链
- 绕过基于栈回溯的检测机制
- 实现更隐蔽的函数调用
关键技术点在于对x64调用约定、栈帧结构和返回机制的深入理解,以及对寄存器、内存布局的精确控制。