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

admin 2025年4月28日00:11:53评论3 views字数 22053阅读73分30秒阅读模式

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:11:53
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   记一次爱加密企业版脱壳与反调试绕过https://cn-sec.com/archives/4007531.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息