#!/usr/bin/env python3 """把 FULL dump 的解密数据合并进 ORIGINAL .so (元数据完好, unidbg 直接可加载). 关键洞察: unidbg 加载原文件时会自己按 .rela.dyn 重定位(RELATIVE=base+addend, GLOB_DAT/JUMP_SLOT=按符号解析) —— 重定位槽内容会被覆盖, 所以只需要把 "非重定位的加密数据"(字符串/密钥/常量)换成解密字节即可. 映射: dump 偏移(vaddr 轴) V -> 原文件偏移 = V - 0x1000 (V>=0x3b21c0) 否则 V. 随后把数据区里残留的运行期指针(>=0x4000000000)统一回退/清零. 用法: python3 merge_decrypted.py """ from __future__ import annotations import struct, sys def main(): original, dump, base_s, out = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4] base = int(base_s, 16) od = bytearray(open(original, 'rb').read()) dd = open(dump, 'rb').read() print(f"[*] original size={len(od):#x} dump size={len(dd):#x} base={base:#x}") def d2o(v): """dump 偏移(vaddr轴) -> 原文件偏移""" return v - 0x1000 if v >= 0x3b21c0 else v # 1) 复制解密数据: 覆盖 [0x30000, 0x3eb000) (rodata+data), 含 text 尾部(相同, 无害) COPY = [(0x30000, 0x3eb000)] for a, b in COPY: for off in range(a, b): pass # 慢, 用切片 # 切片方式: 逐块映射(避免逐字节) dst_start, dst_end = 0x30000, min(0x3eb000, len(dd)) # 一次性: dump[0x30000:0x3b21c0) -> orig[0x30000:0x3b21c0) (v<0x3b21c0 1:1) s1, e1 = 0x30000, 0x3b21c0 od[s1:e1] = dd[s1:e1] # dump[0x3b21c0:0x3eb000) -> orig[0x3b11c0:0x3ea000) s2, e2 = 0x3b21c0, min(0x3eb000, len(dd)) d2 = e2 - 0x1000 if d2 <= len(od): od[s2 - 0x1000:d2] = dd[s2:e2] print(f"[*] data merged: dump[{s1:#x}:{e1:#x}]->orig[{s1:#x}] ; dump[{s2:#x}:{e2:#x}]->orig[{s2-0x1000:#x}:{d2:#x}]") open(out, 'wb').write(od) open(out, 'wb').write(od) print(f"[*] -> {out}") if __name__ == '__main__': main()