版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/
基于 Unicorn 实现一个轻量级的 ARM64 模拟器,具备代码加载、内存映射、指令执行、反汇编、寄存器监控、Hook、Patch、字符串处理等功能,适合用于逆向分析或调试 ARM64 代码。
初始化与内存管理
-
代码加载:通过 _load_binary() 将 so 文件加载到内存中。
-
内存映射:在 _setup_memory() 中分配 10MB 的代码区和 1MB 的栈区。
-
寄存器初始化:在 _setup_registers() 中设置栈指针(SP)和程序计数器(PC)。
-
寄存器设置:提供了 set_x0()、set_x1() 和 set_x2() 等方法,用于直接设置寄存器值。
import capstone
from unicorn import *
from unicorn.arm64_const import *
class ARM64Emulator:
def __init__(self, so_file: str):
self.so_file = so_file
# 分配代码区(TEXT 段)
self.CODE_BASE = 0x000000 # 假设代码段起始地址
self.CODE_SIZE = 1024 * 1024 * 10 # 10MB
# 分配栈区(STACK 段)
self.STACK_BASE = self.CODE_BASE + self.CODE_SIZE
self.STACK_SIZE = 1024 * 1024 * 1 # 1MB
# 初始化 Unicorn
self.mu = Uc(UC_ARCH_ARM64, UC_MODE_ARM)
self._load_binary()
self._setup_memory()
self._setup_registers()
self._setup_hooks()
def _load_binary(self):
with open(self.so_file, "rb") as f:
self.CODE = f.read()
def _setup_memory(self):
self.mu.mem_map(self.CODE_BASE, self.CODE_SIZE)
self.mu.mem_map(self.STACK_BASE, self.STACK_SIZE)
# 写入指令
self.mu.mem_write(self.CODE_BASE, self.CODE)
def _setup_registers(self):
self.mu.reg_write(UC_ARM64_REG_SP, self.STACK_BASE + self.STACK_SIZE - 4) # 使 SP 从栈的顶部往下移动 4 字节,以 预留一点空间,避免越界错误。
self.mu.reg_write(UC_ARM64_REG_PC, self.CODE_BASE)
def set_x0(self, value):
self.mu.reg_write(UC_ARM64_REG_X0, value)
def set_x1(self, value):
self.mu.reg_write(UC_ARM64_REG_X1, value)
def set_x2(self, value):
self.mu.reg_write(UC_ARM64_REG_X2, value)
打印寄存器
dump_registers() 打印所有 ARM64 寄存器的当前值。
def dump_registers(self):
""" 打印 Unicorn ARM64 CPU 的所有寄存器 """
print("\n====== Registers Dump ======")
# 遍历 X0 - X30
for i in range(31): # X0 ~ X30
reg_id = getattr(arm64_const, f'UC_ARM64_REG_X{i}')
value = self.mu.reg_read(reg_id)
print(f"X{i:02}: 0x{value:016x}")
# 打印 SP(栈指针)和 PC(程序计数器)
sp = self.mu.reg_read(UC_ARM64_REG_SP)
pc = self.mu.reg_read(UC_ARM64_REG_PC)
print(f"\nSP: 0x{sp:016x}")
print(f"PC: 0x{pc:016x}")
print("============================\n")
运行程序
run() 使用 emu_start() 运行从 start_address 到 end_address 的指令。
def run(self, start_address, end_address):
print("\nBefore execution:")
self.dump_registers()
# 运行 Unicorn
self.mu.emu_start(self.CODE_BASE + start_address, self.CODE_BASE + end_address)
print("\nAfter execution:")
self.dump_registers()
反汇编
disassembly() 使用 Capstone 对指定地址的内存数据进行反汇编。
class ARM64Emulator:
def __init__(self, so_file: str):
# 初始化 Capstone 反汇编器 (针对 ARM64 架构)
self.cs = capstone.Cs(capstone.CS_ARCH_ARM64, capstone.CS_MODE_ARM)
def disassembly(self, start_address, end_address):
"""
反汇编指定地址的字节码
:param start_address: 开始地址
:param end_address: 结束地址
"""
# 提取目标方法的字节码
target_data = self.CODE[start_address:end_address]
# 反汇编字节码
print("Disassembly:")
for instruction in self.cs.dis

最低0.47元/天 解锁文章
1320

被折叠的 条评论
为什么被折叠?



