常见Frida检测方法+一个小Demo

常见Frida检测方法+一个小Demo


Frida检测方法

最近研究了一下常见的Frida检测方法,本文对其中一些比较简单的检测进行了一些记录,并且提供了一个检测的Demo,由于本人C语言水平极菜所以写出来的Demo也比较水,代码方面大家可以稍作参考。另外安装包使用了最简单的混淆和默认OLLVM方案,供小伙伴门试水。

D-Bus

属于比较常用的一种检测方式,fridaserver是使用 D-Bus 协议通信,我们为每个开放的端口发送 D-Bus 的认证消息,哪个端口回复了哪个就是 fridaserver,但是此方法需要的时间会比较长,一般来讲如果出现一个App启动后过了一会就退出那么就有可能是这种检测方案。

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);
}

进程名

进程名方式检测在高版本Android上是无法使用的,目前使用这种方式检测frida的基本上已经没有了,这种检测方案基本上是没有意义的。

// Android5.1以上无效
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;
}
public static synchronized boolean mCheckFridaShell() {
  String rsp = "";
  synchronized (CheckFrida.class) {
    if (Build.VERSION.SDK_INT < 26) {
      rsp = shellExec("ps");
    } else {
      rsp = shellExec("ps -ef");
    }
  }
  return rsp.contains("frida");
}

默认端口

比较低级的检测方案,frida默认端口27047,通过检测默认端口是否开放来检测frida是否开启,只需要启动时指定端口即可绕过,也属于没有太多意义的检测方案。

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默认会在/data/local/tmp/re.frida.server/frida-agent-64.so中存放frida-agent,可以查找此路径下是否存在对应文件,也属于比较初级的检测方案,使用去除了特征的frida即可绕过

new File("/data/local/tmp/re.frida.server/frida-agent-64.so").exists()

maps

frida在注入App后会在maps中显示frida的frida-agent.so的内存信息,可以通过搜索特征字符串来检测frida。目前大佬们的去特征的frida一般会使用随机so名称,此时也可以通过查找maps文件内存信息中是否存在一些满足某些条件的特征路径,如data/local/tmp

char line[512];
FILE* fp;
fp = fopen("/proc/self/maps", "r");
if (fp) {
    while (fgets(line, 512, fp)) {
        if (strstr(line, "frida")) {
           
        }
    }
    fclose(fp);
    } else {
       
    }
}

内存扫描库特征

其实也是maps中的特征信息

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 = open(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) {
        
    }
}

查看tcp连接信息

frida-server启动后/proc/net/tcp和/proc/net/tcp6中会有特殊标识:69a2,可以通过搜索tcp中的字符串来检测frida是否启动

public static boolean mCheckFridaTcp(){
  String[] stringArrayTcp6;
  String[] stringArrayTcp;
  String tcpStringTcp6 = mReadFile("/proc/net/tcp6");
  String tcpStringTcp = mReadFile("/proc/net/tcp");
  boolean isFridaExits = false;
  if(null != tcpStringTcp6 && !"".equals(tcpStringTcp6)){
    stringArrayTcp6 = tcpStringTcp6.split("\n");
    for(String sa : stringArrayTcp6){
      if(sa.toLowerCase().contains(":69a2")){
        Log.e(TAG,"tcp文件中发现Frida特征");
        isFridaExits = true;
      }
    }
  }
  if(null != tcpStringTcp && !"".equals(tcpStringTcp)){
    stringArrayTcp = tcpStringTcp.split("\n");
    for(String sa : stringArrayTcp){
      if(sa.toLowerCase().contains(":69a2")){
        Log.e(TAG,"tcp文件中发现Frida特征");
        isFridaExits = true;
      }
    }
  }
  return isFridaExits;

status文件特征

frida注入App后在App的/proc/self/task/pid/status文件中会存在一些frida的特征信息,如gmain、pool-frida、gdbus,可以通过这些特征进行检测,根据目前做过的几个检测来看,这还是比较常用的方法,一些人脸识别的SDK会用到此检测方案。

status

if (strstr(line, "frida") || strstr(line, "gum-js") || strstr(line, "gmain")) {
  fclose(fp);
  rst = filepath;
  strcat(rst, "==>");
  strcat(rst, line);
  return rst;
}

另外,以上检测方法检测皆使用系统函数读取文件和进行检测,实际应用中有很多检测方案会自己通过汇编实现读取文件或者比对方法,此时就需要对具体情况进行具体分析。

本文目前仅记录了比较简单的检测点和NB

最后:

如果需要下载测试Demo可到星球自取

参考文献

[翻译]多种特征检测 Frida-外文翻译-看雪论坛-安全社区|安全招聘|bbs.pediy.com[1]

详解Android studio ndk配置cmake开发native C - 博客 - 编程圈 (bianchengquan.com)[2]

darvincisec/DetectFrida: Detect Frida for Android (github.com)[3]

引用链接

[1] 翻译]多种特征检测 Frida-外文翻译-看雪论坛-安全社区|安全招聘|bbs.pediy.com: https://bbs.pediy.com/thread-217482.htm
[2] 详解Android studio ndk配置cmake开发native C - 博客 - 编程圈 (bianchengquan.com): https://www.bianchengquan.com/article/28252.html
[3] darvincisec/DetectFrida: Detect Frida for Android (github.com): https://github.com/darvincisec/DetectFrida

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Frida是一款免费的,基于Python和JavaScript来实现的,面向开发人员、逆向工程师和安全研究人员的动态检测工具包。 Frida拥有一套全面的测试套件,不但调试效率极高,而且在广泛的使用中经历了多年严格的测试。 尤其是,移动应用安全测试和服务巨头NowSecure对齐钟爱有加,在NowSecure内部,安全人员通过Frida这个工具套装,已经完成对大量的移动应用程序大规模深度的安全分析测试。目前依然在该公司的安全测试中扮演重要的角色。 基于Python和JavaScript的Frida,天生就是跨平台的动态调试工具,不但可以运行在Windows、Linux、macOS之上,而且还可以调试Windows应用程序、Linux应用程序,macOS、iOS、Andriod和QNX等几乎全平台的应用程序。可以说,一旦掌握Frida这套工具,就可以在全平台,对全平台的应用程序进行动态调试和分析。 Frida使用极其方便,在使用过程中,只需将你编写的JavaScript脚本通过Frida自身的工具注入到目标进程中,就可以HOOK任何功能,其中包括但不限于监视加密API或跟踪应用程序关键代码等。在使用过程中,无需知道被“研究”程序的源代码。 尤其是可以一边编辑JavaScript脚本,一边运行JavaScript脚本的功能对于调试分析来说极为友好。只需“保存”正在编辑的JavaScript脚本,就立即就能看到该脚本执行的结果,全称无需其它人工介入,也无需重新启动被“研究”的应用程序,极大地简化了分析流程,同时也极大地提高了工作效率。因此,得到了众多安全分析人士的青睐。 本课程从最基本的调试环境搭建开始,基于经典的Windows“扫雷”游戏的动态调试分析,编码等,循序渐进演示Firda在分析调试Windows应用程序中基本使用方法和技巧。拥有这些知识储备之后,在加上官方的参考文档,你就可以轻松地将这些知识“迁移”至分析和调试其他平台的应用程序。 课程资料,请看第一课中github链接。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值