版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/
ARM64Emulator
ARM64Emulator 是基于 Unicorn 实现一个轻量级的 ARM64 模拟器,具备代码加载、内存映射、指令执行、反汇编、寄存器监控、Hook、Patch、字符串处理等功能
项目地址:https://github.com/CYRUS-STUDIO/ARM64Emulator
这里主要使用 ARM64Emulator 模拟执行 so 中的汇编指令实现算法还原。
目标应用信息

app 中实现一个 CRC32 算法变形,具体实现在 so 中 modifiedCRC32 函数,现在要通过 unicorn 和 IDA Pro 逆向还原 so 中的算法。

项目地址:https://github.com/CYRUS-STUDIO/AndroidExample
目标 so 文件地址:https://github.com/CYRUS-STUDIO/ARM64Emulator/tree/main/examples
使用 ARM64Emulator 加载 so 并执行 modifiedCRC32 函数的汇编指令实现算法还原。
from unicorn.arm64_const import *
import struct
import re
from ARM64Emulator import ARM64Emulator
def modifiedCRC32(data):
emulator = ARM64Emulator("libcrc32.so")
mu = emulator.mu
# 字符串地址
str_addr = emulator.STACK_BASE + emulator.STACK_SIZE
emulator.mu.mem_map(str_addr, 0x1000) # 4KB
...
# 初始化传参
emulator.set_x0(0) # JNIEnv*
emulator.set_x1(0) # jobject
emulator.set_x2(str_addr) # input
# 运行
emulator.run(0x1C040, 0x1C2D8)
return hex(mu.reg_read(UC_ARM64_REG_X4))
if __name__ == "__main__":
result = modifiedCRC32("546NBypEyvgBt")
print(f"modifiedCRC32 result: '{result}'")
但汇编指令中有调用到一些 JNI 接口函数和系统函数,需要分析汇编代码并替换成对应的 Python 实现。
关键汇编代码分析
_ReadStatusReg
汇编代码如下:
.text:000000000001C05C 59 D0 3B D5 MRS X25, #3, c13, c0, #2
.text:000000000001C060 3A 01 00 D0 ADRP X26, #modified_crc32_table_ptr@PAGE
.text:000000000001C064 F4 03 02 AA MOV X20, X2
.text:000000000001C068 28 17 40 F9 LDR X8, [X25,#0x28]
.text:000000000001C06C F3 03 00 AA MOV X19, X0
.text:000000000001C070 A8 83 1F F8 STUR X8, [X29,#var_8]
MRS X25, #3, c13, c0, #2
-
MRS(Move from System Register)用于 读取系统寄存器。
-
#3, c13, c0, #2 对应 TPIDR_EL1(线程特定寄存器,常用于存储 TLS 线程本地存储指针)。
-
这行指令 将 TPIDR_EL1 读入 X25,可能是为了访问某个线程局部存储的数据。
ADRP X26, #modified_crc32_table_ptr@PAGE
-
ADRP(Address of Page)用于 获取 modified_crc32_table_ptr 所在的内存页地址,存入 X26。
-
这个指令不会提供完整地址,需要 结合 ADD 或 LDR 获取最终地址。
MOV X20, X2
- 保存 X2 到 X20
LDR X8, [X25,#0x28]
-
从 X25(即 TPIDR_EL1)的偏移 0x28 处读取一个 64-bit 值,存入 X8。
-
X25 指向 TLS(线程局部存储),所以 0x28 偏移量可能是线程相关的变量。
MOV X19, X0
- 备份 X0 到 X19,可能是 函数的第一个参数,用于后续计算。
STUR X8, [X29,#var_8]
-
把 X8 存入 X29(即 FP,帧指针)的 var_8 位置,通常是局部变量或栈空间的一部分。
-
STUR(Store Register Unscaled)是 STR 的变种,支持负偏移。
这段汇编代码中,主要通过 MRS 指令读取系统寄存器中内存访问异常相关状态信息信息,只需要把相关的两条指令 nop 掉就好了。
# v49 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
emulator.patch_nop([0X1C05C, 0X1C068])
GetStringUTFChars
汇编代码如下:
.text:000000000001C160 68 02 40 F9 LDR X8, [X19]
.text:000000000001C164 E0 03 13 AA MOV X0, X19
.text:000000000001C168 E1 03 14 AA MOV X1, X20
.text:000000000001C16C E2 03 1F AA MOV X2, XZR
.text:000000000001C170 08 A5 42 F9 LDR X8, [X8,#0x548]
.text:000000000001C174 00 01 3F D6 BLR X8
.text:000000000001C174
.text:000000000001C178 F5 03 00 AA MOV X21, X0

最低0.47元/天 解锁文章
2349

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



