首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
Android安全
发新帖
12
6
[原创]《安卓逆向这档事》第十九课、表哥,你也不想你的Frida被检测吧!(下)
发表于: 2024-7-25 12:04
41390
[原创]《安卓逆向这档事》第十九课、表哥,你也不想你的Frida被检测吧!(下)
正己
2024-7-25 12:04
41390
 # 一、课程目标 1.了解常见frida检测 2.了解frida持久化hook # 二、工具 1.教程Demo(更新) 2.jadx-gui 3.VS Code # 三、课程内容 ## 1.Syscall&SVC&自定义strstr 在上面的检测对抗中,我们hook了libc.so中的fread、strstr、open等系统函数,但是如果app不讲武德,自实现这些函数,阁下又该如何应对?  在用户空间和内核空间之间,有一个叫做Syscall(系统调用, system call)的中间层,是连接用户态和内核态的桥梁。这样即提高了内核的安全型,也便于移植,只需实现同一套接口即可。Linux系统,用户空间通过向内核空间发出Syscall,产生软中断,从而让程序陷入内核态,执行相应的操作。 **SVC(软件中断指令)指令**:在ARM架构的系统中,`svc`是一条特殊的指令,它允许用户态的程序发起一个系统调用。当这条指令被执行时,CPU会从用户态切换到内核态,从而允许内核处理这个请求。 Linux操作系统是一个巨大的图书馆,而`syscall`就是这个图书馆的前台服务窗口。当一个应用程序(比如一个读者)需要借阅书籍(获取系统资源或服务)时,它不能直接进入图书馆的内部书架去拿书,因为那样可能会造成混乱和损坏。所以,读者需要通过前台服务窗口,也就是`syscall`,来请求它想要的书籍。 `svc`就像是图书馆前台服务窗口的内部电话。当读者通过前台窗口提出请求时,前台工作人员会通过内部电话(`svc`)来联系图书馆的内部工作人员,请求他们找到并提供所需的书籍。在Linux系统中,当一个程序通过`syscall`请求服务时,实际上是通过`svc`这条指令通知内核,然后由内核来处理这些请求。 [Frida-Sigaction-Seccomp实现对Android APP系统调用的拦截](https://bbs.kanxue.com/thread-280343.htm#/) [分享一个Android通用svc跟踪以及hook方案——Frida-Seccomp](https://bbs.kanxue.com/thread-271815.htm) [基于seccomp+sigaction的Android通用svc hook方案](https://bbs.kanxue.com/thread-277544.htm#/) [[原创]SVC的TraceHook沙箱的实现&无痕Hook实现思路](https://bbs.kanxue.com/thread-273160.htm) [[原创]Seccomp技术在Android应用中的滥用与防护](https://bbs.kanxue.com/thread-276585.htm) [[原创]批量检测android app的so中是否有svc调用](https://bbs.kanxue.com/thread-269895.htm)  1. 首先当我们长按开机键(电源按钮)开机,此时会引导芯片开始从固化到ROM中的预设代码处执行,然后加载引导程序到RAM。然后启动加载的引导程序,引导程序主要做一些基本的检查,包括RAM的检查,初始化硬件的参数。 2. 到达内核层的流程后,这里初始化一些进程管理、内存管理、加载各种Driver等相关操作,如Camera Driver、Binder Driver 等。下一步就是内核线程,如软中断线程、内核守护线程。下面一层就是Native层,这里额外提一点知识,层于层之间是不可以直接通信的,所以需要一种中间状态来通信。Native层和Kernel层之间通信用的是syscall,Native层和Java层之间的通信是JNI。 3. 在Native层会初始化init进程,也就是用户组进程的祖先进程。init中加载配置文件init.rc,init.rc中孵化出ueventd、logd、healthd、installd、lmkd等用户守护进程。开机动画启动等操作。核心的一步是孵化出Zygote进程,此进程是所有APP的父进程,这也是Xposed注入的核心,同时也是Android的第一个Java进程(虚拟机进程)。 4. 进入框架层后,加载zygote init类,注册zygote socket套接字,通过此套接字来做进程通信,并加载虚拟机、类、系统资源等。zygote第一个孵化的进程是system_server进程,负责启动和管理整个Java Framework,包含ActivityManager、PowerManager等服务。 5. 应用层的所有APP都是从zygote孵化而来 ```c bool anti_anti_maps() { // 定义一个足够大的字符数组line,用于存储读取的行 const int buf_size = 512; char buf[buf_size]; int fd; // 文件描述符 // 使用 my_openat 打开当前进程的内存映射文件 /proc/self/maps 进行读取 // AT_FDCWD 表示当前工作目录,"r" 表示只读方式打开 fd = my_openat(AT_FDCWD, "/proc/self/maps", O_RDONLY | O_CLOEXEC, 0); if (fd != -1) { // 如果文件成功打开,循环读取每一行 while ((read_line(fd, buf, buf_size)) > 0) { // 使用strstr函数检查当前行是否包含"frida"字符串 if (strstr(buf, "frida") || strstr(buf, "gadget")) { // 如果找到了"frida",关闭文件并返回true,表示检测到了恶意库 close(fd); return true; // Evil library is loaded. } } // 遍历完文件后,关闭文件 close(fd); } else { // 如果无法打开文件,记录错误。这可能意味着系统状态异常 // 注意:这里的代码没有处理错误,只是注释说明了可能的情况 } // 如果没有在内存映射文件中找到"frida",返回false,表示没有检测到恶意库 return false; // No evil library detected. } ENTRY(my_openat) // 定义函数入口,标签my_openat mov x8, __NR_openat // 将openat系统调用号(__NR_openat)移动到x8寄存器,x8用于存储系统调用号 svc #0 // 触发系统调用异常,进入操作系统执行系统调用 cmn x0, #(MAX_ERRNO + 1) // 将函数返回值(存储在x0寄存器)与MAX_ERRNO + 1进行无符号比较 cneg x0, x0, hi // 如果上面的比较结果大于或等于零(即没有错误),则将x0的符号位取反(如果原来是负则变正) b.hi __set_errno_internal // 如果上面的比较结果大于或等于零(即发生了错误),则跳转到__set_errno_internal进行错误处理 ret // 从函数返回,继续执行调用者代码 END(my_openat) // 标记函数结束 ``` `anti脚本` ```js function anti_svc(){ let target_code_hex; // 用于搜索特定汇编指令序列的十六进制字符串 let call_number_openat; // 系统调用号对应的数值,openat let arch = Process.arch; // 获取当前进程的架构 if ("arm" === arch){ // 如果架构是ARM target_code_hex = "00 00 00 EF"; // ARM架构下svc指令的十六进制表示 call_number_openat = 322; // openat在ARM架构中的系统调用号 }else if("arm64" === arch){ // 如果架构是ARM64 target_code_hex = "01 00 00 D4"; // ARM64架构下svc指令的十六进制表示 call_number_openat = 56; // openat在ARM64架构中的系统调用号 }else { console.log("arch not support!"); // 如果架构不支持,打印错误信息 } if (arch){ // 如果成功获取了架构信息 console.log("\nthe_arch = " + arch); // 打印当前架构 // 枚举进程的内存范围,寻找只读内存段 Process.enumerateRanges('r--').forEach(function (range) { if(!range.file || !range.file.path){ // 如果内存段没有文件路径,跳过 return; } let path = range.file.path; // 获取内存段的文件路径 // 如果文件路径不是以"/data/app/"开头或不以".so"结尾,跳过 if ((!path.startsWith("/data/app/")) || (!path.endsWith(".so"))){ return; } let baseAddress = Module.getBaseAddress(path); // 获取so库的基址 let soNameList = path.split("/"); // 通过路径分割获取so库的名称 let soName = soNameList[soNameList.length - 1]; // 获取so库的名称 console.log("\npath = " + path + " , baseAddress = " + baseAddress + " , rangeAddress = " + range.base + " , size = " + range.size); // 在so库的内存范围内搜索target_code_hex对应的指令序列 Memory.scan(range.base, range.size, target_code_hex, { onMatch: function (match){ let code_address = match; // 获取匹配到的指令地址 let code_address_str = code_address.toString(); // 转换为字符串 // 如果地址的最低位是0, 4, 8, c中的任意一个,说明可能是svc指令 if (code_address_str.endsWith("0") || code_address_str.endsWith("4") || code_address_str.endsWith("8") || code_address_str.endsWith("c")){ console.log("--------------------------"); let call_number = 0; // 初始化系统调用号 if ("arm" === arch){ // 获取svc指令后面的立即数,作为系统调用号 call_number = (code_address.sub(0x4).readS32()) & 0xFFF; }else if("arm64" === arch){ call_number = (code_address.sub(0x4).readS32() >> 5) & 0xFFFF; }else { console.log("the arch get call_number not support!"); // 如果架构不支持,打印错误信息 } console.log("find svc : so_name = " + soName + " , address = " + code_address + " , call_number = " + call_number + " , offset = " + code_address.sub(baseAddress)); // 如果匹配到的系统调用号是openat,挂钩该地址 if (call_number_openat === call_number){ let target_hook_addr = code_address; let target_hook_addr_offset = target_hook_addr.sub(baseAddress); console.log("find svc openat , start inlinehook by frida!"); Interceptor.attach(target_hook_addr, { onEnter: function (args){ // 当进入挂钩函数时 console.log("\nonEnter_" + target_hook_addr_offset + " , __NR_openat , args[1] = " + args[1].readCString()); // 修改openat的第一个参数为指定路径 this.new_addr = Memory.allocUtf8String("/data/user/0/com.zj.wuaipojie/maps"); args[1] = this.new_addr; console.log("onEnter_" + target_hook_addr_offset + " , __NR_openat , args[1] = " + args[1].readCString()); }, onLeave: function (retval){ // 当离开挂钩函数时 console.log("onLeave_" + target_hook_addr_offset + " , __NR_openat , retval = " + retval) } }); } } }, onComplete: function () {} // 搜索完成后的回调函数 }); }); } } ``` `自定义strstr` ```C bool anti_str_maps() { // 定义一个足够大的字符数组line,用于存储读取的行 char line[512]; // 打开当前进程的内存映射文件/proc/self/maps进行读取 FILE* fp = fopen("/proc/self/maps", "r"); if (fp) { // 如果文件成功打开,循环读取每一行 while (fgets(line, sizeof(line), fp)) { // 使用自定义strstr函数检查当前行是否包含"frida"指纹 if (my_strstr(line, "frida") || my_strstr(line, "gadget")) { // 如果找到了,关闭文件并返回true,表示检测到了恶意库 fclose(fp); return true; } } // 遍历完文件后,关闭文件 fclose(fp); } else { // 如果无法打开文件,记录错误。这可能意味着系统状态异常 // 注意:这里的代码没有处理错误,只是注释说明了可能的情况 } // 如果没有在内存映射文件中找到"frida",返回false,表示没有检测到恶意库 return false; } //自实现了libc里的几个系统函数 __attribute__((always_inline)) static inline char * my_strstr(const char *s, const char *find) { char c, sc; size_t len; if ((c = *find++) != '\0') { len = my_strlen(find); do { do { if ((sc = *s++) == '\0') return (NULL); } while (sc != c); } while (my_strncmp(s, find, len) != 0); s--; } return ((char *)s); } ``` ## 2.frida持久化方案 ### 1.免root方案 Frida的Gadget是一个共享库,用于免root注入hook脚本。 <a href="elink@11eK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6X3M7X3W2V1j5g2)9J5k6i4u0W2i4K6u0r3k6r3!0U0M7#2)9J5c8X3N6S2k6r3N6W2N6q4)9J5c8W2)9J5x3#2)9J5c8R3`.`.">官方文档</a> 思路:将APK解包后,通过修改smali代码或patch so文件的方式植入frida-gadget,然后重新打包安装。 优点:免ROOT、能过掉一部分检测机制 缺点:重打包可能会遇到解决不了的签名校验、hook时机需要把握 1. 基于obejction的patchapk功能 <a href="elink@6b0K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6K6k6h3&6K6k6i4m8G2M7%4c8Q4x3V1k6G2j5X3A6W2j5%4c8A6L8$3&6Q4x3V1k6%4K9h3E0A6i4K6u0r3f1r3q4@1j5$3S2A6L8X3N6Q4x3X3c8m8L8X3c8J5L8$3W2V1i4K6u0V1b7i4m8H3L8r3W2U0j5i4c8A6L8$3&6K6">官方文档</a> 命令: ``` objection patchapk -V 14.2.18 -c config.txt -s demo.apk(注意路径不要有中文) -V 指定gadget版本 -c 加载脚本配置信息 -s 要注入的apk ``` 注意的问题: `objection patchapk`命令基本上是其他几个系统命令的补充,可尽可能地自动化修补过程。当然,需要先安装并启用这些命令。它们是: - `aapt`- 来自:<a href="elink@3daK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3g2D9K9h3&6#2P5q4)9J5k6h3!0J5k6#2)9J5c8V1q4F1k6s2u0G2K9h3c8Q4y4h3k6S2j5i4m8@1"><mark class="encrypted">c37K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3g2D9K9h3&6#2P5q4)9J5k6h3!0J5k6#2)9J5c8V1q4F1k6s2u0G2K9h3c8Q4y4h3k6S2j5i4m8@1</mark></a> - `adb`- 来自:<a href="elink@864K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1k6i4k6W2L8r3!0H3k6i4u0Q4x3X3g2S2L8X3c8J5L8$3W2V1i4K6u0W2j5$3!0E0i4K6u0r3M7%4c8#2k6r3W2G2i4K6u0r3j5$3!0E0L8h3q4F1k6q4)9J5k6r3I4A6L8X3g2Q4x3V1k6S2k6r3u0Q4x3X3g2Z5N6r3#2D9"><mark class="encrypted">3eaK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1k6i4k6W2L8r3!0H3k6i4u0Q4x3X3g2S2L8X3c8J5L8$3W2V1i4K6u0W2j5$3!0E0i4K6u0r3M7%4c8#2k6r3W2G2i4K6u0r3j5$3!0E0L8h3q4F1k6q4)9J5k6r3I4A6L8X3g2Q4x3V1k6S2k6r3u0Q4x3X3g2Z5N6r3#2D9</mark></a> - `jarsigner`- 来自:<a href="elink@e16K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3c8G2j5%4y4Q4x3X3g2G2M7X3q4U0L8r3g2Q4x3X3g2U0L8$3#2Q4x3V1k6B7j5i4k6S2M7$3g2Q4x3V1j5%4i4K6u0r3k6r3!0U0M7#2)9J5c8Y4c8W2j5$3S2F1L8%4c8W2M7#2)9J5c8Y4c8G2L8$3I4K6i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3A6S2M7Y4y4A6k6$3&6W2M7W2)9J5k6h3S2@1L8h3H3`."><mark class="encrypted">75dK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3c8G2j5%4y4Q4x3X3g2G2M7X3q4U0L8r3g2Q4x3X3g2U0L8$3#2Q4x3V1k6B7j5i4k6S2M7$3g2Q4x3V1j5%4i4K6u0r3k6r3!0U0M7#2)9J5c8Y4c8W2j5$3S2F1L8%4c8W2M7#2)9J5c8Y4c8G2L8$3I4K6i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3A6S2M7Y4y4A6k6$3&6W2M7W2)9J5k6h3S2@1L8h3H3`.</mark></a> - `apktool`- 来自:<a href="elink@91cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6A6j5X3!0@1M7r3g2S2j5$3S2W2M7#2)9J5k6h3N6A6N6r3S2#2j5W2)9J5k6h3W2G2i4K6u0r3b7i4m8C8N6r3!0G2L8q4)9J5c8R3`.`."><mark class="encrypted">d02K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6A6j5X3!0@1M7r3g2S2j5$3S2W2M7#2)9J5k6h3N6A6N6r3S2#2j5W2)9J5k6h3W2G2i4K6u0r3b7i4m8C8N6r3!0G2L8q4)9J5c8R3`.`.</mark></a> ps:这几个环境工具,aapt、jarsigner都是Android Studio自带的,所以在配置好as的环境即可,abd的环境配置网上搜一下就行,apktool则需要额外配置,我会上传到课件当中 另外会遇到的问题,patchapk的功能在patch的时候会下载对应版本的gadget的so,但是网络问题异常慢,所以建议根据链接去下载好,然后放到这个路径下并重命名 ``` C:\Users\用户名\.objection\android\arm64-v8a\libfrida-gadget.so ``` ### 2.root方案 方法一: 思路:可以patch /data/app/pkgname/lib/arm64(or arm)目录下的so文件,apk安装后会将so文件解压到该目录并在运行时加载,修改该目录下的文件不会触发签名校验。 Patch SO的原理可以参考<a href="elink@446K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4M7$3I4S2j5W2)9J5k6i4q4I4i4K6u0W2j5$3!0E0i4K6u0r3M7r3!0J5N6r3q4D9i4K6u0W2M7r3S2H3i4K6y4r3L8h3!0V1i4K6y4p5N6X3W2W2N6#2)9J5y4X3q4A6k6q4)9K6c8o6p5$3x3H3`.`.">Android平台感染ELF文件实现模块注入</a> 优点:绕过签名校验、root检测和部分ptrace保护。 缺点:需要root、高版本系统下,当manifest中的android:extractNativeLibs为false时,lib目录文件可能不会被加载,而是直接映射apk中的so文件、可能会有so完整性校验 使用方法 ``` python LIEFInjectFrida.py test.apk ./ lib52pojie.so -apksign -persistence test.apk要注入的apk名称 lib52pojie.so要注入的so名称 ``` 然后提取patch后是so文件放到对应的so目录下 方法二: 思路:基于magisk模块方案注入frida-gadget,实现加载和hook。寒冰师傅的<a href="elink@0b4K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6Z5j5h3&6T1K9h3&6Y4L8r3g2F1k6%4W2#2k6g2)9J5c8V1k6J5K9h3c8S2e0h3q4F1j5h3N6W2M7R3`.`.">FridaManager</a> 优点:无需重打包、灵活性较强 缺点:需要过root检测,magsik检测  方法三: 思路:基于jshook封装好的fridainject框架实现hook <a href="elink@bbaK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6j5M7r3!0K6k6h3c8Q4x3X3c8y4L8$3c8#2L8r3g2K6i4K6u0V1f1X3g2H3L8#2)9J5c8X3#2W2i4K6u0W2K9Y4y4G2L8X3g2@1i4K6u0W2K9Y4y4Z5L8$3!0C8">JsHook</a>  ### 3.源码定制方案 原理:修改aosp源代码,在fork子进程的时候注入frida-gadget <a href="elink@f17K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2E0L8$3u0A6j5Y4u0%4i4K6u0W2j5$3!0E0i4K6u0r3x3U0l9J5x3g2)9J5c8U0t1^5y4e0R3^5i4K6t1K6i4K6u0r3">ubuntu 20.04系统AOSP(Android 11)集成Frida</a> <a href="elink@068K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3f1#2x3Y4m8G2K9X3W2W2i4K6u0W2j5$3&6Q4x3V1k6@1K9s2u0W2j5h3c8Q4x3X3b7I4y4K6b7H3x3U0p5@1i4K6u0V1x3g2)9J5k6o6q4Q4x3X3g2Z5N6r3#2D9i4K6t1K6i4K6u0r3">AOSP Android 10内置FridaGadget实践01</a> <a href="elink@0abK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3f1#2x3Y4m8G2K9X3W2W2i4K6u0W2j5$3&6Q4x3V1k6@1K9s2u0W2j5h3c8Q4x3X3b7I4y4K6b7^5x3e0l9I4i4K6u0V1x3g2)9J5k6o6q4Q4x3X3g2Z5N6r3#2D9">AOSP Android 10内置FridaGadget实践02(完)</a>| ## 3.其他检测思路与反思 1.检测方法签名信息,frida在hook方法的时候会把java方法转为native方法 2.Frida在attach进程注入SO时会显式地校验ELF_magic字段,不对则直接报错退出进程,可以手动在内存中抹掉SO的magic,达到反调试的效果。 <a href="elink@734K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3M7X3W2V1j5g2)9J5c8X3k6J5K9h3c8S2i4K6u0V1k6%4g2E0i4K6u0r3j5X3I4G2j5W2)9J5c8U0S2V1z5h3j5@1y4e0M7^5j5U0f1^5j5K6l9K6x3o6t1#2j5h3g2X3y4U0x3$3y4e0u0W2j5K6c8V1k6h3k6S2x3e0W2X3z5o6l9$3x3h3y4Q4x3V1k6Y4N6h3#2Q4x3V1k6T1j5h3y4C8k6h3&6V1i4K6u0V1L8r3W2F1N6i4S2Q4x3V1k6Y4N6h3#2S2L8X3c8J5L8$3W2V1i4K6u0W2j5#2)9J5x3@1H3^5y4K6j5`.">检测点</a>  ```C if (memcmp (GSIZE_TO_POINTER (start), elf_magic, sizeof (elf_magic)) != 0) return FALSE; ``` ```C FILE *fp=fopen("/proc/self/maps","r"); while (fgets(line, sizeof(line), fp)) { if (strstr(line, "linker64") ) { start = reinterpret_cast<int *>(strtoul(strtok(line, "-"), NULL, 16)); *(long*)start=*(long*)start^0x7f; } } ``` 3.Frida源码中多次调用somain结构体,但它在调用前不会判断是否为空,只要手动置空后Frida一附加就会崩溃 <a href="elink@535K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3M7X3W2V1j5g2)9J5c8X3k6J5K9h3c8S2i4K6u0V1k6%4g2E0i4K6u0r3j5X3I4G2j5W2)9J5c8U0S2V1z5h3j5@1y4e0M7^5j5U0f1^5j5K6l9K6x3o6t1#2j5h3g2X3y4U0x3$3y4e0u0W2j5K6c8V1k6h3k6S2x3e0W2X3z5o6l9$3x3h3y4Q4x3V1k6Y4N6h3#2Q4x3V1k6T1j5h3y4C8k6h3&6V1i4K6u0V1L8r3W2F1N6i4S2Q4x3V1k6Y4N6h3#2S2L8X3c8J5L8$3W2V1i4K6u0W2j5#2)9J5x3@1H3I4x3o6M7^5">检测点</a>  ```C somain = api->solist_get_somain (); gum_init_soinfo_details (&details, somain, api, &ranges); api->solist_get_head () gum_init_soinfo_details (&details, si, api, &ranges); ``` ```C int getsomainoff = findsym("/system/bin/linker64","__dl__ZL6somain"); *(long*)((char*)start+getsomainoff)=0; ``` 4.通常inline hook第一条指令是mov 常数到寄存器,然后第二条是一个br 寄存器指令。检查第二条指令高16位是不是0xd61f,就可以判断目标函数是否被inline hook了!  5.还可以去hook加固壳,现在很多加固厂商都antifrida了,从壳中的代码去分析检测思路 `反思` | 反调试现状 | 详细说明 | |------------------|----------------------------------------------------------------------------------------------| | 检测方式多样 | 从通用检测、hook检测到源码检测,方式层出不穷。源码检测可以针对每行代码都能开发出不同检测方式,Frida指纹过多。 | | 检测位置不确定 | 一般是单独开线程跑,也可以在关键函数执行前判断 | | 强混淆加大定位难度 | 反调试通常埋几行代码,但结合混淆可达万行代码,不考虑效率可膨胀更多,定位极难。 | # 六、视频及课件地址 <a href="elink@03fK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6H3j5h3&6Q4x3X3g2T1j5h3W2V1N6g2)9J5k6h3y4G2L8g2)9J5c8Y4y4Q4x3V1j5I4j5@1k6i4g2p5I4F1x3e0c8B7k6g2N6X3M7q4S2^5L8s2R3K6M7%4W2k6N6#2)9K6c8Y4m8%4k6q4)9K6c8r3&6I4N6e0V1`.">百度云</a> <a href="elink@734K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2S2L8r3W2&6N6h3&6V1M7X3W2$3k6g2)9J5k6h3y4G2L8g2)9J5c8Y4y4Q4x3V1k6f1d9X3!0w2e0f1D9$3k6s2f1$3P5l9`.`.">阿里云</a> <a href="elink@b0cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2T1K9h3I4A6j5X3W2D9K9g2)9J5k6h3y4G2L8g2)9J5c8Y4k6A6k6r3g2G2i4K6u0r3b7W2j5I4N6#2b7@1x3e0q4z5y4%4y4h3i4K6u0r3i4K6y4r3M7%4m8E0i4K6g2X3K9h3c8Q4y4h3k6X3M7X3!0E0i4K6y4p5x3K6x3K6i4K6u0W2y4K6R3^5i4K6t1$3N6X3c8Q4y4h3k6K6L8%4g2J5j5$3g2Q4x3@1b7$3k6r3c8W2x3e0k6V1j5K6j5@1y4K6W2X3x3o6l9$3z5e0c8T1j5h3q4X3y4K6y4S2x3U0t1J5y4e0b7#2x3R3`.`.">哔哩哔哩</a> <a href="elink@c2cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6K9d9U0f1&6y4g2)9J5c8V1q4F1k6s2u0G2K9h3c8d9k6i4k6W2M7Y4y4W2">教程开源地址</a> PS:解压密码都是52pj,阿里云由于不能分享压缩包,所以下载exe文件,双击自 # 八、参考文档 <a href="elink@d4fK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3f1#2x3Y4m8G2K9X3W2W2i4K6u0W2j5$3&6Q4x3V1k6X3L8%4u0#2L8g2)9J5k6i4m8Z5M7q4)9K6c8X3#2G2k6q4)9K6c8s2k6A6k6i4N6@1K9s2u0W2j5h3c8Q4x3U0k6@1K9h3c8Q4x3@1b7I4y4o6j5%4z5e0p5J5">小菜花的frida-gadget持久化方案汇总</a> <a href="elink@971K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6Z5j5h3&6T1K9h3&6Y4L8r3g2F1k6%4W2#2k6g2)9J5c8V1k6J5K9h3c8S2e0h3q4F1j5h3N6W2M7R3`.`.">FridaManager:Frida脚本持久化解决方案</a> <a href="elink@cecK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8&6N6h3q4F1i4K6u0W2j5$3!0E0i4K6u0r3x3U0l9I4y4W2)9J5c8U0l9#2i4K6u0r3x3U0q4Q4x3V1k6K6P5i4y4U0j5h3I4D9i4K6u0r3i4K6t1K6i4K6u0r3">Linux系统调用(syscall)原理</a> [小菜花的frida-svc-interceptor](https://bbs.kanxue.com/thread-270144-1.htm#/) [[原创]小日本也有大安全——记一次不寻常的手游反调试,反hook分析与绕过](https://bbs.kanxue.com/thread-278113.htm) [[原创]非root环境下frida持久化的两种方式及脚本](https://bbs.kanxue.com/thread-268175.htm#/) <a href="elink@850K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6S2M7$3S2W2L8X3!0F1k6e0j5$3i4K6u0W2j5$3&6Q4x3V1j5J5x3o6t1I4i4K6u0r3x3o6W2Q4x3V1j5J5x3q4)9J5c8X3c8#2L8#2)9J5k6r3y4Z5L8$3&6Y4i4K6u0V1P5X3W2Q4x3X3c8K6K9r3W2Q4x3X3c8Z5N6h3q4Q4x3X3c8&6j5h3&6Y4i4K6u0V1M7$3S2A6i4K6u0V1P5h3!0F1k6#2)9J5k6r3k6J5K9h3c8S2i4K6u0V1P5X3S2#2i4K6u0V1M7Y4g2Q4x3V1k6Q4x3U0y4Q4x3V1j5`.">多种姿势花样使用Frida注入</a>
登录后可查看完整内容
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!
最后于
2024-7-25 12:06 被正己编辑 ,原因:
#逆向分析
#NDK分析
#HOOK注入
收藏
・
12
点赞
・
6
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
派克冬
感谢你的贡献,论坛因你而更加精彩!
2024-11-1 09:09
mb_zfqvurgb
期待更多优质内容的分享,论坛有你更精彩!
2024-10-24 14:10
PLEBFE
为你点赞!
2024-9-12 04:54
empty_
感谢你的贡献,论坛因你而更加精彩!
2024-9-6 09:52
vay
+1
谢谢你的细致分析,受益匪浅!
2024-7-26 11:15
Forgo7ten
+1
期待更多优质内容的分享,论坛有你更精彩!
2024-7-25 14:02
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
6
)
z笑的样子
雪 币:
43
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
8
粉丝
1
关注
私信
z笑的样子
2
楼
666666666666666666
2024-7-27 22:10
0
aizhiqun
雪 币:
101
活跃值:
(1721)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
17
粉丝
0
关注
私信
aizhiqun
3
楼
感谢大佬分享!!
2024-7-27 22:29
0
mb_zfqvurgb
雪 币:
306
活跃值:
(1564)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
51
粉丝
1
关注
私信
mb_zfqvurgb
4
楼
很系统,学到很多,感谢大佬
2024-10-24 14:14
0
mYcheng
雪 币:
0
活跃值:
(670)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
2
粉丝
0
关注
私信
mYcheng
5
楼
大佬,怎么anti自定义 strstr 呀
2024-10-30 10:53
0
正己
雪 币:
6603
活跃值:
(5263)
能力值:
( LV7,RANK:110 )
在线值:
发帖
18
回帖
61
粉丝
501
关注
私信
正己
6
楼
没有通用方案,只能定位再去hook
2024-10-31 16:10
1
mb_fhpfcoqp
雪 币:
0
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
30
粉丝
0
关注
私信
mb_fhpfcoqp
7
楼
666
2025-12-9 16:56
0
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
正己
18
发帖
61
回帖
110
RANK
关注
私信
他的文章
[原创]《安卓逆向这档事》第二十六课、Unidbg之补完环境我就睡(下)
19170
[原创]《安卓逆向这档事》第二十五课、Unidbg之补完环境我就睡(中)
18464
《安卓逆向这档事》第二十四课、Unidbg之补完环境我就睡(上)
11070
《安卓逆向这档事》第二十三课、黑盒魔法之Unidbg
65808
[原创]《安卓逆向这档事》第二十二课、抓包学得好,牢饭吃得饱(下)
41695
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部