huolong blog

Frida检测

  1. 直接检测frida文件,frida文件一般会放在/data/local/tmp目录下,可以直接查找该目录下的文件判断是否存在frida。较老版本的frida会在运行后在当前目录下释放一个名为re.frida.server的文件,不过新版本已经改进了这一问题。

  2. 识别指定端口,frida server启动后默认会在27042端口监听。

  3. 检测ptrace状态,frida是基于ptrace技术发挥作用的,而ptrace操作是独占式的,故程序可以通过尝试对自身进行ptrace来检测frida。

  4. 检测maps文件,frida(以64位为例)注入进程后会加载frida-agent-64.so,故进程可以通过访问/proc/self/maps查找是否加载该库判断frida的存在。

  5. 检测线程status,frida注入进程后会启动多个新线程,通过查询/proc/self/task/number_for_tid/status下的线程信息判断是否被frida注入。以下为常见的frida会启动的新线程名次:

    • gmain:Frida 使用 Glib 库,其中的主事件循环被称为 GMainLoop。在 Frida 中,gmain 表示 GMainLoop 的线程。
    • gdbus:GDBus 是 Glib 提供的一个用于 D-Bus 通信的库。在 Frida 中,gdbus 表示 GDBus 相关的线程。
    • gum-js-loop:Gum 是 Frida 的运行时引擎,用于执行注入的 JavaScript 代码。gum-js-loop 表示 Gum 引擎执行 JavaScript 代码的线程。
    • pool-frida:Frida 中的某些功能可能会使用线程池来处理任务,pool-frida 表示 Frida 中的线程池。
    • linjector:一种用于 Android 设备的开源工具,它允许用户在运行时向 Android 应用程序注入动态链接库(DLL)文件。通过注入 DLL 文件,用户可以修改应用程序的行为、调试应用程序、监视函数调用等,这在逆向工程、安全研究和动态分析中是非常有用的。
  6. 检测native代码是否被inlinehook。inlinehook是一种代码hook技术,通常用于native层代码的控制,原理可以简单概括为修改函数代码开头的几个字节为跳转指令,跳转到一段由攻击者控制的内存执行额外的操作。因此被inlinehook代码的开头几个字节会发生变化,通过判断文件中的代码和内存中的代码开头是否发生变化可以用于检测frida。

  7. frida在attach进程注入动态链接库时会显式地校验ELF_magic字段,如果不对则直接报错退出,可以手动在内存中抹掉SO的magic字段,达到反调试的效果。

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));
		*(int*)start=*(int*)start^0x7f;   // 抹除Magic       
		}      
	}
  1. Frida源码中多次调用somain结构体,但它在调用前不会判断是否为空,只要手动置空后Frida一附加就会崩溃。
int getsomainoff = findsym("/system/bin/linker64","__dl__ZL6somain");
*(int*)((void*)start+getsomainoff)=0; // 修改somain指针