unicorn

unicorn

相关链接

unicorn官网

Unicorn

官方教程

Programming with C & Python languages

api文档

Unicorn-Engine-Documentation/Unicorn-Engine Documentation.md at master · kabeor/Unicorn-Engine-Documentation

使用方法

在python下的基本使用方法如下(以arm为例)

from unicorn import *
from unicorn.arm_const import *

code =b'\x01\x10\xa0\xe3\x02 \xa0\xe3\x010B\xe0'
# mov r1, #1
# mov r2, #2
# sub r3, r2, r1
UC = Uc(UC_ARCH_ARM, UC_MODE_LITTLE_ENDIAN)
ADDRESS = 0x1000000

UC.mem_map(ADDRESS, 2 * 1024 * 1024)
UC.mem_write(ADDRESS, code)

UC.emu_start(ADDRESS, ADDRESS + len(code))
r1 = UC.reg_read(UC_ARM_REG_R1)
r2 = UC.reg_read(UC_ARM_REG_R2)
r3 = UC.reg_read(UC_ARM_REG_R3)

print(r1,r2,r3)

# 执行输出为
# 1 2 1

由于该脚本中使用了一些寄存器常量,所以除了导入unicorn,该脚本还导入了unicorn.arm_const

UC = Uc(UC_ARCH_ARM, UC_MODE_LITTLE_ENDIAN) 作用为初始化一个Unicorn类,其参数为硬件架构和模式

UC.mem_map(ADDRESS, 2 * 1024 * 1024) 意为在给定地址处开辟了一块2Mb(210241024 b)大小的内存

UC.mem_write(ADDRESS, code) 的作用是在给定的地址处将机器码写入,方便用于模拟执行。可以使用keystone用汇编指令生成机器码或使用capstone解析机器码

UC.emu_start(ADDRESS, ADDRESS + len(code)) 的作用是执行从ADDRESSADDRESS + len(code) 范围内的指令。该函数原型为emu_start(begin, until, timeout=0, count=0) ,其参数含义分别如下

begin:模拟执行开始的地址

until:模拟执行结束的地址

timeout:模拟执行的时间,如果为0则不限制时间

count:模拟执行的命令数,如果为0则不限制命令

r1 = UC.reg_read(UC_ARM_REG_R1) 的含义为读取了r1寄存器的值,并将其存储,其参数为寄存器常量,位于unicorn.arm_const,每一个寄存器都拥有一个寄存器常量,用于方便索引相应的寄存器

除此之外,还可以使用hook_add函数给执行的代码添加一定的hook事件

该函数原型为hook_add(htype, callback, user_data=None, begin=1, end=0, arg1=0 )

htype:hook类型,所有类型见下文

callback:回调函数,hook到后执行的函数

user_data:用户数据,hook到时可以将此数据传递给回调函数

begin:回调生效区域的起始地址(包括)

end :回调生效区域的结束地址(包括),若begin>end,则会hook所有内容

arg1:参数,取决于htype

其回调函数模板为

def hook_block(uc, address, size, user_data):
    # unicorn类
    # 当前hook地址
    # 当前hook大小
    # hook_add中给定的user_data
    pass

调用示例如下

from capstone import *
from unicorn import *
from unicorn.arm_const import *

# callback for tracing basic blocks
def hook_block(uc, address, size, user_data):
    print(>>> Tracing basic block at 0x%x, block size = 0x%x %(address, size))

# callback for tracing instructions
def hook_code(uc, address, size, user_data):
    print(>>> Tracing instruction at 0x%x, instruction size = 0x%x %(address, size))

code =b'\x01\x10\xa0\xe3\x02 \xa0\xe3\x010B\xe0'
CS = Cs(CS_ARCH_ARM, CS_MODE_LITTLE_ENDIAN)
UC = Uc(UC_ARCH_ARM, UC_MODE_LITTLE_ENDIAN)
ADDRESS = 0x1000000

a=CS.disasm_lite(code,0x400000)

# for (address, size, mnemonic, op_str) in Cs.disasm_lite(CS,code,0):
for (address, size, mnemonic, op_str) in a:
    print(hex(address), mnemonic, op_str)

UC.mem_map(ADDRESS, 2 * 1024 * 1024)
UC.mem_write(ADDRESS, code)

# tracing all basic blocks with customized callback
UC.hook_add(UC_HOOK_BLOCK, hook_block)

# tracing one instruction at ADDRESS with customized callback
UC.hook_add(UC_HOOK_CODE, hook_code, begin=ADDRESS, end=ADDRESS)

UC.emu_start(ADDRESS, ADDRESS + len(code))
r1 = UC.reg_read(UC_ARM_REG_R1)
r2 = UC.reg_read(UC_ARM_REG_R2)
r3 = UC.reg_read(UC_ARM_REG_R3)

print(r1,r2,r3)

# 执行输出为
# 0x400000 mov r1, #1
# 0x400004 mov r2, #2
# 0x400008 sub r3, r2, r1
# >>> Tracing basic block at 0x1000000, block size = 0xc
# >>> Tracing instruction at 0x1000000, instruction size = 0x4
# 1 2 1

相关数据结构

  • 支持的所有架构
typedef enum uc_arch {
        UC_ARCH_ARM = 1,    // ARM 架构 (包括 Thumb, Thumb-2)
        UC_ARCH_ARM64,      // ARM-64, 也称 AArch64
        UC_ARCH_MIPS,       // Mips 架构
        UC_ARCH_X86,        // X86 架构 (包括 x86 & x86-64)
        UC_ARCH_PPC,        // PowerPC 架构 (暂不支持)
        UC_ARCH_SPARC,      // Sparc 架构
        UC_ARCH_M68K,       // M68K 架构
        UC_ARCH_MAX,
} uc_arch;
  • 支持的所有模式
typedef enum uc_mode {
        UC_MODE_LITTLE_ENDIAN = 0,    // 小端序模式 (默认)
        UC_MODE_BIG_ENDIAN = 1 << 30, // 大端序模式

        // arm / arm64
        UC_MODE_ARM = 0,              // ARM 模式
        UC_MODE_THUMB = 1 << 4,       // THUMB 模式 (包括 Thumb-2)
        UC_MODE_MCLASS = 1 << 5,      // ARM's Cortex-M 系列 (暂不支持)
        UC_MODE_V8 = 1 << 6,          // ARMv8 A32 encodings for ARM (暂不支持)

        // arm (32bit) cpu 类型
        UC_MODE_ARM926 = 1 << 7,      // ARM926 CPU 类型
        UC_MODE_ARM946 = 1 << 8,      // ARM946 CPU 类型
        UC_MODE_ARM1176 = 1 << 9,     // ARM1176 CPU 类型

        // mips
        UC_MODE_MICRO = 1 << 4,       // MicroMips 模式 (暂不支持)
        UC_MODE_MIPS3 = 1 << 5,       // Mips III ISA (暂不支持)
        UC_MODE_MIPS32R6 = 1 << 6,    // Mips32r6 ISA (暂不支持)
        UC_MODE_MIPS32 = 1 << 2,      // Mips32 ISA
        UC_MODE_MIPS64 = 1 << 3,      // Mips64 ISA

        // x86 / x64
        UC_MODE_16 = 1 << 1,          // 16-bit 模式
        UC_MODE_32 = 1 << 2,          // 32-bit 模式
        UC_MODE_64 = 1 << 3,          // 64-bit 模式

        // ppc
        UC_MODE_PPC32 = 1 << 2,       // 32-bit 模式 (暂不支持)
        UC_MODE_PPC64 = 1 << 3,       // 64-bit 模式 (暂不支持)
        UC_MODE_QPX = 1 << 4,         // Quad Processing eXtensions 模式 (暂不支持)

        // sparc
        UC_MODE_SPARC32 = 1 << 2,     // 32-bit 模式
        UC_MODE_SPARC64 = 1 << 3,     // 64-bit 模式
        UC_MODE_V9 = 1 << 4,          // SparcV9 模式 (暂不支持)

        // m68k
    } uc_mode;
  • 所有内存访问类型
typedef enum uc_mem_type {
        UC_MEM_READ = 16,   // 内存从..读取
        UC_MEM_WRITE,       // 内存写入到..
        UC_MEM_FETCH,       // 内存被获取
        UC_MEM_READ_UNMAPPED,    // 未映射内存从..读取
        UC_MEM_WRITE_UNMAPPED,   // 未映射内存写入到..
        UC_MEM_FETCH_UNMAPPED,   // 未映射内存被获取
        UC_MEM_WRITE_PROT,  // 内存写保护,但是已映射
        UC_MEM_READ_PROT,   // 内存读保护,但是已映射
        UC_MEM_FETCH_PROT,  // 内存不可执行,但是已映射
        UC_MEM_READ_AFTER,   // 内存从 (成功访问的地址) 读入
    } uc_mem_type;
  • 所有的错误类型
typedef enum uc_err {
        UC_ERR_OK = 0,   // 无错误
        UC_ERR_NOMEM,      // 内存不足: uc_open(), uc_emulate()
        UC_ERR_ARCH,     // 不支持的架构: uc_open()
        UC_ERR_HANDLE,   // 不可用句柄
        UC_ERR_MODE,     // 不可用/不支持架构: uc_open()
        UC_ERR_VERSION,  // 不支持版本 (中间件)
        UC_ERR_READ_UNMAPPED, // 由于在未映射的内存上读取而退出模拟: uc_emu_start()
        UC_ERR_WRITE_UNMAPPED, // 由于在未映射的内存上写入而退出模拟: uc_emu_start()
        UC_ERR_FETCH_UNMAPPED, // 由于在未映射的内存中获取数据而退出模拟: uc_emu_start()
        UC_ERR_HOOK,    // 无效的hook类型: uc_hook_add()
        UC_ERR_INSN_INVALID, // 由于指令无效而退出模拟: uc_emu_start()
        UC_ERR_MAP, // 无效的内存映射: uc_mem_map()
        UC_ERR_WRITE_PROT, // 由于UC_MEM_WRITE_PROT冲突而停止模拟: uc_emu_start()
        UC_ERR_READ_PROT, // 由于UC_MEM_READ_PROT冲突而停止模拟: uc_emu_start()
        UC_ERR_FETCH_PROT, // 由于UC_MEM_FETCH_PROT冲突而停止模拟: uc_emu_start()
        UC_ERR_ARG,     // 提供给uc_xxx函数的无效参数
        UC_ERR_READ_UNALIGNED,  // 未对齐读取
        UC_ERR_WRITE_UNALIGNED,  // 未对齐写入
        UC_ERR_FETCH_UNALIGNED,  // 未对齐的提取
        UC_ERR_HOOK_EXIST,  // 此事件的钩子已经存在
        UC_ERR_RESOURCE,    // 资源不足: uc_emu_start()
        UC_ERR_EXCEPTION, // 未处理的CPU异常
        UC_ERR_TIMEOUT // 模拟超时
    } uc_err;
  • 所有的hook类型
typedef enum uc_hook_type {
        // Hook 所有中断/syscall 事件
        UC_HOOK_INTR = 1 << 0,
        // Hook 一条特定的指令 - 只支持非常小的指令子集
        UC_HOOK_INSN = 1 << 1,
        // Hook 一段代码
        UC_HOOK_CODE = 1 << 2,
        // Hook 基本块
        UC_HOOK_BLOCK = 1 << 3,
        // 用于在未映射的内存上读取内存的Hook
        UC_HOOK_MEM_READ_UNMAPPED = 1 << 4,
        // Hook 无效的内存写事件
        UC_HOOK_MEM_WRITE_UNMAPPED = 1 << 5,
        // Hook 执行事件的无效内存
        UC_HOOK_MEM_FETCH_UNMAPPED = 1 << 6,
        // Hook 读保护的内存
        UC_HOOK_MEM_READ_PROT = 1 << 7,
        // Hook 写保护的内存
        UC_HOOK_MEM_WRITE_PROT = 1 << 8,
        // Hook 不可执行内存上的内存
        UC_HOOK_MEM_FETCH_PROT = 1 << 9,
        // Hook 内存读取事件
        UC_HOOK_MEM_READ = 1 << 10,
        // Hook 内存写入事件
        UC_HOOK_MEM_WRITE = 1 << 11,
        // Hook 内存获取执行事件
        UC_HOOK_MEM_FETCH = 1 << 12,
        // Hook 内存读取事件,只允许能成功访问的地址
        // 成功读取后将触发回调
        UC_HOOK_MEM_READ_AFTER = 1 << 13,
        // Hook 无效指令异常
        UC_HOOK_INSN_INVALID = 1 << 14,
    } uc_hook_type;
  • 宏定义Hook类型(由基本hook类型组成)
    // Hook 所有未映射内存访问的事件
    #define UC_HOOK_MEM_UNMAPPED (UC_HOOK_MEM_READ_UNMAPPED + UC_HOOK_MEM_WRITE_UNMAPPED + UC_HOOK_MEM_FETCH_UNMAPPED)
    // Hook 所有对受保护内存的非法访问事件
    #define UC_HOOK_MEM_PROT (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_FETCH_PROT)
    // Hook 所有非法读取存储器的事件
    #define UC_HOOK_MEM_READ_INVALID (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_READ_UNMAPPED)
    // Hook 所有非法写入存储器的事件
    #define UC_HOOK_MEM_WRITE_INVALID (UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_WRITE_UNMAPPED)
    // Hook 所有非法获取内存的事件
    #define UC_HOOK_MEM_FETCH_INVALID (UC_HOOK_MEM_FETCH_PROT + UC_HOOK_MEM_FETCH_UNMAPPED)
    // Hook 所有非法的内存访问事件
    #define UC_HOOK_MEM_INVALID (UC_HOOK_MEM_UNMAPPED + UC_HOOK_MEM_PROT)
    // Hook 所有有效内存访问的事件
    // 注意: UC_HOOK_MEM_READ 在 UC_HOOK_MEM_READ_PROT 和 UC_HOOK_MEM_READ_UNMAPPED 之前触发 ,
    //       因此这个Hook可能会触发一些无效的读取。
    #define UC_HOOK_MEM_VALID (UC_HOOK_MEM_READ + UC_HOOK_MEM_WRITE + UC_HOOK_MEM_FETCH)
  • 映射区域的权限
    typedef enum uc_prot {
       UC_PROT_NONE = 0,    //无
       UC_PROT_READ = 1,    //读取
       UC_PROT_WRITE = 2,   //写入
       UC_PROT_EXEC = 4,    //可执行
       UC_PROT_ALL = 7,     //所有权限
    } uc_prot;
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇