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

admin 2025年4月28日00:12:21记一次爱加密企业版脱壳与反调试绕过已关闭评论4 views字数 10838阅读36分7秒阅读模式

Frida-Dexdump脱壳

用于提取DEX文件


https://github.com/hluwa/frida-dexdump

需要先绕过frida反调试

Fart脱壳

一款自动化脱壳工具


https://github.com/hanbinglengyue/FART?tab=readme-ov-file

同样需要先绕过frida反调试

绕过frida反调试

实践一:Hook pthread_create绕过反调试

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

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

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!"); }
记一次爱加密企业版脱壳与反调试绕过

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

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

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()
记一次爱加密企业版脱壳与反调试绕过

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

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

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()
记一次爱加密企业版脱壳与反调试绕过

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

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();
记一次爱加密企业版脱壳与反调试绕过

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

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

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

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

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线程函数的偏移量

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

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

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

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)后又中断,可能存在多层反调试机制

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

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

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

参考:
https://www.cnblogs.com/dxmao/articles/17678351.html

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

参考:
https://iiong.com/reinforce-android-applications-for-unpacking-learning/#%E5%B0%9D%E8%AF%95%E8%84%B1%E5%A3%B3

Hook mprotect 提取所有内存数据

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

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

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 文件

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

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

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

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

adb shell ps -A | grep 
            com.oceanwing.battery.cam
           # 获取 sPID  gdbserver64 :1234 --attach    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文件,但无济于事,针对新版爱加密加固,还是需要虚拟机脱壳


            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}`);
                       }         }     }); }
原文链接:
https://www.freebuf.com/articles/sectool/428181.html

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年4月28日00:12:21
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   记一次爱加密企业版脱壳与反调试绕过https://cn-sec.com/archives/4007646.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.