针对so层不固定位置的动态加密,怎么解决?(面试题)

发布于:2025-03-11 ⋅ 阅读:(125) ⋅ 点赞:(0)

Android逆向之破解某应用加密算法(动态调试so和hook so代码)
https://blog.csdn.net/qq_35559358/article/details/86672687

Android逆向之旅—动态方式破解apk进阶篇(IDA调试so源码)
https://cloud.tencent.com/developer/article/1193472

某APP密码加密算法分析
https://bbs.kanxue.com/thread-270847.htm

针对 so 层不固定位置的动态加密,通常涉及以下几种情况:

  1. so 代码段(.text)动态解密:代码在运行时才解密并执行,防止静态分析。
  2. so 数据段(.data/.bss)动态密钥保护:运行时生成密钥,避免静态分析获取。
  3. so 随机加载地址(PIE & ASLR):使 so 文件地址随机化,防止直接 Hook。
  4. 代码段自我校验:防止修改 .text 段,导致 Hook 失败或检测 Hook。
  5. so 内联汇编/指令混淆:防止逆向工具分析代码逻辑。

完整解决思路


1. 绕过动态解密

分析解密过程

思路:so 代码动态解密后才执行,我们可以在解密完成后获取解密后的代码或数据。

方法:

  • Hook mprotect()/memcpy()/memmove()
    • 监听 .text 段修改,找到解密后代码:
    Interceptor.attach(Module.findExportByName(null, "mprotect"), {
        onEnter: function(args) {
            console.log("mprotect:", args[0], "size:", args[1], "flags:", args[2]);
        }
    });
    
    • 内存扫描获取解密后的 .text
    var baseAddr = Module.findBaseAddress("libtarget.so");
    Memory.scan(baseAddr, 0x100000, "90 90 90 90", {
        onMatch: function(address, size) {
            console.log("Found decrypted code at:", address);
        }
    });
    
    • 利用 gdb 断点 Dump 解密后代码
      gdb -p <pid>
      dump memory dump.bin 0xADDR 0xADDR+size
      

2. 绕过动态密钥保护

某些 so 在运行时生成密钥,解密后再用。可以 Hook AES_decrypt() / EVP_DecryptFinal_ex() 截获解密数据。

Hook 关键加密 API
Interceptor.attach(Module.findExportByName(null, "AES_decrypt"), {
    onEnter: function(args) {
        console.log("AES decrypt input:", hexdump(args[0], {length: 32}));
    },
    onLeave: function(retval) {
        console.log("AES decrypt output:", hexdump(retval, {length: 32}));
    }
});

3. 绕过 ASLR(地址随机化)

  • 获取 so 基地址
var baseAddr = Module.findBaseAddress("libtarget.so");
console.log("Base address of libtarget.so:", baseAddr);
  • 禁用 ASLR 让 so 地址固定
    setarch `uname -m` -R target_app
    
    或者
    echo 0 > /proc/sys/kernel/randomize_va_space
    

4. 绕过代码段自我校验

  • 避免修改 .text 段被检测
    • so 可能使用 memcmp() 进行校验,我们可以 Hook:
      Interceptor.attach(Module.findExportByName(null, "memcmp"), {
          onEnter: function(args) {
              console.log("memcmp called:", hexdump(args[0], {length: 32}));
          }
      });
      
    • 强制返回校验通过
      Interceptor.attach(Module.findExportByName(null, "memcmp"), {
          onLeave: function(retval) {
              retval.replace(0);
          }
      });
      

5. 逆向混淆代码

  • 如果函数名被混淆,先找导出函数
    nm -D libtarget.so
    
  • 静态分析 obfuscation
    IDA + IDAPython
    
    for func in idautils.Functions():
        print("Function at:", hex(func))
    

总结

保护方式 解决方案
动态解密 .text 段 Hook mprotect()/memcpy(),Dump 解密后代码
动态密钥保护 Hook AES_decrypt()/EVP_DecryptFinal_ex() 截获解密数据
ASLR 随机化 读取 libtarget.so 基地址,禁用 ASLR
代码完整性检测 Hook memcmp(),强制返回校验通过
代码混淆 IDA+Frida+GDB 结合分析

如果你有更具体的加密场景,欢迎提供更多信息,我可以给出更详细的方案!🚀


网站公告

今日签到

点亮在社区的每一天
去签到