使用BinaryNinja分析某外卖libmtguard.so(一)
字数 1245 2025-08-29 08:30:24
BinaryNinja分析libmtguard.so字符串加密与间接跳转混淆
前言
本文详细讲解如何使用BinaryNinja分析某外卖应用的libmtguard.so文件,重点解决两种常见的混淆技术:字符串加密和基于ret的间接跳转。这些技术在安卓native层加固中非常常见,会严重干扰静态分析过程。
字符串加密分析
加密函数识别
在分析目标so文件时,我们发现函数sub_25d14负责字符串解密,其特征如下:
-
参数:
- 第一个参数(x0):存放解密后的字符串
- 第二个参数(x1):加密的字符串
- 第三个参数(x2):密钥
- 第四个参数(x3):长度
-
解密逻辑:简单的密文与密钥异或操作
解密脚本编写
由于加密字符串数量众多,需要编写自动化脚本进行批量解密。关键注意事项:
- 在执行
bl sub_25d14之前不能有其他跳转指令 - 第一个参数(x0)必须被正确赋值
- 使用Unicorn引擎模拟执行解密过程
示例脚本结构:
def decrypt_string(bv, addr):
# 初始化Unicorn引擎
mu = Uc(UC_ARCH_ARM64, UC_MODE_ARM)
# 设置内存和寄存器状态
# ...
# 模拟执行解密函数
mu.emu_start(decrypt_func_addr, decrypt_func_end)
# 读取解密后的字符串
decrypted = mu.mem_read(decrypted_ptr, length)
return decrypted
基于ret的间接跳转分析
间接跳转函数分析
函数sub_25d44负责间接跳转,IDA中表现为大量爆红区域。BinaryNinja的Low Level IL分析显示其逻辑:
- 从x30(链接寄存器)指向的地址加载数据到w0
- 使用
zx.q(w0)将w0扩展为64位 - 左移2位
- 计算跳转地址:
x30 + (w0 << 2) - 最终跳转地址为x30加上计算出的偏移
跳转目标计算示例
以JNI_OnLoad为例:
- 通过
bl指令将x30设置为0x249c8 - x0被赋值为3
- 计算跳转地址:
0x249c8 + (3 << 2) = 0x249c8 + 0xC = 0x249D4
去混淆脚本编写
编写deindbr函数进行patch处理:
- 获取所有跳转到
0x25d44的引用 - 获取所有跳板(如
b 0x249c4)的引用 - 模拟执行计算实际跳转地址
- 将跳转地址patch到跳板位置
关键注意事项:
- B指令构造:跳转地址需要减去当前指令地址,因为B指令是相对跳转
- 计算公式:
目标地址 = (当前指令地址 + 8) + (立即数 * 4) - 处理异常情况:过滤
br寄存器类型的引用
示例脚本结构:
def deindbr(bv):
# 获取所有跳转到间接跳转函数的引用
refs = get_call_references(bv, 0x25d44)
for ref in refs:
# 获取跳板地址
trampoline_addr = get_trampoline(ref)
# 模拟执行计算跳转目标
target = simulate_jump(bv, ref)
# 构造并patch B指令
patch_b_instruction(bv, trampoline_addr, target)
多次运行脚本
由于BinaryNinja不会像IDA那样一次性反编译所有代码,可能需要多次运行脚本直到没有新的地址被patch。
结果验证
完成patch后:
- JNI_OnLoad等函数的执行流已恢复
- IDA中仅剩
br寄存器类型的混淆(将在后续文章中分析) - 可以正常进行后续分析
总结
BinaryNinja配合Unicorn引擎能有效处理native层混淆:
- 字符串加密:通过模拟执行解密函数批量恢复字符串
- 间接跳转:通过分析跳转逻辑并patch跳板指令恢复执行流
- 后续工作:需要恢复符号信息,结合Frida、unidbg等工具进行更深入的分析
这种方法比传统IDA分析更加灵活高效,特别适合处理现代安卓应用中的复杂混淆技术。