前言
在移动应用安全测试和研究过程中,我们经常需要使用Frida等工具对应用进行动态分析。然而,很多应用都实现了反调试和反注入机制,用来检测并阻止此类分析工具的使用。本文将分享如何使用Frida绕过某流行阅读应用(以下简称"某书",本次任务目的原本是需要找出该书订单跳转某宝支付进行frida hook 参数)的反调试检测机制。
检测原理分析
现代Android应用通常采用多种方式检测Frida等工具:
- 字符串检测:在内存或进程列表中查找特征字符串,如"frida"、"gum-js-loop"等
- 文件检测:检查特定目录是否存在可疑文件
- 端口检测:检查Frida默认使用的27042端口是否开放
- 本地库检测:使用Native库实现更复杂的检测逻辑
在某书应用中,我们发现它主要通过libmsaoaidsec.so
这个本地库实现了反调试检测。
绕过策略
在多次尝试后,我们确定了一种有效的绕过策略,包含三个主要组件:
- 字符串检测绕过:拦截字符串相关函数,防止检测关键词
- 库加载阻断:阻止目标检测库的加载或替换为空实现
- Java层方法钩子:监控和记录关键方法调用
下面详细介绍这些技术的实现。
实现代码
1. 字符串检测绕过
首先,我们需要钩住常见的字符串比较函数,如strstr
和strcmp
,来阻止关键词检测:
function hook_dlopen(soName = '') {
// 定义要检测的关键词
var keywords = ["REJECT", "tmp", "frida", "gum-js-loop", "gmain", "linjector", "gadget", "magisk", "xposed"];
// 拦截 strstr 函数
var pt_strstr = Module.findExportByName("libc.so", 'strstr');
if (pt_strstr) {
Interceptor.attach(pt_strstr, {
onEnter: function (args) {
try {
if (args[0] !== null && args[1] !== null) {
var str1 = Memory.readCString(args[0]);
var str2 = Memory.readCString(args[1]);
if (str1 && str2) {
// 检查第二个参数是否包含任何关键词
for (var i = 0; i < keywords.length; i++) {
if (str2.indexOf(keywords[i]) !== -1) {
console.log("strstr 拦截 -->", str1, str2);
this.hook = true;
break;
}
}
}