admin管理员组

文章数量:1437151

记一次爱加密企业版脱壳与反调试绕过

Frida-Dexdump脱壳

用于提取DEX文件

需要先绕过frida反调试

Fart脱壳

一款自动化脱壳工具

同样需要先绕过frida反调试

绕过frida反调试

实践一:Hook pthread_create绕过反调试

首先确认哪个库文件创建了检测线程,Patch 所有调用 pthread_create 函数的caller或者自建pthread_create来绕过检测

通过hook dlopen查看哪个.so文件在检测hook,运行

代码语言:javascript代码运行次数:0运行复制
var dlopen_ext = Module.findExportByName(null, "android_dlopen_ext"); if (dlopen_ext) {     Interceptor.attach(dlopen_ext, {         onEnter: function (args) {             var pathptr = args[0];             if (pathptr !== undefined && pathptr != null) {                 var path = ptr(pathptr).readCString();                 console.log("load " + path);             }         }     }); } else {     console.log("android_dlopen_ext not found!"); }
1745222442_6805fb2ac96633472b957.png!small?1745222443858

hook到 android_dlopen_ext,但libexecmain.so执行后进程退出,可能是libexecmain.so中创建了一个线程检测到了Frida使其退出

确认是否由libexecmain创建的检测线程

代码语言:javascript代码运行次数:0运行复制
function hook_pthread_create(){     Interceptor.attach(Module.findExportByName(null, "pthread_create"),         {             onEnter: function (args) {                 var module = Process.findModuleByAddress(ptr(this.returnAddress))                 if (module != null) {                     console.log("[pthread_create] called from", module.name)                 }                 else {                     console.log("[pthread_create] called from", ptr(this.returnAddress))                 }             },         } ) } hook_pthread_create()
1745222486_6805fb56c3f6bd410099f.png!small?1745222487738

只有libexec.so创建进程,而libexecmain.so从未出现,而libexec.so是上一个调用的,可能就是由libexec.so创建的检测线程

尝试进行patch hook能不能过掉检测

代码语言:javascript代码运行次数:0运行复制
function patchPthreadCreate(){     let pthread_create = Module.findExportByName(null, "pthread_create")         let org_pthread_create = new NativeFunction(pthread_create, "int", ["pointer", "pointer", "pointer", "pointer"])         let my_pthread_create = new NativeCallback(function (a, b, c, d) {             let m = Process.getModuleByName("libexec.so");             let base = m.base             console.log(Process.getModuleByAddress(c).name)             if (Process.getModuleByAddress(c).name == m.name) {                 console.log("pthread_create")                 return 0;             }             return org_pthread_create(a, b, c, d)         }, "int", ["pointer", "pointer", "pointer", "pointer"])         Interceptor.replace(pthread_create, my_pthread_create) } patchPthreadCreate()
1745222543_6805fb8fb501e2e421301.png!small?1745222544655

未找到 libexec.so 模块,libexec.so 被嵌入在 APK 内

代码语言:javascript代码运行次数:0运行复制
function patchPthreadCreate() {     let pthread_create = Module.findExportByName(null, "pthread_create");     if (!pthread_create) {         console.log("Error: Unable to find pthread_create!");         return;     }      let org_pthread_create = new NativeFunction(pthread_create, "int", ["pointer", "pointer", "pointer", "pointer"]);      let my_pthread_create = new NativeCallback(function (a, b, c, d) {         let moduleFound = false;         let modulePath = "";         let modules = Process.enumerateModules();                  for (let m of modules) {             if (m.name.includes("libexec.so")) {  // 兼容不同路径的 libexec.so                 console.log("Found libexec.so at: " + m.path);                 moduleFound = true;                 modulePath = m.path;                 break;             }         }          if (!moduleFound) {             console.log("Error: libexec.so not found in the loaded modules!");             return org_pthread_create(a, b, c, d);         }          let moduleName = Process.getModuleByAddress(c)?.name;         console.log("pthread_create called from: " + moduleName);          if (moduleName && moduleName.includes("libexec.so")) {             console.log("Blocking pthread_create from libexec.so");             return 0;         }          return org_pthread_create(a, b, c, d);     }, "int", ["pointer", "pointer", "pointer", "pointer"]);      Interceptor.replace(pthread_create, my_pthread_create);     console.log("Successfully patched pthread_create!"); }  patchPthreadCreate();
1745222589_6805fbbd8a46d1856599f.png!small?1745222590600

先是报错未找到 libexec.so 模块,后又存在该模块,那么反调试进程可能存在延迟加载

Patch 所有调用 pthread_create 函数的caller不太行,可能是检测了pthread_create 是否被hook,那么就需要自己实现一个 pthread_create 函数,并让应用调用,避开对 pthread_create 的完整性检查

通过拦截 pthread_create 特定偏移量的线程执行,替换特定偏移量到自建的 pthread_create 函数,来防止在hook时检测机制生效,从而绕过检测

Hook pthread_create获取属于libexec.so线程函数的偏移量

代码语言:javascript代码运行次数:0运行复制
function hook_pthread() {    var pthread_create_addr = Module.findExportByName(null, 'pthread_create');   console.log("pthread_create_addr,", pthread_create_addr);    var pthread_create = new NativeFunction(pthread_create_addr, "int", ["pointer", "pointer", "pointer", "pointer"]);    Interceptor.replace(pthread_create_addr, new NativeCallback(function (parg0, parg1, parg2, parg3) {     var so_name = Process.findModuleByAddress(parg2).name;     var so_path = Process.findModuleByAddress(parg2).path;     var so_base = Module.getBaseAddress(so_name);     var offset = parg2 - so_base;     console.log("so_name", so_name, "offset", offset, "path", so_path, "parg2", parg2);     var PC = 0;     if ((so_name.indexOf("libexec.so") > -1)) {       console.log("find thread func offset", so_name, offset);       if ((1 === offset)) {         console.log("anti bypass");       } else if (1 === offset) {         console.log("anti bypass");       } else if (1 === offset) {         console.log("anti bypass");       } else if (1 === offset) {         console.log("anti bypass");       } else if (1 === offset) {         console.log("anti bypass");       } else if (1 === offset) {         console.log("anti bypass");       } else if (1 === offset) {         console.log("anti bypass");       } else {         PC = pthread_create(parg0, parg1, parg2, parg3);         console.log("ordinary sequence", PC)       }     } else {       PC = pthread_create(parg0, parg1, parg2, parg3);       // console.log("ordinary sequence", PC)     }     return PC;   }, "int", ["pointer", "pointer", "pointer", "pointer"]))  }  hook_pthread();

自建pthread_create,将代码中的判断语句中(1 === offset)的1全部替换成获取到的属于libexec.so线程函数的偏移量

1745222681_6805fc195d67d2400eb73.png!small?1745222682333

但仅仅获取了一个libexec.so偏移量就中断了

由于 libexec.so 的加载具有延迟性,就需要实时监视 libexec.so 是否被动态加载,再运行 pthread_create 钩子

代码语言:javascript代码运行次数:0运行复制
function enumerateModules() {     console.log("Enumerating modules...");     const modules = Process.enumerateModules();     modules.forEach(m => {         if (m.name.includes("libexec.so")) {             console.log(`Found module: ${m.name} at ${m.base} - ${m.path}`);         }     });     return modules.some(m => m.name === "libexec.so"); }  function hook_dlopen() {     const dlopen = Module.findExportByName(null, "dlopen") ||                     Module.findExportByName(null, "__loader_dlopen");     if (!dlopen) {         console.log("Failed to find dlopen");         return;     }      Interceptor.attach(dlopen, {         onEnter(args) {             const path = args[0].readUtf8String();             console.log("dlopen called for:", path);             if (path && path.includes("libexec.so")) {                 this.isLibexec = true;             }         },         onLeave(retval) {             if (this.isLibexec && retval) {                 console.log("libexec.so loaded at:", retval);                 setupPthreadHook();             }         }     }); }  function setupPthreadHook() {     const pthread_create_addr = Module.findExportByName(null, 'pthread_create');     if (!pthread_create_addr) {         console.log("Failed to find pthread_create");         return;     }     console.log("pthread_create_addr:", pthread_create_addr);      const pthread_create = new NativeFunction(pthread_create_addr, "int",          ["pointer", "pointer", "pointer", "pointer"]);     const targetOffset = 274972;      Interceptor.replace(pthread_create_addr, new NativeCallback(         function(parg0, parg1, parg2, parg3) {             try {                 const module = Process.findModuleByAddress(parg2) || {name: "unknown", base: 0};                 const so_name = module.name;                 const offset = module.base ? ptr(parg2).sub(module.base) : 0;                  console.log("so_name:", so_name, "offset:", offset);                  if (so_name === "libexec.so") {                     console.log("Found libexec.so thread func offset:", offset);                     if (offset.equals(targetOffset)) {                         console.log("Anti-detection triggered - bypassing");                         return 0;                     }                 }                 return pthread_create(parg0, parg1, parg2, parg3);             } catch (e) {                 console.log("Pthread hook error:", e);                 return pthread_create(parg0, parg1, parg2, parg3);             }         }, "int", ["pointer", "pointer", "pointer", "pointer"]));          console.log("Pthread hook installed successfully"); }  function main() {     console.log("Initializing...");          // First check if libexec.so is already loaded     if (enumerateModules()) {         console.log("libexec.so already loaded, setting up hook...");         setupPthreadHook();     } else {         console.log("libexec.so not found initially, hooking dlopen...");         hook_dlopen();                  // Fallback: keep checking periodically         let attempts = 0;         const maxAttempts = 50;         const interval = setInterval(() => {             if (enumerateModules()) {                 clearInterval(interval);                 setupPthreadHook();             } else if (attempts >= maxAttempts) {                 clearInterval(interval);                 console.log("Gave up waiting for libexec.so");             }             attempts++;         }, 100);     } }  try {     main(); } catch (e) {     console.log("Main execution error:", e); }

绕过libexec.so检测后,在另一个 dlopen 调用(libsotweak.so)后又中断,可能存在多层反调试机制

1745222734_6805fc4edf26e0fa6a1cb.png!small?1745222735961

实践二:阻止反调试库加载

阻止反调试 .so 的加载绕过检测,hook android_dlopen_ext,监控库加载,如果通过.so文件检测 hook,可以阻止其加载,绕过安全检查,尝试不可行

参考:.html

分析出创建检测线程的so文件,hook pthread_create 的偏移量为空函数来绕过检测,尝试不可行

参考:

Hook mprotect 提取所有内存数据

由于反调试检测线程的libexec.bin库文件在程序启动后加载,具有延迟性,而mprotect又是在程序启动时就加载,所以可以在反调试生效前,hook mprotect提取加载时执行的所有代码

拦截 mprotect 调用,检查内存权限更改,并强制将某些内存区域设置为 rwx,然后尝试进行内存转储,提取所有执行的代码,其中包括了解密后的dex文件

代码语言:javascript代码运行次数:0运行复制
var mprotect = Module.findExportByName(null, "mprotect");     if (mprotect) {         Interceptor.attach(mprotect, {             onEnter: function (args) {                 this.addr = ptr(args[0].toString());                 this.size = args[1].toInt32();                 this.prot = args[2].toInt32();                 if (this.prot === 1 || this.prot === 3 || this.prot === 7) {                     console.log(`mprotect called: ${this.addr.toString(16)}, size: ${this.size}, prot: ${this.prot}`);                 }             },             onLeave: function (retval) {                 if (retval.toInt32() === 0) {                     Memory.protect(this.addr, this.size, "rwx");                     console.log(`Memory protection patched at ${this.addr.toString(16)}, size: ${this.size}`);                     var header = Memory.readByteArray(this.addr, Math.min(8, this.size));                     var headerBytes = new Uint8Array(header);                     var headerHex = Array.from(headerBytes).map(b => b.toString(16).padStart(2, '0')).join(' ');                     console.log(`Header check: ${headerHex}`);                     if (this.size > 4096) {                         console.log(`Dumping memory region at ${this.addr.toString(16)}`);                         var data = Memory.readByteArray(this.addr, this.size);                         var fileName = `/data/data/com.oceanwing.battery.cam/dump_${this.addr.toString(16)}_${this.size}.bin`;                         try {                             var file = new File(fileName, "wb");                             file.write(data);                             file.close();                             console.log(`Saved to ${fileName}`);                         } catch (e) {                             console.error(`Failed to save: ${e.message}`);                             console.log("Dumping first 256 bytes:");                             console.log(hexdump(this.addr, { length: Math.min(this.size, 256) }));                         }                     }                 }             }         });     }

同样从内存提取数据并绕过保护,但没有frida-dexdump针对性的提取dex文件,该脚本 Dump 了所有被 mprotect 标记为可执行的代码段,其中可能包括 Dex 代码、so 库代码等,然后手动逐一分析提取的 bin 文件

1745222967_6805fd37b14eb8fd7f396.png!small?1745222968698

解析bin文件,手动提取dex文件,反编译分析dex文件,发现不完整

1745222992_6805fd506be2b39acb0e7.png!small?1745222993338

frida联合gdb动调,结合Frida的Hook,实时获取报错问题

代码语言:javascript代码运行次数:0运行复制
adb shell ps -A | grep com.oceanwing.battery.cam # 获取 sPID  gdbserver64 :1234 --attach <pid>   adb forward tcp:1234 tcp:1234 gdb target remote :1234

最终分析:

该脚本使用 Frida Hook 关键系统函数和 Java 方法,以绕过反调试机制、监控动态库加载、拦截进程退出、篡改时间检测、提取 DEX 代码并保持进程存活

在JNI_OnLoad中,原生代码解密这些数据,并通过DexClassLoader动态加载到内存中,所以它可能是应用加载额外DEX文件的触发点,hook它可能会获取到关键的DEX解密数据,但目前程序并未执行到JNI_OnLoad函数就中断了

提取出的解密数据并不是主要业务代码,同时也提出一堆加密的内存数据

通过Frida Hook和内存提取,成功绕过了部分反调试机制,提取了部分DEX文件,但无济于事,针对新版爱加密加固,还是需要虚拟机脱壳

代码语言:javascript代码运行次数:0运行复制
/*
* 提示:该行代码过长,系统自动注释不进行高亮。一键复制会移除系统注释 
* console.log("Script loaded immediately!");  setImmediate(function () {     console.log("Starting advanced anti-anti-debugging...");      // Hook mprotect(标记可读内存)     var mprotect = Module.findExportByName(null, "mprotect");     if (mprotect) {         Interceptor.attach(mprotect, {             onEnter: function (args) {                 this.addr = ptr(args[0].toString());                 this.size = args[1].toInt32();                 this.prot = args[2].toInt32();                 if (this.prot === 1 || this.prot === 3 || this.prot === 7) {                     console.log(`mprotect called: ${this.addr.toString(16)}, size: ${this.size}, prot: ${this.prot}`);                 }             },             onLeave: function (retval) {                 if (retval.toInt32() === 0 && (this.prot & 0x4)) {                     console.log(`Memory protection succeeded at ${this.addr.toString(16)}, size: ${this.size}`);                     this.safeToRead = true;                 }             }         });     }      // Hook dlopen 检测 libexec.so 和 libexecmain.so     var dlopen = Module.findExportByName(null, "dlopen");     if (dlopen) {         Interceptor.attach(dlopen, {             onEnter: function (args) {                 this.path = args[0].readCString();                 console.warn(`dlopen detected for ${this.path}`);                 if (this.path && this.path.includes("libsotweak.so")) {                     console.warn("Allowing libsotweak.so load, hooking its functions...");                 }             },             onLeave: function (retval) {                 if (retval.toInt32() > 0) {                     if (this.path && (this.path.includes("libexec.so") || this.path.includes("libexecmain.so"))) {                         console.log(`${this.path} loaded, initiating memory scan...`);                         scanMemory();                     }                     if (this.path && this.path.includes("libsotweak.so")) {                         console.log("Scanning memory after libsotweak.so load...");                         scanMemory();                     }                 }             }         });     }      // Hook pthread_create 增加扫描     var pthread_create = Module.findExportByName(null, "pthread_create");     if (pthread_create) {         Interceptor.attach(pthread_create, {             onEnter: function (args) {                 console.warn("pthread_create detected");                 this.threadFunc = args[2];                 var module = Process.findModuleByAddress(this.threadFunc) || { name: "unknown", base: 0 };                 var offset = module.base ? ptr(this.threadFunc).sub(module.base) : ptr(0);                 console.log(`pthread_create - module: ${module.name}, offset: ${offset}`);                  if (module.name === "libexec.so" && offset.toInt32() === 0x4321c) {                     console.log("Anti-detection thread detected - bypassing");                     this.bypass = true;                     scanMemory();                 }             },             onLeave: function (retval) {                 if (this.bypass) {                     console.log("Bypassing pthread_create");                     retval.replace(-1);                 } else if (retval.toInt32() === 0) {                     console.log("pthread_create succeeded");                 }             }         });     }      // Hook dlsym 防止触发 core 的陷阱并动态 hook JNI_OnLoad     var dlsym = Module.findExportByName(null, "dlsym");     if (dlsym) {         Interceptor.attach(dlsym, {             onEnter: function (args) {                 this.symbol = args[1].readCString();                 console.warn(`dlsym detected for ${this.symbol}`);                 if (this.symbol === "ptrace" || this.symbol === "gettimeofday" || this.symbol === "clock_gettime" || this.symbol === "core") {                     console.log(`Blocking dlsym for ${this.symbol} to avoid trap`);                     this.bypass = true;                 }             },             onLeave: function (retval) {                 if (this.bypass) {                     console.log(`Bypassing dlsym for ${this.symbol}`);                     retval.replace(ptr(0));                 }                 // 动态 hook JNI_OnLoad                 if (this.symbol === "JNI_OnLoad" && retval.isNull() === false) {                     console.log(`Attempting to hook JNI_OnLoad at ${retval.toString(16)}`);                     try {                         Interceptor.attach(retval, {                             onEnter: function (args) {                                 console.log("JNI_OnLoad called with args:");                                 console.log(`  vm: ${args[0]}`);                                 console.log(`  reserved: ${args[1]}`);                                 scanMemory(); // 扫描内存                             },                             onLeave: function (retval) {                                 console.log(`JNI_OnLoad returned: ${retval}`);                                 scanMemory(); // 再次扫描                             }                         });                     } catch (e) {                         console.error(`Failed to hook JNI_OnLoad: ${e.message}`);                     }                 }             }         });     }      // 定时扫描内存     setInterval(function () {         console.log("Periodic memory scan...");         scanMemory();     }, 500);      // 延迟 Java 层 hook     setTimeout(function () {         Java.perform(function () {             console.log("Initializing Java hooks...");             var AppComponentFactoryC0012A = Java.use("p000s.p001h.p002e.p003l.p004l.AppComponentFactoryC0012A");             if (AppComponentFactoryC0012A) {                 AppComponentFactoryC0012A["m43al"].implementation = function (classLoader, applicationInfo, packageName, orignAppName) {                     console.log("Java m43al called with:");                     console.log(`  ClassLoader: ${classLoader}`);                     console.log(`  ApplicationInfo: ${applicationInfo}`);                     console.log(`  PackageName: ${packageName}`);                     console.log(`  OrignAppName: ${orignAppName}`);                      var result = this["m43al"](classLoader, applicationInfo, packageName, orignAppName);                     console.log(`Java m43al returned ClassLoader: ${result}`);                      scanMemory();                      return result;                 };             } else {                 console.error("Failed to find AppComponentFactoryC0012A");             }              Java.use("java.lang.ClassLoader").loadClass.overload('java.lang.String', 'boolean').implementation = function (className, resolve) {                 console.log(`ClassLoader.loadClass called for: ${className}`);                 var result = this.loadClass(className, resolve);                 return result;             };         });     }, 1000);      // Hook sys_exit 和 sys_exit_group     var syscall = Module.findExportByName(null, "syscall");     if (syscall) {         Interceptor.attach(syscall, {             onEnter: function (args) {                 var nr = args[0].toInt32();                 if (nr === 93 || nr === 94) {                     console.warn(`syscall detected: ${nr === 93 ? "sys_exit" : "sys_exit_group"}`);                     this.bypass = true;                 }             },             onLeave: function (retval) {                 if (this.bypass) {                     console.log("Bypassing sys_exit/sys_exit_group");                     retval.replace(0);                 }             }         });     }      // Hook kill 防止信号终止     var kill = Module.findExportByName(null, "kill");     if (kill) {         Interceptor.attach(kill, {             onEnter: function (args) {                 console.warn(`kill detected! PID: ${args[0].toInt32()}, Signal: ${args[1].toInt32()}`);                 args[1] = ptr(0); // 禁用信号             }         });     }      // Hook raise 防止信号终止     var raise = Module.findExportByName(null, "raise");     if (raise) {         Interceptor.attach(raise, {             onEnter: function (args) {                 console.warn(`raise detected! Signal: ${args[0].toInt32()}`);                 args[0] = ptr(0); // 禁用信号             }         });     }      // Hook pthread_join 防止线程同步退出     var pthread_join = Module.findExportByName(null, "pthread_join");     if (pthread_join) {         Interceptor.attach(pthread_join, {             onEnter: function (args) {                 console.warn(`pthread_join detected! Thread: ${args[0].toString(16)}`);                 this.bypass = true;             },             onLeave: function (retval) {                 if (this.bypass) {                     console.log("Bypassing pthread_join");                     retval.replace(0);                 }             }         });     }      // Hook sched_yield 防止调度检测     var sched_yield = Module.findExportByName(null, "sched_yield");     if (sched_yield) {         Interceptor.attach(sched_yield, {             onEnter: function () {                 console.warn("sched_yield detected");                 this.bypass = true;             },             onLeave: function (retval) {                 if (this.bypass) {                     console.log("Bypassing sched_yield");                     retval.replace(0);                 }             }         });     }      // Hook sigaction 防止信号处理     var sigaction = Module.findExportByName(null, "sigaction");     if (sigaction) {         Interceptor.attach(sigaction, {             onEnter: function (args) {                 console.warn(`sigaction called with signal: ${args[0].toInt32()}`);                 args[1] = ptr(0); // 禁用信号处理             }         });     }      var prctl = Module.findExportByName(null, "prctl");     if (prctl) {         Interceptor.attach(prctl, {             onEnter: function (args) {                 console.warn(`prctl detected (bypassing)! Option: ${args[0].toInt32()}`);                 this.skip = true;             },             onLeave: function (retval) {                 if (this.skip) {                     retval.replace(0);                 }             }         });     }      var ptrace = Module.findExportByName(null, "ptrace");     if (ptrace) {         Interceptor.attach(ptrace, {             onEnter: function (args) {                 console.warn(`ptrace detected! Request: ${args[0].toInt32()}`);                 this.bypass = true;             },             onLeave: function (retval) {                 if (this.bypass) {                     console.log("Bypassing ptrace");                     retval.replace(-1);                 }             }         });     }      var fopen = Module.findExportByName(null, "fopen");     if (fopen) {         Interceptor.attach(fopen, {             onEnter: function (args) {                 var path = args[0].readCString();                 if (path && (path.includes("/proc") 혹은 path.includes("/sys") || path.includes("frida"))) {                     console.warn(`fopen detected for ${path}, redirecting to /dev/null`);                     args[0] = Memory.allocUtf8String("/dev/null");                 }             }         });     }      var gettimeofday = Module.findExportByName(null, "gettimeofday");     if (gettimeofday) {         Interceptor.attach(gettimeofday, {             onEnter: function (args) {                 console.warn("gettimeofday detected");                 this.tv = args[0];             },             onLeave: function (retval) {                 if (retval.toInt32() === 0 && this.tv) {                     var baseTime = Date.now() / 1000;                     var currentTime = Math.floor(baseTime + (Date.now() - baseTime * 1000) / 1000);                     Memory.writeLong(this.tv, currentTime);                     Memory.writeLong(this.tv.add(8), 0);                 }             }         });     }      var clock_gettime = Module.findExportByName(null, "clock_gettime");     if (clock_gettime) {         Interceptor.attach(clock_gettime, {             onEnter: function (args) {                 console.warn("clock_gettime detected");                 this.ts = args[1];             },             onLeave: function (retval) {                 if (retval.toInt32() === 0 && this.ts) {                     var baseTime = Date.now() / 1000;                     var currentTime = Math.floor(baseTime + (Date.now() - baseTime * 1000) / 1000);                     Memory.writeLong(this.ts, currentTime);                     Memory.writeLong(this.ts.add(8), 0);                 }             }         });     }      var exit = Module.findExportByName(null, "exit");     if (exit) {         Interceptor.attach(exit, {             onEnter: function (args) {                 console.warn(`exit detected with status: ${args[0].toInt32()}`);                 this.bypass = true;             },             onLeave: function (retval) {                 if (this.bypass) {                     console.log("Preventing exit");                     throw new Error("Blocked exit");                 }             }         });     }      var _exit = Module.findExportByName(null, "_exit");     if (_exit) {         Interceptor.attach(_exit, {             onEnter: function (args) {                 console.warn(`_exit detected with status: ${args[0].toInt32()}`);                 this.bypass = true;             },             onLeave: function (retval) {                 if (this.bypass) {                     console.log("Preventing _exit");                     throw new Error("Blocked _exit");                 }             }         });     }      var abort = Module.findExportByName(null, "abort");     if (abort) {         Interceptor.attach(abort, {             onEnter: function () {                 console.warn("abort detected");                 this.bypass = true;             },             onLeave: function (retval) {                 if (this.bypass) {                     console.log("Preventing abort");                     throw new Error("Blocked abort");                 }             }         });     }      // Exception handler with stack trace     Process.setExceptionHandler(function (details) {         console.log("Exception caught:", JSON.stringify(details, null, 2));         console.log("Stack:", Thread.backtrace(details.context, Backtracer.ACCURATE)             .map(DebugSymbol.fromAddress).join("\n"));         return true; // 继续运行     });      // Keep process alive     setInterval(function () {         console.log("Keeping process alive...");     }, 5000);      console.log("Advanced anti-anti-debugging setup complete!"); });  // 内存扫描函数 function scanMemory() {     console.log("Scanning memory...");     Process.enumerateRanges('r-x').forEach(range => {         if (range.size > 1024 * 100) {             try {                 var header = Memory.readByteArray(range.base, 8);                 var headerBytes = new Uint8Array(header);                 var headerHex = Array.from(headerBytes).map(b => b.toString(16).padStart(2, '0')).join(' ');                 var dexMagic = "64 65 78 0A 30 33 35 00"; // dex\n035\0                 var isDex = headerHex === dexMagic;                  if (isDex) {                     console.log(`DEX detected at ${range.base.toString(16)}, size: ${range.size}`);                     var fileName = `/data/data/com.oceanwing.battery.cam/dump_${range.base.toString(16)}_unencrypted.dex`;                     var data = Memory.readByteArray(range.base, Math.min(range.size, 1024 * 1024));                     var file = new File(fileName, "wb");                     file.write(data);                     file.close();                     console.log(`Dumped unencrypted DEX to ${fileName}`);                 } else if (range.size > 4096) {                     console.log(`Potential encrypted data at ${range.base.toString(16)}, size: ${range.size}`);                     var fileName = `/data/data/com.oceanwing.battery.cam/damp_${range.base.toString(16)}_encrypted.bin`;                     var data = Memory.readByteArray(range.base, Math.min(range.size, 1024 * 1024));                     var file = new File(fileName, "wb");                     file.write(data);                     file.close();                     console.log(`Dumped encrypted data to ${fileName}`);                 }             } catch (e) {                 console.error(`Memory scan error at ${range.base.toString(16)}: ${e.message}`);             }         }     }); }
*/

原文链接:.html

本文标签: 记一次爱加密企业版脱壳与反调试绕过