- 输入图定案: 库内零硬件文件读, 种子=ANDROID_ID+服务端hydeviceid_config+MID, 属性层无关(X1/X2) - 真机全段解密 dump(phone_dump_hydev_full) + merge_decrypted 合入原文件 → unidbg 可直接加载 - unidbg(JDK21+patch) harness: JNI 桩(SharedPreferences日志化/Settings.Secure/NativeBridge) 金测试: androidId 加密态与 getGUID 全部与真机一致 - 遗留: NativeBridge.b(100) 原生归属库未定(非hydeviceid/udb/device-util), 当前桩替顶 - 修正结论: '单机不可铸造'判断错误, GUID=b(100)=f(androidId密, config, MID) 输入全可控
48 lines
2.0 KiB
Python
48 lines
2.0 KiB
Python
#!/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 <original.so> <dump_full.so> <runtime_base> <out.so>
|
|
"""
|
|
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()
|