Unicorn - 初探 (一)

Unicorn - 初探 (一)_第1张图片
保护全开的llvm程序

对于ollvm的恢复基本基于angr和miasm,但对于arm的恢复,支持并不理想;所以便看到了另外的一框架unicorn。

LLVM将混淆之后的程序分为以下几个模块:

        1.函数的开始地址为序言的地址
        2.序言的后继为主分发器
        3.后继为主分发器的块为预处理器
        4.后继为预处理器的块为真实块
        5.无后继的块为retn块
        6.剩下的为无用块

所以我们去混淆的大概思路就是按照几个模块找到函数地址,将真实块留下,retn块留下,之后那些无用块全部置为nop;关键就是对真实块和虚拟块的识别,之后再对真实块中两种 分支顺序 关系的识别,使用符号执行模拟两者之间的关系。

unicorn的优点

  • 支持多种架构: Arm, Arm64 (Armv8), M68K, Mips, Sparc, & X86 (include X86_64).
  • 对Windows和*nix系统(已确认包含Mac OSX, Linux, *BSD & Solaris)的原生支持
  • 具有平台独立且简洁易于使用的API
  • 使用JIT编译技术, 性能表现优异
 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple unicorn
 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple capstone //使用capstone进行反汇编

这篇 只 先对unicorn熟悉了解下

官方文档给的例子

#coding:utf-8
from unicorn import *
from unicorn.arm_const import *
 
ARM_CODE = b"\x37\x00\xa0\xe3\x03\x10\x42\xe0"
 
 
# mov r0, #0x37;
# sub r1, r2, r3
# Test ARM
 
# callback for tracing instructions
def hook_code(uc, address, size, user_data):
    print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" % (address, size))
 
 
def test_arm():
    print("Emulate ARM code")
    try:
        # Initialize emulator in ARM mode
        mu = Uc(UC_ARCH_ARM, UC_MODE_THUMB) #创建UC对象
 
        # map 2MB memory for this emulation 创建2MB的内存空间
        ADDRESS = 0x10000
        mu.mem_map(ADDRESS, 2 * 0x10000)
        mu.mem_write(ADDRESS, ARM_CODE) #将前面定义的ARM_CODE传入内存空间内,只支持byte
 
        #未开机前寄存器赋值
        mu.reg_write(UC_ARM_REG_R0, 0x1234)
        mu.reg_write(UC_ARM_REG_R2, 0x6789)
        mu.reg_write(UC_ARM_REG_R3, 0x3333)
        #添加指令集Hook
#        mu.hook_add(UC_HOOK_CODE, hook_code, begin=ADDRESS, end=ADDRESS)
 
        # emulate machine code in infinite time,开机
        mu.emu_start(ADDRESS, ADDRESS + len(ARM_CODE))
        print("已开机")
        #获取计算器结果
        r0 = mu.reg_read(UC_ARM_REG_R0)
        r1 = mu.reg_read(UC_ARM_REG_R1)
        print(">>> R0 = 0x%x" % r0)
        print(">>> R1 = 0x%x" % r1)
    except UcError as e:
        print("ERROR: %s" % e)
 
test_arm()

***************************************
结果如下:
Emulate ARM code
已开机
>>> R0 = 0x37
>>> R1 = 0x3456

通过上述脚本来了解各个函数的作用

R0 寄存器为 0x37,R1 为 0x3456

之后使用capstone 来对操作的代码进行反汇编,查看进行了什么操作

from capstone import *
from capstone.arm import *
 
CODE = b"\x37\x00\xa0\xe3\x03\x10\x42\xe0"
 
md = Cs(CS_ARCH_ARM, CS_MODE_ARM)
for i in md.disasm(CODE, 0x1000):
    print("%x:\t%s\t%s" % (i.address, i.mnemonic, i.op_str))

********************************************************************
结果:
1000:   mov r0, #0x37
1004:   sub r1, r2, r3

你可能感兴趣的:(Unicorn - 初探 (一))