论坛首页 逆向工程技术区 阅读主题

[原创]经典 Frida 检测 libmsaoaidsec.so 绕过

441 浏览 11 回复
#1 楼主 2026-06-01 21:09:09
案例:某红薯(v9.8.0)在面对 Frida 检测导致的闪退时,首要任务是找到是哪个 SO 库触发了检测。
通常,反调试逻辑会在 JNI_OnLoad​ 或 .init_array 中执行。如果 App 在加载某个特定的 SO 后立即崩溃,那么该 SO 极大概率就是检测逻辑的所在地。通过 Hook 系统底层的动态库加载函数,监控 App 启动过程中加载了哪些 SO 文件。观察 App 崩溃(闪退)前的最后一条加载记录,即可锁定目标。在 Android 7.0 (Nougat) 及更高版本中,系统加载动态库的底层实现主要依赖 android_dlopen_ext​。相比标准的 dlopen,它提供了更丰富的扩展能力(如从文件描述符加载、指定内存空间加载等),是系统加载器的必经之路。​函数原型:使用 spawn 模式启动 App 并注入上述脚本:​现象:
控制台快速打印出一系列 SO 加载日志,随后 App 突然闪退,Frida 会话断开。日志片段:​结论​:
加载日志停留在 ​​libmsaoaidsec.so​。这说明当系统尝试加载并初始化该库时,触发了其内部的反调试机制,导致进程自杀。确定了 libmsaoaidsec.so​ 是检测元凶后,我们需要找出具体是哪段代码在执行检测。通常,反调试逻辑不会在主线程运行(会卡顿 UI),而是创建一个独立的 子线程 (pthread) 进行轮询检测。因此,我们需要 Hook 系统底层的线程创建函数 pthread_create​,监控由 libmsaoaidsec.so 发起的所有线程创建行为,并获取其执行函数的入口地址。这是 Linux/Android 创建线程的标准 POSIX API。我们重点关注 ​​start_routine​​ (arg2) ,它直接指向了线程要执行的代码逻辑。运行脚本后,当控制台输出如下信息时,我们便成功捕获了检测线程:通过输出我们可以看到一共捕获到了3条关于 libmsaoaidsec.so 创建线程的数据,其函数在so中的偏移量分别是:在定位到检测线程的来源后,最简单粗暴且有效的绕过方式是 ​ “拒绝执行” 。由于 libmsaoaidsec.so​ 中的检测逻辑通常在子线程中死循环运行,我们可以 Hook pthread_create​,当识别到请求来自该 SO 库时,​直接返回 0​(假装创建成功),但不调用原始的 pthread_create 函数。这样,反调试线程永远不会被创建,而主程序的逻辑却以为线程已正常启动。为什么是 ​return 0​​ ?
​pthread_create​ 的函数原型定义中,返回值 0 表示 ​Success(成功),而非 0 的值表示错误码。
反调试逻辑通常会检查返回值: 通过返回 0,我们完美欺骗了上层逻辑,使其认为“监控线程”正在正常运行。副作用与风险
目前的脚本采用的是“核弹级”处理:​禁止该 SO 创建任何线程。进阶:精确打击 (基于 Offset)
如果发现“一刀切”导致 App 功能异常,请使用 第 2 步 中获取的 Offset 进行精确过滤:成功绕过,程序没用被 Kill ,且程序正常运行:Android 系统加载一个 SO 库的顺序如下:很多强壳或检测库(如 libmsaoaidsec.so​)会将反调试检测放在 ​.init_proc​​ 或 ​.init_array​​ 中。
如果我们在 android_dlopen_ext​ 的 onLeave​(即加载完成)后再去 Hook JNI_OnLoad​,此时 .init 系列函数早已执行完毕,检测已经触发(App 已闪退),为时晚矣。既然 onLeave​ 太晚,我们需要在 android_dlopen_ext​ 的 onEnter​ 之后,但在 .init​ 函数执行期间介入。
最佳策略是:寻找一个在 ​.init_proc​​ 中被调用的外部导入函数(Import)进行 Hook。so 未加载完全,无法 Hook 导出函数,也无法通过 so 基址 + 偏移的方式 Hook 函数,所以只能通过 Hook 导入函数进行绕过。通过 IDA 反编译 libmsaoaidsec.so​ 的 .init_proc 函数:我们发现 .init_proc​ 的入口处调用了 ​ ​__system_property_get​​。这是一个非常好的 Hook 锚点!只要我们 Hook 这个系统函数,当它被调用且参数为 ro.build.version.sdk​ 时,我们就可以断定:​现在正是 ​libmsaoaidsec.so​​ 执行初始化的时刻。此时 SO 已经在内存中(基址已确定),但后续的检测线程还没来得及创建。我们的思路如下:App 正常启动,日志显示 Patch 成功,且没有再出现闪退。面对在 .init​ 段做检测的 SO,​android_dlopen_ext​​ + ​__system_property_get​ 是一套非常经典的组合拳。它能帮我们卡住 SO 初始化的咽喉,实现最完美的早期注入。73aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6S2M7X3y4Z5x3%4u0F1y4s2u0Q4x3X3g2Y4K9i4c8Z5N6h3u0Q4x3X3g2A6L8#2)9J5c8U0t1H3x3U0g2Q4x3V1j5H3x3#2)9J5c8U0l9J5i4K6u0r3k6Y4u0A6k6r3q4Q4x3U0g2q4y4#2)9J5y4f1u0n7i4K6t1#2z5e0g2Q4x3U0g2q4z5q4)9J5y4f1u0r3i4K6t1#2z5o6N6Q4x3U0g2q4i4K6u0W2i4K6u0W2i4K6u0W2‍void* android_dlopen_ext(

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-289359.htm
#2 2026-06-01 21:09:09
感谢分享
#3 2026-06-01 21:09:09
mb_ldbucrik 
  6 楼
感谢分享
#4 2026-06-01 21:09:09
感谢分享
#5 2026-06-01 21:09:09
tql
#6 2026-06-01 21:09:09
感谢分享
#7 2026-06-01 21:09:09
很给力,感谢分享!
#8 2026-06-01 21:09:09
很给力,感谢分享!
#9 2026-06-01 21:09:09
学习学习
#10 2026-06-01 21:09:09
非常好
#11 2026-06-01 21:09:09
学习学习
#12 2026-06-01 21:09:09
最新版YY也是使用的这个版本的libmsaoaidsec.so,因为pthread_create的几个偏移都是一模一样的,但是patch这几个地址以后APP直接白屏卡死,过一会就再次crash了。

请登录后参与讨论

立即登录 注册账号