逆向实战:360加固DEX解密全流程解析(附Frida脚本与SoFixer修复技巧)
360加固DEX解密技术深度剖析从动态Hook到ELF修复实战1. 360加固技术概览与逆向工程准备360加固作为国内主流Android应用保护方案其核心技术架构采用多层防护机制。在逆向分析过程中我们需要重点关注以下几个核心组件Java层入口com.stub.StubApp类作为应用启动入口Native层保护libjiagu.so系列动态库实现核心解密逻辑DEX保护机制原始DEX被加密存储在assets或classes.dex尾部1.1 逆向分析环境搭建进行360加固逆向需要准备以下工具链工具类别推荐工具主要用途动态调试工具Frida、IDA Pro运行时Hook和指令级分析静态分析工具JADX、Ghidra反编译Java和Native代码文件修复工具SoFixer、010 EditorELF文件结构修复脚本支持Python、JavaScript自动化分析脚本开发关键配置技巧# Frida脚本基础模板 import frida def on_message(message, data): print(message) device frida.get_usb_device() pid device.spawn([com.target.app]) session device.attach(pid) with open(hook.js) as f: script session.create_script(f.read()) script.on(message, on_message) script.load() device.resume(pid)1.2 加固特征识别识别360加固应用的典型特征Manifest标志入口Activity被替换为com.stub.StubApp存在android:extractNativeLibsfalse属性文件结构特征assets目录包含libjiagu_arch.so文件classes.dex大小异常通常包含加密数据运行时行为早期加载多个so文件敏感操作通过JNI桥接实现2. 动态Hook关键技术实现2.1 Frida框架深度应用针对360加固的有效Hook需要解决以下技术难点反调试对抗方案// 反调试检测绕过技巧 Interceptor.attach(Module.findExportByName(null, ptrace), { onEnter: function(args) { this.returnValue 0; } }); // maps文件伪装实现 const fake_maps /data/local/tmp/fake_maps; Interceptor.replace(Module.findExportByName(null, open), new NativeCallback(function(pathname, flags) { if (pathname.readCString().includes(maps)) { return open(fake_maps, flags); } return open(pathname, flags); }, int, [pointer, int]) );2.2 关键函数定位技术通过分层Hook策略定位解密函数Java层HookJava.perform(function() { const StubApp Java.use(com.stub.StubApp); StubApp.attachBaseContext.implementation function(context) { console.log(attachBaseContext called); return this.attachBaseContext(context); }; });Native层Hook// 监控dlopen调用链 const android_dlopen_ext Module.findExportByName(null, android_dlopen_ext); Interceptor.attach(android_dlopen_ext, { onEnter: function(args) { this.path args[0].readCString(); if (this.path.includes(libjiagu)) { console.log(Loading ${this.path}); this.shouldHook true; } }, onLeave: function(retval) { if (this.shouldHook) { hookDecryptFunctions(); } } });3. SoFixer修复实战技巧3.1 ELF文件修复流程360加固的so文件通常经过以下处理清除节区头信息加密关键区段破坏导入/导出表修复步骤内存Dumpfunction dumpSo(soName) { const lib Process.getModuleByName(soName); const filePath /data/local/tmp/${soName}_${lib.base}_${lib.size}.so; const file new File(filePath, wb); Memory.protect(lib.base, lib.size, rwx); const buffer lib.base.readByteArray(lib.size); file.write(buffer); file.flush(); file.close(); console.log(Dumped to ${filePath}); }SoFixer修复命令./SoFixer -s dumped.so -o fixed.so -m 0x12340000 -d参数说明-m指定内存加载基址-d启用调试模式输出详细信息3.2 导入表重建技巧修复后的验证步骤使用readelf检查动态段readelf -d fixed.so | grep NEEDEDIDA Pro分析验证确认JNI_OnLoad等关键函数可见检查交叉引用完整性常见问题处理出现DF__REFERENCE错误需要手动修正重定位信息符号解析失败补充DT_SYMTAB和DT_STRTAB信息4. DEX解密核心算法解析4.1 多层解密流程360加固采用典型的链式解密架构第一层解密RC4算法def rc4_decrypt(data, key): S list(range(256)) j 0 # Key-scheduling algorithm for i in range(256): j (j S[i] key[i % len(key)]) % 256 S[i], S[j] S[j], S[i] # Pseudo-random generation algorithm i j 0 out [] for char in data: i (i 1) % 256 j (j S[i]) % 256 S[i], S[j] S[j], S[i] out.append(char ^ S[(S[i] S[j]) % 256]) return bytes(out)第二层处理zlib解压缩import zlib def inflate(data): decompressor zlib.decompressobj() try: return decompressor.decompress(data) except zlib.error: return None4.2 内存Dump技巧通过Hook关键函数获取解密后的DEXInterceptor.attach(Module.findExportByName(null, mmap), { onLeave: function(retval) { const size this.context.x1.toInt32(); if (size 0x100000) { // 筛选大内存分配 console.log(mmap allocated ${size} bytes at ${retval}); MemoryAccessMonitor.enable({ base: retval, size: size }, { onAccess: function(details) { if (details.operation write) { dumpIfDex(details.from, details.size); } } }); } } }); function dumpIfDex(addr, size) { const dexHeader addr.readCString(4); if (dexHeader dex\n) { const path /data/local/tmp/dex_${addr}.dex; const file new File(path, wb); file.write(addr.readByteArray(size)); file.close(); console.log(DEX dumped to ${path}); } }5. 高级对抗技术与解决方案5.1 反调试对抗体系360加固采用的多维度检测技术检测类型实现方式绕过方案调试器检测ptrace、TracerPidHook相关系统调用环境检测/proc/self/maps分析文件路径重定向线程检测pthread_create监控动态拦截线程创建时间差检测gettimeofday差值计算固定返回值综合对抗脚本// 综合反调试绕过 function bypassAntiDebug() { // 1. 调试器检测绕过 const ptrace Module.findExportByName(null, ptrace); Interceptor.replace(ptrace, new NativeCallback(() { return 0; }, int, [])); // 2. 环境伪装 const openPtr Module.findExportByName(null, open); Interceptor.replace(openPtr, new NativeCallback((pathname, flags) { const path Memory.readUtf8String(pathname); if (path.includes(maps) || path.includes(status)) { const fake Memory.allocUtf8String(/data/fake_ path.split(/).pop()); return open(fake, flags); } return open(pathname, flags); }, int, [pointer, int])); // 3. 线程监控绕过 const pthread_create Module.findExportByName(null, pthread_create); Interceptor.attach(pthread_create, { onEnter: function(args) { const func args[2]; const module Process.findModuleByAddress(func); if (module module.name.includes(jiagu)) { console.log(Thread created in jiagu: ${func}); } } }); }5.2 代码混淆对抗360加固使用的混淆技术控制流平坦化通过状态机打乱执行流程指令替换将关键指令替换为等效复杂操作虚假分支插入大量不可达代码路径动态解密运行时解密关键代码片段反混淆策略使用Frida进行运行时代码Dump基于模拟执行的路径分析关键内存断点监控6. 自动化分析框架设计6.1 模块化脚本架构# 自动化分析框架示例 class JiaguAnalyzer: def __init__(self, package_name): self.package package_name self.frida_script // 基础Hook代码 def setup_hooks(self): # 添加各类Hook self._add_anti_debug_hooks() self._add_decryption_hooks() def start_analysis(self): device frida.get_usb_device() pid device.spawn(self.package) session device.attach(pid) script session.create_script(self.frida_script) script.on(message, self._handle_message) script.load() device.resume(pid) return script6.2 关键数据流追踪// 数据流追踪实现 function traceDataFlow(startPtr, size) { const endPtr startPtr.add(size); MemoryAccessMonitor.enable({ base: startPtr, size: size }, { onAccess: function(details) { const accessFrom DebugSymbol.fromAddress(details.from); console.log(Access from ${accessFrom} with ${details.operation}); if (details.operation read) { console.log(hexdump(details.from, { length: 64, header: true })); } } }); }7. 修复与重建技术7.1 DEX文件重建解密后的DEX可能存在的问题头信息损坏类定义不完整方法体被修改修复步骤使用baksmali/smali工具链java -jar baksmali.jar d decrypted.dex -o out java -jar smali.jar a out -o fixed.dex010 Editor模板修复使用DEX.bt模板验证结构手动修复header和map_list7.2 应用重打包安全重打包注意事项保留原始签名块修复AndroidManifest.xml入口处理assets中的加密资源自动化脚本import zipfile def repack_apk(original_apk, output_apk, modified_files): with zipfile.ZipFile(original_apk, r) as orig: with zipfile.ZipFile(output_apk, w) as new: # 复制原始文件 for item in orig.infolist(): if item.filename not in modified_files: new.writestr(item, orig.read(item.filename)) # 添加修改后的文件 for filename, content in modified_files.items(): new.writestr(filename, content)8. 技术演进与防护建议8.1 加固技术发展趋势VMP加固关键代码转换为虚拟机指令异构执行结合SGX等硬件安全特性动态防御基于行为的实时防护AI对抗机器学习检测分析行为8.2 防护方案建议针对开发者的防护建议分层防护Java层控制流混淆、字符串加密Native层VMP保护、符号消除运行时完整性校验、环境检测关键策略// 示例基于时间的自校验 void self_check() { struct timespec start, end; clock_gettime(CLOCK_MONOTONIC, start); // 关键代码段 sensitive_operation(); clock_gettime(CLOCK_MONOTONIC, end); long elapsed (end.tv_sec - start.tv_sec) * 1e9 (end.tv_nsec - start.tv_nsec); if (elapsed 1000000) { // 超过1ms认为被调试 exit(1); } }持续更新定期更换加密算法和防护策略