版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

Capstone

简介

Capstone 是一个强大的多平台开源反汇编框架,用于将机器码翻译为汇编代码。

官网:https://www.capstone-engine.org/

源码地址:https://github.com/capstone-engine/capstone

文档:https://www.capstone-engine.org/documentation.html

相关应用:

  • Radare2 内部使用 Capstone 作为其反汇编引擎之一。

  • Frida 的底层核心使用 Capstone 作为反汇编引擎,用于分析运行时的指令流、解码和显示二进制代码(例如,用户可以通过 Frida 的 API 获取内存中的指令数据,并使用 Capstone 对其进行解码和分析。)

使用 Capstone 反汇编 .so 文件中的机器码

要反汇编 .so 文件,首先需要提取其中的代码段内容(通常为 .text 段),然后利用 Capstone 进行反汇编。

1. 安装 capstone

pip install capstone

2. 提取 .so 文件中的代码段

使用 readelf 工具获取 .text 段的偏移和大小( -A 1:表示匹配行后再输出 1 行):

readelf -S libvmp-lib.so | grep -A 1 .text

[14] .text             PROGBITS         000000000009d480  0009d480
   00000000000af0f8  0000000000000000  AX       0     0     16

关键信息:

  • 偏移地址:000000000009d480(在文件中的位置)

  • 大小:00000000000af0f8(代码段的字节数)

根据偏移地址和大小提取 .text 段内容,输出 text_section.bin 将包含 .text 段的机器码。

dd if=libvmp-lib.so of=text_section.bin bs=1 skip=$((0x9d480)) count=$((0xaf0f8))

3. 使用 Capstone 反汇编

from capstone import *

# 配置架构和模式(以 ARM64 为例,可根据实际情况调整)
ARCH = CS_ARCH_ARM64
MODE = CS_MODE_ARM

# 加载提取的机器码
with open("text_section.bin", "rb") as f:
    code = f.read()

# 初始化 Capstone 引擎
md = Cs(ARCH, MODE)

# 设置反汇编选项(可选)
md.detail = True  # 是否显示详细信息

# 指定起始地址(根据 .text 的虚拟地址设置)
START_ADDRESS = 0x9d480

# 反汇编代码
for insn in md.disasm(code, START_ADDRESS):
    print(f"0x{insn.address:x}:\t{insn.mnemonic}\t{insn.op_str}")

输出如下:

0xec6e8:strx10, [x19, #0x50]
0xec6ec:b#0xec798
0xec6f0:dupv0.2d, x9
0xec6f4:dupv1.2d, x10
0xec6f8:ldurq2, [x20, #0x48]
0xec6fc:ldurq3, [x19, #0x48]
0xec700:cmpx9, x8
0xec704:subv0.2d, v2.2d, v0.2d
0xec708:subv1.2d, v3.2d, v1.2d
0xec70c:cmeqv2.2d, v2.2d, #0
0xec710:cmeqv3.2d, v3.2d, #0

. . . 

和 IDA 反汇编出来的是一样的

word/media/image1.png

Unicorn

简介

Unicorn 是一个轻量级、多平台的开源 CPU 指令集仿真框架,用于模拟多种架构的 CPU 指令执行。

它基于 QEMU 的代码,并优化了接口和功能,目标是为安全研究、逆向工程和调试等提供灵活高效的解决方案。

官网:https://www.unicorn-engine.org/

源码地址:https://github.com/unicorn-engine/unicorn

文档:https://www.unicorn-engine.org/docs/

核心组件

  • CPU 模拟:提供精准的 CPU 指令集仿真。

  • 内存管理:允许开发者分配、映射和访问内存。

  • 钩子机制:支持用户自定义回调函数,用于监控指令执行、内存访问等事件。

相关应用:

  • AndroidNativeEmu:Android native 库仿真框架。利用 Unicorn 引擎模拟 ARM 和 ARM64 架构下的 Android native 函数调用和系统行为(如 JNI 调用)。

  • Unidbg:Android 和 iOS 仿真框架,以 Unicorn 为核心,提供了更丰富的 API 和封装。

  • Qiling:跨平台、跨架构的仿真框架,支持模拟多个操作系统(如 Windows、Linux 和 macOS),使用 Unicorn 作为指令集仿真的底层引擎。

示例代码

安装 Unicorn

pip install unicorn

把汇编指令转换为机器码:https://armconverter.com/?code=ADD+X0,+X0,+%231

word/media/image2.png

以下是一个简单的 Unicorn ARM64 示例,模拟 1 + 1 的计算:

from unicorn import *
from unicorn.arm64_const import *

# 初始化 Unicorn 模拟器
mu = Uc(UC_ARCH_ARM64, UC_MODE_ARM)

# 设置内存地址和大小
ADDRESS = 0x1000
MEM_SIZE = 0x1000

# 分配内存
mu.mem_map(ADDRESS, MEM_SIZE)

# 汇编代码
# MOV X0, #1   ; 将 1 加载到寄存器 X0
# ADD X0, X0, #1 ; 将 X0 + 1 的结果存入 X0
CODE = b'\x20\x00\x80\xd2'  # MOV X0, #1
CODE += b'\x00\x04\x00\x91'  # ADD X0, X0, #1

# 写入代码到内存
mu.mem_write(ADDRESS, CODE)

# 初始化寄存器
mu.reg_write(UC_ARM64_REG_X0, 0)  # 初始化 X0
mu.reg_write(UC_ARM64_REG_SP, 0x2000)  # 初始化堆栈指针
mu.reg_write(UC_ARM64_REG_PC, ADDRESS)  # 设置程序计数器

# 执行指令
try:
    mu.emu_start(ADDRESS, ADDRESS + len(CODE))
    # 获取结果
    result = mu.reg_read(UC_ARM64_REG_X0)
    print(f"Result of 1 + 1 = {result}")
except UcError as e:
    print(f"Unicorn error: {e}")

输出如下:

Result of 1 + 1 = 2

Keystone

简介

Keystone 是一个轻量级的汇编框架,支持多种架构和编程语言,可以快速将汇编指令翻译成机器码。

官网:https://www.keystone-engine.org/

项目地址:https://github.com/keystone-engine/keystone

文档:https://www.keystone-engine.org/docs/

示例代码

安装 keystone

pip install keystone-engine

以下是一个用于 ARM64 的 Keystone 示例,实现一个简单的 1 + 1 运算,并将结果存储在寄存器中

from keystone import *

# 汇编指令:计算 1 + 1,将结果存储到 x0 寄存器
CODE = """
    mov x0, #1
    add x0, x0, #1
""".strip()

try:
    # 初始化 Keystone(ARM64 架构,小端模式)
    ks = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN)

    # 将指令汇编为机器代码
    encoding, count = ks.asm(CODE)

    # 打印机器代码结果
    print("机器代码(字节数组):", encoding)
    print("机器代码(十六进制):", bytes(encoding).hex())
    print("指令数:", count)

except KsError as e:
    print("ERROR: %s" % e)

输出如下:

机器代码(字节数组): [32, 0, 128, 210, 0, 4, 0, 145]
机器代码(十六进制): 200080d200040091
指令数: 2

把机器码转换回汇编指令:https://armconverter.com/?disasm&code=200080d2%0A00040091

word/media/image3.png