多种特征检测 Frida

本文介绍了如何检测Android应用中Frida的存在,包括检查进程、端口和内存中的库特征。同时,文章讨论了Frida的反检测策略,如更名和改端口,并提出通过扫描内存中的特定字符串来增强检测方法的可靠性。最后,给出了一个Android Studio工程的链接供读者实践。

引用:https://bbs.pediy.com/thread-263438.htm

之前看雪上读到过一篇检测 frida 的文章(参考链接在文末)。这里我们做了如下两步来反检测:

1、更名: 将frida-server改名为fenfeiserver

2、改端口: 手机里面用 fenfeiserver -l 127.0.0.1:8080 来启动; 电脑里面先映射 adb forward tcp:8080 tcp:8080; 然后启动 frida -H 127.0.0.1:8080 -l jd.js com.XXXXX.mall

 

转:https://bbs.pediy.com/thread-217482.htm

多种特征检测 Frida

Frida 在逆向工程狮中很受欢迎,你基本可以在运行时访问到你能想到的任何东西,内存地址、native 函数、Java 实例对象等。在 OWASP 的移动测试指南里就提到了 Frida。但是啊,每出来个好用的注入工具,都会有反注入、反反注入、反反反注入、反...注入。这篇文章要介绍的是 Android APP 检测 Frida 的方法。

检查 Frida 的痕迹

一种简易方法是检测 Frida 的运行痕迹,也适用于同类工具的检测,比如包文件、二进制文件、库文件、进程、临时文件等等。本例中针对的对象是 fridaserver,它通过 TCP 对外与 frida 通信,此时可以用 Java 遍历运行的进程列表从而检查 fridaserver 是否在运行。

public boolean checkRunningProcesses() {
  boolean returnValue = false;
  // Get currently running application processes
  List<RunningServiceInfo> list = manager.getRunningServices(300);
  if(list != null){
    String tempName;
    for(int i=0;i<list.size();++i){
      tempName = list.get(i).process;
      if(tempName.contains("fridaserver")) {
        returnValue = true;
      }
    }
  }
  return returnValue;
}

若 Frida 运行在默认配置时此法有效,若是遇到个笨拙的脚本小子,在第一步就能绊倒他。绕过也是相当简单,只需重命名 fridaserver,我们得找个更好的方法。

fridaserver 默认的 TCP 端口是 27047,可以检查这个端口是否开放。native 代码如下:

boolean is_frida_server_listening() {
    struct sockaddr_in sa;
    memset(&sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_port = htons(27047);
    inet_aton("127.0.0.1", &(sa.sin_addr));
    int sock = socket(AF_INET , SOCK_STREAM , 0);
    if (connect(sock , (struct sockaddr*)&sa , sizeof sa) != -1) {
      /* Frida server detected. Do something… */
    }
}

同样,这也得要求 fridaserver 是默认配置运行,命令行指定参数就可以改变它的监听端口,绕过也太不麻烦了。不过我们可以用' nmap -sV' 找到开放端口来改善这个方法。因为 fridaserver 使用 D-Bus 协议通信,我们为每个开放的端口发送 D-Bus 的认证消息,哪个端口回复了哪个就是 fridaserver。

/*
 * Mini-portscan to detect frida-server on any local port.
 */
for(i = 0 ; i <= 65535 ; i++) {
    sock = socket(AF_INET , SOCK_STREAM , 0);
    sa.sin_port = htons(i);
    if (connect(sock , (struct sockaddr*)&sa , sizeof sa) != -1) {
        __android_log_print(ANDROID_LOG_VERBOSE, APPNAME,  "FRIDA DETECTION [1]: Open Port: %d", i);
        memset(res, 0 , 7);
        // send a D-Bus AUTH message. Expected answer is “REJECT"
        send(sock, "\x00", 1, NULL);
        send(sock, "AUTH\r\n", 6, NULL);
        usleep(100);
        if (ret = recv(sock, res, 6, MSG_DONTWAIT) != -1) {
            if (strcmp(res, "REJECT") == 0) {
               /* Frida server detected. Do something… */
            }
        }
    }
    close(sock);
}

我们现在好像有了个非常好用的方法了呢,但是还存在问题。Frida 提供不需要 fridaserver 运行的模式!怎么检测?!

Frida 的各个模式都是用来注入的,我们可以利用的点就是 frida 运行时映射到内存的库。最直接的是挨个检查加载的库。

char line[512];
FILE* fp;
fp = fopen("/proc/self/maps", "r");
if (fp) {
    while (fgets(line, 512, fp)) {
        if (strstr(line, "frida")) {
            /* Evil library is loaded. Do something… */
        }
    }
    fclose(fp);
    } else {
       /* Error opening /proc/self/maps. If this happens, something is off. */
    }
}

 

这段代码检测名字含有“frida”的库,表明上有用,实际上:

还记得为什么检测名字是“fridaserver”的方法为什么不可靠吧?这里也是一样,稍微改一下 frida 就能重命名代理库名。

这段代码依赖的是标准库的`fopen()`和`strstr()`函数,可笑的是,我们竟想用能被 frida 轻而易举就 hook 的函数来检测 frida !

问题1可以用经典的病毒扫描法解决,在内存中扫描 frida 的库特征 “gadgets”。我选择字符串 “LIBFRIDA”,它在所有 frida-gadget 和 frida-agent 的版本中都有出现。下面的代码扫描了在 `/proc/sel/maps` 里找到的所有的可执行段,为了简洁我放了部分代码,完整的在 https://github.com/b-mueller/frida-detection-demo/blob/master/AntiFrida/app/src/main/cpp/native-lib.cpp 。

static char keyword[] = "LIBFRIDA";
num_found = 0;
int scan_executable_segments(char * map) {
    char buf[512];
    unsigned long start, end;
    sscanf(map, "%lx-%lx %s", &start, &end, buf);
    if (buf[2] == 'x') {
        return (find_mem_string(start, end, (char*)keyword, 8) == 1);
    } else {
        return 0;
    }
}
void scan() {
    if ((fd = my_openat(AT_FDCWD, "/proc/self/maps", O_RDONLY, 0)) >= 0) {
    while ((read_one_line(fd, map, MAX_LINE)) > 0) {
        if (scan_executable_segments(map) == 1) {
            num_found++;
        }
    }
    if (num_found > 1) {
        /* Frida Detected */
    }
}

注意 `my_openat()` 等函数,它们并非平常的 libc 库函数,是自定义实现的,但是功能和 libc 中的一样,设置了系统调用的参数,执行了软中断。因为直接调用公共 API 并不可靠,这样不容易被 hook。完整的实现在 https://github.com/b-mueller/frida-detection-demo/blob/master/AntiFrida/app/src/main/cpp/syscall.S 。下面是 my_openat 的代码:

#include "bionic_asm.h"
.text
    .globl my_openat
    .type my_openat,function
my_openat:
    .cfi_startproc
    mov ip, r7
    .cfi_register r7, ip
    ldr r7, =__NR_openat
    swi #0
    mov r7, ip
    .cfi_restore r7
    cmn r0, #(4095 + 1)
    bxls lr
    neg r0, r0
    b __set_errno_internal
    .cfi_endproc
    .size my_openat, .-my_openat;

到这里总算是有效的方法了,只用 frida 的话也不容易绕过,加了混淆更难。即使这样,依然有很多办法可以绕过,直接能想到的就是打补丁、hook 系统调用。但是记住,逆向工程永远胜利

想要试验,可以在这里 https://github.com/b-mueller/frida-detection-demo/ 下载 Android studio 工程。frida 注入时的运行结果如下:

 

原文链接:http://www.vantagepoint.sg/blog/90-the-jiu-jitsu-of-detecting-frida

本文由 看雪翻译小组 kiyaa 编译

<think>首先,用户的问题是:“我想检测某书应用中的反Frida机制 请问anti-frida detection in 《某书》 app”。我需要理解用户的需求:用户想检测某个应用(称为“某书”应用)中的反Frida机制,即应用如何检测Frida工具的使用。 根据系统指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式必须使用$$...$$格式并单独成段。 - LaTeX语法必须正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识。 - 回答结构清晰,帮助用户逐步解决问题。 - 参考站内引用:用户提供了几个引用,我需要参考这些引用,但用户说“上述引用仅供参考”,所以我应该基于这些引用构建回答,但不要直接复制。 提供的引用: - [^1]: 关于Frida绕过检测和反调试的技术。 - [^2]: Frida在设备上创建的文件和检测方法。 - [^3]: 一个Frida工具frida-dexdump,用于dump dex文件。 - [^4]: 对抗策略,如插入伪装系统调用。 用户上一次的问题似乎是关于检测Frida机制,所以我需要构建一个结构化的回答。 回答结构: 1. **理解问题**:先解释什么是反Frida机制。 2. **检测方法**:提供如何检测应用中的反Frida机制。 3. **步骤指南**:给出逐步的检测方法。 4. **相关工具**:提到工具如frida-dexdump或其他。 5. **生成相关问题**:在最后添加相关问题。 使用中文回答。 生成相关问题:在回答结束时,添加几个相关问题,如示例中所示。 现在,基于引用构建内容: - 从[^2]:检测Frida文件,如检查/data/local/tmp目录下的frida-server、frida-agent等。 - 从[^1]:Frida可以伪装或hook检测函数。 - 从[^3]:使用frida-dexdump需要先绕过检测。 - 从[^4]:插入伪装系统调用以对抗检测。 所以,回答应该包括: - 如何检测应用是否在检测Frida。 - 常见检测方法:文件检查、内存检查、系统调用监控等。 - 如何应对:使用Frida自身来hook检测函数或修改行为。 逐步回答: 1. **介绍反Frida机制**:解释应用如何检测Frida。 2. **检测Frida机制的方法**: - 静态分析:检查应用代码。 - 动态分析:使用Frida来监控应用行为。 3. **具体步骤**: - 步骤1:设置环境。 - 步骤2:使用Frida hook应用函数。 - 步骤3:监控文件访问或系统调用。 4. **工具推荐**:如frida-dexdump或其他。 5. **总结**。 最后,添加相关问题。 确保LaTeX格式正确:如果有数学表达式,使用$...$或$$...$$。在这个上下文中,可能没有太多数学,但如果有,比如概率或算法,我会使用。 在回答中,自然地添加引用标识。</think>### 检测某书应用中的反Frida机制 反Frida机制是指应用通过各种技术检测Frida工具的存在,以阻止动态分析和调试。某书应用(假设为类似小红书或类似App)可能采用多种Frida策略,包括文件检测、内存扫描、系统调用监控等。以下我将逐步指导您如何检测这些机制,确保回答基于可靠的安全工程实践。参考了Frida绕过检测的相关技术[^1],并结合实际分析步骤。 #### 1. **理解反Frida机制的常见类型** - **文件检测**:应用检查设备上Frida的残留文件,如`/data/local/tmp/frida-server`或`frida-agent.so`。如果存在这些文件,应用可能触发反调试行为[^2]。 - **内存特征扫描**:应用扫描进程内存中的Frida特征字符串(如`frida-agent`或`gum-js`),以识别注入。 - **系统调用监控**:应用监控异常系统调用序列(如频繁的`ptrace`或`openat`),这些可能是Frida操作的痕迹[^4]。 - **行为检测**:应用检测Frida的运行时行为,如动态代码加载或线程创建。 要检测这些机制,您需要结合静态和动态分析。Frida本身是强大的检测工具,因为它能hook应用函数来观察检测逻辑。 #### 2. **检测Frida机制的步骤** 以下是逐步检测方法。假设您已配置好Frida环境(Frida Server运行在Android设备上,并与PC客户端连接)。如果某书应用有加固(如混淆或加壳),需先脱壳处理。 **步骤1: 静态分析应用代码(初步识别检测点)** - 使用工具(如Jadx或Apktool)反编译某书APK,搜索可疑字符串: - 关键词:`frida`、`/data/local/tmp`、`ptrace`、`anti-debug`。 - 示例:在反编译代码中,查找如`if (file.exists("/data/local/tmp/frida-server"))`的语句,这表示文件检测机制[^2]。 - 如果发现检测逻辑,记录相关类和方法名(如`com.xiaohongshu.anti.FridaDetector`)。 **步骤2: 动态Hook检测函数(使用Frida监控行为)** - 编写Frida脚本,hook应用中的可疑函数。以下是一个Python示例脚本,监控文件访问和内存操作: ```javascript // frida_detect_anti.js Java.perform(function() { // Hook文件检测函数(示例类名,需根据实际反编译结果修改) var fileClass = Java.use("java.io.File"); fileClass.exists.implementation = function() { var path = this.getPath(); console.log("[文件检测] 访问路径: " + path); if (path.includes("frida")) { console.log("[反Frida触发] 检测Frida文件检查!"); } return this.exists.call(this); }; // Hook内存扫描函数(如System.loadLibrary) var systemClass = Java.use("java.lang.System"); systemClass.loadLibrary.implementation = function(libName) { console.log("[内存检测] 加载库: " + libName); if (libName.includes("frida")) { console.log("[反Frida触发] 检测到内存特征扫描!"); } return this.loadLibrary.call(this, libName); }; }); ``` - 运行脚本:`frida -U -l frida_detect_anti.js -f com.xiaohongshu.app`(替换为某书包名)。 - 观察日志:如果应用触发检测,控制台会输出反Frida行为,如文件访问或库加载警告。 **步骤3: 监控系统调用和内存特征** - Frida可以注入代码来监控底层系统调用。使用`Stalker`模块跟踪异常调用序列: ```javascript // stalker_monitor.js Interceptor.attach(Module.findExportByName(null, "ptrace"), { onEnter: function(args) { console.log("[系统调用] ptrace 调用, 可能被用于反调试"); // 如果调用频繁,可能是检测Frida[^4] } }); ``` - 结合内存扫描工具(如frida-dexdump)dump内存DEX文件,检查是否有检测代码注入[^3]。 - 命令:`frida-dexdump -U -p com.xiaohongshu.app`(需先确保Frida检测已绕过)。 **步骤4: 验证和绕过检测** - 如果检测到反Frida机制,应用可能崩溃或输出错误日志。此时,使用伪装技术: - 重命名Frida文件(如将`frida-server`改为`myserver`)[^2]。 - Hook检测函数并返回虚假值(如强制`file.exists()`返回`false`)。 - 插入伪装系统调用以混淆监控(例如,在敏感操作前添加无害调用如`SYS_getrandom`)[^4]。 - 测试绕过:修改Frida脚本后重新运行应用,确认检测不再触发。 #### 3. **工具和最佳实践** - **推荐工具**: - **Frida**:核心工具,用于动态注入和监控。 - **frida-dexdump**:dump内存DEX,帮助分析检测逻辑[^3]。 - **Ghidra/IDA**:静态分析辅助。 - **注意事项**: - 某书应用可能更新检测机制,需动态调整脚本。 - 在root设备上操作,避免权限问题。 - 参考Frida社区脚本(如GitHub仓库)获取针对特定App的示例。 通过以上步骤,您可以系统地检测某书应用中的反Frida机制。Frida的动态注入特性使其成为“以毒攻毒”的理想工具,帮助灵活应对防护机制[^1]。如果遇到具体错误,请提供更多细节以进一步分析。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值