美文网首页
Unicorn - 初探 (一)

Unicorn - 初探 (一)

作者: 喝豆腐脑加糖 | 来源:发表于2019-10-09 10:56 被阅读0次
    保护全开的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 - 初探 (一)

          本文链接:https://www.haomeiwen.com/subject/dnbwpctx.html