Unicorn 初探

前言

笔者由于对IOT比较感兴趣,故经常需要模拟一些IOT的固件,之前我习惯直接直接使用qemu对固件进行模拟。这几天由于任务需要接触了一下unicorn,一个轻量级, 多平台, 多架构的CPU 模拟器框架。它基于qemu,但是提供了很多API这使得我们可以方便的读写寄存器的值等内容。我们可以通过它进行调用目标二进制中的目标函数、用于模糊测试、模拟执行一些混淆代码等等。

安装

笔者更偏向于使用python,故在linux可以通过如下方法安装。对于那些想要使用C的用户, 则可能需要去官网查看文档编译源码包。

pip install unicorn

python常用API

模拟器初始化:Uc(arch, mode)
内存映射:mem_map(address, size, perms=uc.UC_PROT_ALL)
向内存中写入数据:mem_write(address, data)
从内存中读出数据:mem_read(address, size)
向寄存器中写入值:reg_write(reg_id, value)
从寄存器中读出值:reg_read(reg_id)
添加hook:hook_add(htype, callback, user_data=None, begin=1, end=0, arg1=0)

初次使用Unicorn模拟程序执行

hxp CTF 2017 Fibonacci为例

from unicorn import *
from unicorn.x86_const import *


mu = Uc(UC_ARCH_X86, UC_MODE_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, open('./fibonacci','rb').read())
mu.reg_write(UC_X86_REG_RSP, STACK_ADDR + STACK_SIZE - 1)

instructions_skip_list = [0x00000000004004EF, 0x00000000004004F6, 0x0000000000400502, 0x000000000040054F]

def hook_code(mu, address, size, user_data):
	#print('>>> Tracing instruction at 0x%x, instruction size = 0x%x' %(address, size))

	if address in instructions_skip_list:
		mu.reg_write(UC_X86_REG_RIP, address+size)
	
	elif address == 0x400560 or address == 0x400575:
		c = mu.reg_read(UC_X86_REG_RDI)
		print(chr(c))
		mu.reg_write(UC_X86_REG_RIP, address+size)


mu.hook_add(UC_HOOK_CODE, hook_code)

mu.emu_start(0x4004E0, 0x400582)

posted @ 2023-02-14 12:08  狒猩橙  阅读(157)  评论(0编辑  收藏  举报