sakuraのall fuzz : afl-unicorn
字数 1026 2025-08-24 16:48:16
AFL-Unicorn 模糊测试技术详解
1. Unicorn引擎基础
1.1 Unicorn简介
Unicorn是一个轻量级、多平台、多架构的CPU仿真框架,基于QEMU开发。它允许我们在不依赖真实硬件的情况下模拟执行二进制代码。
1.2 基本API使用
from unicorn import *
from unicorn.x86_const import *
# 初始化Unicorn实例
mu = Uc(UC_ARCH_X86, UC_MODE_64) # 指定架构为x86-64
# 内存映射
BASE = 0x400000
STACK_ADDR = 0x0
STACK_SIZE = 1024*1024
mu.mem_map(BASE, 1024*1024) # 映射代码段
mu.mem_map(STACK_ADDR, STACK_SIZE) # 映射栈空间
# 写入程序到内存
mu.mem_write(BASE, read("./fibonacci"))
# 设置寄存器
mu.reg_write(UC_X86_REG_RSP, STACK_ADDR + STACK_SIZE - 1)
# 添加hook
def hook_code(mu, address, size, user_data):
print('>>> Tracing instruction at 0x%x, size=0x%x' %(address, size))
mu.hook_add(UC_HOOK_CODE, hook_code)
# 开始仿真执行
mu.emu_start(0x00000000004004E0, 0x0000000000400582)
1.3 常见问题解决
问题1:BSS段未初始化
解决方案:跳过相关指令或手动初始化BSS段
instructions_skip_list = [0x00000000004004EF, 0x00000000004004F6]
def hook_code(mu, address, size, user_data):
if address in instructions_skip_list:
mu.reg_write(UC_X86_REG_RIP, address+size)
问题2:系统调用/库函数缺失
解决方案:hook关键函数,模拟其行为
def hook_code(mu, address, size, user_data):
if address == 0x400560: # putchar调用点
c = mu.reg_read(UC_X86_REG_RDI) # 获取第一个参数
print(chr(c)) # 模拟输出
mu.reg_write(UC_X86_REG_RIP, address+size) # 跳过调用
2. AFL-Unicorn集成
2.1 基本原理
AFL-Unicorn结合了AFL的模糊测试能力和Unicorn的仿真能力,工作流程:
- AFL生成变异输入
- 输入被写入仿真内存的固定地址
- Harness从该地址读取数据并执行目标代码
- 出现崩溃时模拟崩溃行为通知AFL
2.2 典型Harness结构
import argparse
from unicorn import *
from unicorn.x86_const import *
import unicorn_loader
# 配置参数
START_ADDRESS = 0x0804D106 # 起始地址
END_ADDRESS = 0x0804D120 # 结束地址
def main():
# 初始化
uc = unicorn_loader.AflUnicornEngine(args.context_dir)
# 启动fork server
uc.emu_start(START_ADDRESS, 0, 0, count=1)
# 处理输入
input_content = open(args.input_file, 'rb').read()
buf_addr = unicorn_heap.malloc(len(input_content))
uc.mem_write(buf_addr, input_content)
# 设置输入参数
uc.reg_write(UC_X86_REG_EAX, buf_addr) # pData
uc.reg_write(UC_X86_REG_DL, len(input_content)) # dataLen
# 执行测试
try:
uc.emu_start(START_ADDRESS, END_ADDRESS)
except UcError as e:
uc.force_crash(e) # 通知AFL崩溃
2.3 关键Hook点
1. 绕过校验
CHKSUM_CMP_ADDR = 0x0804DA45
CHKSUM_PASSED_ADDR = 0x0804DA52
def hook_code(uc, address, size, user_data):
if address == CHKSUM_CMP_ADDR:
uc.reg_write(UC_X86_REG_EIP, CHKSUM_PASSED_ADDR)
2. 模拟malloc
def hook_code(uc, address, size, user_data):
if address == MALLOC_ENTRY:
size = struct.unpack("<I", uc.mem_read(uc.reg_read(UC_X86_REG_ESP) + 4, 4))[0]
retval = unicorn_heap.malloc(size)
uc.reg_write(UC_X86_REG_EAX, retval)
uc.reg_write(UC_X86_REG_EIP, struct.unpack("<I", uc.mem_read(uc.reg_read(UC_X86_REG_ESP), 4))[0])
3. 跳过复杂函数
def hook_code(uc, address, size, user_data):
if address == PRINTF_ENTRY:
uc.reg_write(UC_X86_REG_EIP, struct.unpack("<I", uc.mem_read(uc.reg_read(UC_X86_REG_ESP), 4))[0])
uc.reg_write(UC_X86_REG_ESP, uc.reg_read(UC_X86_REG_ESP) + 4)
3. 实战案例:FSK_Messaging_Service
3.1 目标分析
目标函数:cgc_receive_packet
void cgc_receive_packet(uint8_t *pData, uint8_t dataLen, uint16_t packetCRC) {
// 校验checksum
uint16_t check_checksum = cgc_simple_checksum16(pData, dataLen);
if (packetCRC != check_checksum) return;
// 处理packet
for(int i=0; i<MAX_PACKET_HANDLERS; i++) {
if (g_packetHandlers[i].type == pData[0]) {
tSinglePacketData *pNewPacket = cgc_add_new_packet();
cgc_memcpy(pNewPacket->buf, pData+1, dataLen-1); // 潜在溢出点
break;
}
}
}
3.2 漏洞挖掘步骤
- Dump进程上下文
gdb ./FSK_Messaging_Service
(gdb) b *0x804D106
(gdb) source unicorn_dumper_gdb.py
- 构建Harness
# 配置关键地址
START_ADDRESS = 0x0804D106
END_ADDRESS = 0x0804D120
CHKSUM_CMP_ADDR = 0x0804DA45
CHKSUM_PASSED_ADDR = 0x0804DA52
MALLOC_ENTRY = 0x08049C40
PRINTF_ENTRY = 0x0804AA60
# 输入约束
if len(input_content) > 0xFF: # 限制输入大小
return
- 运行Fuzzing
afl-fuzz -U -m none -i testcase/ -o fuzz_out/ -- python harness.py context_dir @@
3.3 漏洞分析
通过跟踪执行流发现cgc_memcpy未对dataLen进行校验,导致可以越界写入pNewPacket->buf(大小仅64字节)。构造特殊输入可触发堆溢出。
4. 最佳实践
- 输入约束:合理限制输入大小和格式
- 关键Hook:精确hook校验点和危险函数
- 执行跟踪:选择性记录关键指令执行信息
- 崩溃分析:结合原始程序调试崩溃样本
- 性能优化:减少不必要的hook和日志输出
5. 局限性
- 复杂环境模拟困难(如多线程、系统调用)
- 性能开销较大
- 需要准确dump目标执行上下文
- 崩溃路径分析复杂
6. 扩展学习
参考资源:
- Unicorn官方文档:http://www.unicorn-engine.org/
- AFL-Unicorn项目:https://github.com/Battelle/afl-unicorn
- 高级Hook技巧:http://eternal.red/2018/unicorn-engine-tutorial/
- 实战案例:https://hackernoon.com/afl-unicorn-part-2-fuzzing-the-unfuzzable-bea8de3540a5