基于frida检测demo来学习frida检测及anti

news2024/11/27 1:39:34

原文地址:https://www.zhuoyue360.com/crack/108.html

image.png

前言

随着逆向的攻防强度不断的提升,目前主流的移动安全厂商的加固服务基本上都已包含了常见Hook框架的反调试,我们最常见的hook工具如下:

  1. frida
  2. xposed

为了更好的提升自己相关的经验,我们可以拿这类demo来进行原理的学习.

分析

demo应用在未启动frida的情况下,点击点我按钮发现. 亮了一个frida-agent路径.我们可以反编译该应用去看看它如何检测的.
image.png

1. frida-agent路径

根据它的代码可以看到,该检测案例是通过判断下面两个条件,只要满足以下两个其中之一,则判定frida存在.

  1. /data/local/tmp/re.frida.server/frida-agent-64.so路径的内容是否存在
  2. /data/local/tmp/re.frida.server/frida-agent.so路径的文件是否存在
    public static boolean a() {
        boolean z = new File("/data/local/tmp/re.frida.server/frida-agent-64.so").exists() || new File("/data/local/tmp/re.frida.server/frida-agent.so").exists();
        if (z) {
            Log.e("Ming-CheckFrida", "/data/local/tmp/re.frida.server/frida-agent-64.so中发现Frida特征");
        }
        return z;
    }

看了下,我们的确存在这些应用.我们删除一下看看.
image.png
re.frida.server目录删除就可以了. 当然,这种方法并不好. 我们可以尝试Hook一下 File,把入参包含frida-agent的fileName给他一个不存在的值,即可绕过该检测. 可以看到已经成功的绕过了frida-agent检测项.
image.pngimage.png

let _File = Java.use("java.io.File");
_File.$init.overload("java.lang.String").implementation = function(fileName){
      var f = '';
      if (fileName.indexOf("frida-agent") > -1){
          f = "/sdcard/fuck_frida";
      }else{
          f= fileName
      }
      console.log("fileName ->" + f,f.indexOf("frida-agent"))

      return this.$init(f);
  }

2.TCP检测

根据下面的代码片段,有点基础的读者应该不难看出.它是在检测端口69a2,69a2端口是十六进制的表示,那么其十进制的表示是27042端口.

this.t = (Switch) findViewById(R.id.switchTcp);
this.t.setChecked(false);
String a2 = CheckFrida.a("/proc/net/tcp6");
String a3 = CheckFrida.a("/proc/net/tcp");
if (a2 == null || ClockFaceView.VALUE_PLACEHOLDER.equals(a2)) {
    z2 = false;
} else {
    z2 = false;
    for (String str : a2.split("\n")) {
        if (str.toLowerCase().contains(":69a2")) {
            Log.e("Ming-CheckFrida", "tcp文件中发现Frida特征");
            z2 = true;
        }
    }
}
if (a3 != null && !ClockFaceView.VALUE_PLACEHOLDER.equals(a3)) {
    for (String str2 : a3.split("\n")) {
        if (str2.toLowerCase().contains(":69a2")) {
            Log.e("Ming-CheckFrida", "tcp文件中发现Frida特征");
            z2 = true;
        }
    }
}

public static String a(String str) {
    try {
        FileInputStream fileInputStream = new FileInputStream(str);
        byte[] bArr = new byte[RecyclerView.c0.FLAG_ADAPTER_FULLUPDATE];
        String str2 = ClockFaceView.VALUE_PLACEHOLDER;
        for (int read = fileInputStream.read(bArr); read > 0; read = fileInputStream.read(bArr)) {
            str2 = str2 + new String(bArr, 0, read);
        }
        fileInputStream.close();
        return str2;
    } catch (IOException e) {
        e.printStackTrace();
        return ClockFaceView.VALUE_PLACEHOLDER;
    }
}

image.png

那么我们该如何做呢? 看到上面的方法a可以看出,它是以读文件的方式进行检测的. 此时我们应该以自定义端口的方式进行frida的启动及Hook.

frida-server启动命令:
./frida-server-16.0.2-android-arm64 -l 0.0.0.0:7777
frida hook 自定义端口命令
frida -H 192.168.123.85:7777 -F -l .\hook_frida_check.js

再来看看效果,Wow!! 看来这不只是解决了TCP检测项,我们还顺手的解决了Native-端口检测. 其原理都是一样的.就是看看27042端口是否打开,咱们从本质上去解决就好啦!
image.png

3.map文件

根据下面代码,我们可以看到.它是通过读取文件/proc/self/maps的内容是否包含frida字眼进行检测的.

this.t = (Switch) findViewById(R.id.switchJMap);
this.t.setChecked(false);
if (CheckFrida.a("/proc/self/maps").contains("frida")) {
    Log.e("Ming-CheckFrida", "/proc/self/maps发现Frida特征");
    z = true;
} else {
    z = false;
}

我们其实可以复用我们上面的脚本,当文件名称为maps的时候,我们传入虚拟的maps文件.
通过执行cat /proc/self/maps >> /sdcard/maps命令maps内容到/sdcard/maps中. 来看看效果吧~
image.png

let _File = Java.use("java.io.File");
_File.$init.overload("java.lang.String").implementation = function(fileName){
    var f = '';
    if (fileName.indexOf("frida-agent") > -1){
        f = "/sdcard/fuck_frida";
    }else if(fileName.indexOf("/proc/self/maps") > -1){
        f = "/sdcard/maps";
    }else{
        f= fileName
    }
    return this.$init(f);
}

4. Native-map文件

打开IDA,拖入so文件进去看看. 发现是动态注册JNI_onload被混淆了.用下registerNative
image.png
我们需要的是mCheckFridaNMap,其偏移是0xb654

[RegisterNatives] method_count: 0x6
[RegisterNatives] java_class: com.example.test.util.CheckFrida name: mCheckFridaPort sig: ()Z fnPtr: 0x7dd0acd540  fnOffset: 0x7dd0acd540 libCheckFrida.so!0x9540  callee: 0x7dd0acd020 libCheckFrida.so!0x9020
[RegisterNatives] java_class: com.example.test.util.CheckFrida name: mCheckFridaBus sig: ()Z fnPtr: 0x7dd0acda70  fnOffset: 0x7dd0acda70 libCheckFrida.so!0x9a70  callee: 0x7dd0acd020 libCheckFrida.so!0x9020
[RegisterNatives] java_class: com.example.test.util.CheckFrida name: mCheckFridaNMap sig: ()Z fnPtr: 0x7dd0acf654  fnOffset: 0x7dd0acf654 libCheckFrida.so!0xb654  callee: 0x7dd0acd020 libCheckFrida.so!0x9020
[RegisterNatives] java_class: com.example.test.util.CheckFrida name: mCheckFridaMem sig: ()Z fnPtr: 0x7dd0ad0998  fnOffset: 0x7dd0ad0998 libCheckFrida.so!0xc998  callee: 0x7dd0acd020 libCheckFrida.so!0x9020
[RegisterNatives] java_class: com.example.test.util.CheckFrida name: mCheckFridaMem2 sig: ()Ljava/lang/String; fnPtr: 0x7dd0ad010c  fnOffset: 0x7dd0ad010c libCheckFrida.so!0xc10c  callee: 0x7dd0acd020 libCheckFrida.so!0x9020
[RegisterNatives] java_class: com.example.test.util.CheckFrida name: mCheckFridaP sig: ()Ljava/lang/String; fnPtr: 0x7dd0ad0f20  fnOffset: 0x7dd0ad0f20 libCheckFrida.so!0xcf20  callee: 0x7dd0acd020 libCheckFrida.so!0x9020 

跳到目标函数发现,依然是进行了混淆的. 我们来分析分析.
image.png
查看下F5的伪代码.看到我认为是关键的.

  1. fopen打开文件,给v1
  2. 把stream的值设置为v1
// FILE *fopen(const char *filename, const char *mode);
  v1 = fopen((const char *)&xmmword_F0A0, &byte_F0B0);
  v2 = -686024801;
  stream = v1;

我们分别查看一下v1stream的交叉应用(选中按下x键)
v1的交叉引用:
可以发现,v1 只有一处使用了,就是把steam的值设置为v1,那么接下来,我们只需要聚焦steam即可.
image.png
steam的交叉引用
image.png

  • fclose : 关闭流
  • fgets : 从指定的流中读取数据,每次读取一行。其原型为:char *fgets(char *str, int n, FILE *stream);

我们只需要看看fgets上下文. 先到215行,结果为v41跟踪v41
image.png
根据交叉引用,去看看121行的内容.
image.png
再看看haystack的引用, 发现了一个很关键的strstr
image.png

  • strstr : 返回值为char * 类型( 返回指向 str1 中第一次出现的 str2 的指针);如果 str2 不是 str1 的一部分,则返回空指针。

此时可以hook一下,strstr函数和fopen函数
fopen hook:

function hook_native(){
    var add = Module.findExportByName(null,"fopen");
    console.log("fopenaddr", add);
    Interceptor.attach(add,{
        onEnter:function(args){
            console.log("[+]fopen("+args[0].readCString()+")")
        },
        onLeave:function(){
            console.log("[-]fopen")
        }
    })

    var strstr = Module.findExportByName(null,"strstr");
    console.log("strstr addr", add);
    Interceptor.attach(strstr,{
        onEnter:function(args){
            console.log("[+]strstr("+args[0].readCString()+","+args[1].readCString()+")")
        },
        onLeave:function(){
            console.log("[-]strstr")
        }
    })
}
function call_maps(){
    Java.perform(function(){
        let CheckFrida = Java.use("com.example.test.util.CheckFrida");
        CheckFrida.mCheckFridaNMap();
    })
}
function hook(){
    hook_native();
    call_maps()
}
setImmediate(hook_native)

hook 日志:
通过fopen方法可以发现,它读的是/proc/self/maps,通过strstr可以发现它是在比较是否包含frida字符串.

call_maps()
[+]fopen(/proc/self/maps)
[-]fopen
[+]strstr(12c00000-12c80000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
,frida)
[-]strstr
[+]strstr(12c80000-12e00000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
,frida)
[-]strstr
[+]strstr(12e00000-13100000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
,frida)
[-]strstr
[+]strstr(13100000-13200000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
,frida)
[-]strstr
[+]strstr(13200000-14100000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
,frida)
[-]strstr
[+]strstr(14100000-14140000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
,frida)
[-]strstr
[+]strstr(14140000-14180000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
,frida)
[-]strstr
[+]strstr(14180000-141c0000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
,frida)
[-]strstr
[+]strstr(141c0000-14200000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
,frida)
[-]strstr
[+]strstr(14200000-14240000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
,frida)
[-]strstr
[+]strstr(14240000-16480000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
,frida)
[-]strstr
[+]strstr(16480000-164c0000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
,frida)
[-]strstr
[+]strstr(164c0000-16500000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
,frida)
[-]strstr
[+]strstr(16500000-32c00000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
,frida)
[-]strstr
[+]strstr(7032d000-705b4000 rw-p 00000000 103:11 1544                              /system/framework/arm64/boot.art
,frida)
[-]strstr
[+]strstr(705b4000-706a3000 rw-p 00000000 103:11 1523                              /system/framework/arm64/boot-core-libart.art
,frida)
[-]strstr
[+]strstr(706a3000-706d9000 rw-p 00000000 103:11 1535                              /system/framework/arm64/boot-okhttp.art
,frida)
[-]strstr
[+]strstr(706d9000-7071a000 rw-p 00000000 103:11 1520                              /system/framework/arm64/boot-bouncycastle.art
,frida)
[-]strstr
[+]strstr(7071a000-7072a000 rw-p 00000000 103:11 1517                              /system/framework/arm64/boot-apache-xml.art
,frida)
[-]strstr
[+]strstr(7072a000-70fe6000 rw-p 00000000 103:11 1529                              /system/framework/arm64/boot-framework.art
,frida)
[-]strstr
[+]strstr(70fe6000-71019000 rw-p 00000000 103:11 1526                              /system/framework/arm64/boot-ext.art
,frida)
[-]strstr
[+]strstr(71019000-71110000 rw-p 00000000 103:11 1538                              /system/framework/arm64/boot-telephony-common.art
,frida)
[-]strstr
[+]strstr(71110000-7111e000 rw-p 00000000 103:11 1541                              /system/framework/arm64/boot-voip-common.art
,frida)
[-]strstr
[+]strstr(7111e000-71133000 rw-p 00000000 103:11 1532                              /system/framework/arm64/boot-ims-common.art
,frida)
[-]strstr
[+]strstr(71133000-71136000 rw-p 00000000 103:11 1514                              /system/framework/arm64/boot-android.test.base.art

那么我们依然使用上面maps文件中的方法 - 伪造maps文件
image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/867390.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何限制运行时间的一则考虑

在日常使用中,会遇到限制过期时间的问题,但是,对于时间的判断,很难找到一个信任根!如果没有信任根,这个问题其实无从判断。 从实用的角度来设计,我们假定可以找到一个相对可信的信任根&#xf…

从零实战SLAM-第三课(李群与李代数)

在七月算法报的班,老师讲的蛮好。好记性不如烂笔头,关键内容还是记录一下吧,课程入口,感兴趣的同学可以学习一下。 --------------------------------------------------------------------------------------------------------…

2023年中国负极石墨用坩埚市场规模现状及前景分析:负极材料为行业增长助推器[图]

负极石墨用坩埚分为再生坩埚和石墨匣钵,其中,再生坩埚主要应用于艾奇逊炉工艺的石墨化工序,石墨匣钵主要应用于预碳化和碳化工序。 负极石墨用坩埚分类 资料来源:共研产业咨询(共研网) 得益于动力电池的旺…

Git Cherry-pick使用

概述 无论项目大小,当你和一群程序员一起工作时,处理多个 Git 分支之间的变更都会变得很困难。有时,与其把整个 Git 分支合并到另一个分支,不如选择并移动几个特定的提交。这个过程被称为 "挑拣", 即 Cherry-pick。 本…

java获取到heapdump文件后,如何快速分析?

简介 在之前的OOM问题复盘之后,本周,又一Java服务出现了内存问题,这次问题不严重,只会触发堆内存占用高报警,没有触发OOM,但好在之前的复盘中总结了dump脚本,会在堆占用高时自动执行jstack与jm…

百度云盘发展历程与影响

摘要: 百度云盘作为中国领先的云存储与共享服务提供商,自其创立至今经历了多个阶段的发展与变革。本论文通过对百度云盘的历史回顾与分析,探讨了其在技术、商业模式、用户体验以及对社会的影响等方面的演变。同时,还分析了在竞争激…

谈谈Java开发语言

目录 1.概念 2.特点 3.应用领域 4.就业情况 1.概念 Java是一种面向对象的编程语言,它由James Gosling和他的团队在1995年于Sun Microsystems(现在是Oracle Corporation)开发出来。Java的设计目标是让开发者能够编写一次代码,在…

服务器安装Tomcat

下载Tomcat 下载地址在这: Tomcat官网 下载完成以后把压缩包上传到服务器中(我传到了www/java),进行解压(解压到),如果没有进行指定解压到哪里,默认是到root文件夹中 tar -zxvf /www/java/apache-tomcat-9.0.103.tar.…

策略模式实战应用

场景 假设做了个卖课网站,会员等级分为月vip、年vip、终生vip,每个等级买课的优惠力度不一样,传统的写法肯定是一堆的 if-else,现在使用策略模式写出代码实现 代码实现 策略模式的核心思想就是对扩展开放,对修改关闭…

Leetcode33 搜索旋转排序数组

题解: /*** 旋转排序数组可分为N1 N2两个部分,如:[4,5,6,7,1,2,3],N1为[4,5,6,7],N2为[1,2,3]** 必然满足以下两个条件:* 1. N1和N2都是分别递增的;* 2. N1中的所有元素大于N2中的所有元素;** …

matlab解常微分方程常用数值解法1:前向欧拉法和改进的欧拉法

总结和记录一下matlab求解常微分方程常用的数值解法,本文先从欧拉法和改进的欧拉法讲起。 d x d t f ( x , t ) , x ( t 0 ) x 0 \frac{d x}{d t}f(x, t), \quad x\left(t_{0}\right)x_{0} dtdx​f(x,t),x(t0​)x0​ 1. 前向欧拉法 前向欧拉法使用了泰勒展开的第…

GitOps实践 | 企业生产环境Jenkins流水线分享,从Gitlab到镜像构建到部署测试以及企业微信消息通知...

关注回复【学习交流群】加入【安全开发运维】答疑交流群 目录: 0x00 前言简述 描述: 当前在企业内部开发中最常用的CI/CD(持续集成和交付),总是可以看到Jenkins(大叔)的身影,其作为老牌开源的CI/CD工具&…

【Minecraft】Fabric Mod开发完整流程3 - 配方与挖掘等级

目录 新配方工作台配方无序合成配方有序合成配方 熔炉配方 挖掘等级与掉落物挖掘等级标准等级配置易错点分析 战利品与掉落物普通方块掉落物矿石方块掉落物 新配方 工作台配方 为便于你快速创建配方,可以直接去这个网站上通过拖拽的方式创建属于你的配方表&#xf…

9.3.1网络原理(应用层)

HTTP和HTTPS后面的博客会另外介绍. 一.设计应用层协议: 1.明确当前请求和响应中包含哪些内容. 2.明确具体请求和响应格式. 网络上传输的数据,本质上就是字符串(无法直接传对象). 序列号:发送数据的时候,把对象转化成二进制字符串.(注意,网络上传输的数据统一为大端字节序…

基于飞桨图学习框架实现的城市地点动态关系挖掘

李双利 飞桨开发者技术专家(PPDE),百度研究院商业智能实验室研究实习生,中国科学技术大学在读博士生。 主要进行时空数据挖掘和图深度学习的相关研究工作。曾获2021年百度研究院年度优秀实习生,有多篇基于飞桨完成的论…

Linux常见面试题,应对面试分享

操作系统基础 1.cpu占⽤率太⾼了怎么办? 排查思路是什么,怎么定位这个问题,处理流程 其他程序: 1.通过top命令按照CPU使⽤率排序找出占⽤资源最⾼的进程 2.lsof查看这个进程在使⽤什么⽂件或者有哪些线程 3.询问开发或者⽼⼤,是什么业务在使⽤这个进程…

Linux学习之sed多行模式

N将下一行加入到模式空间 D删除模式空间中的第一个字符到第一个换行符 P打印模式空间中的第一个字符到第一个换行符 doubleSpace.txt里边的内容如下: goo d man使用下边的命令可以实现把上边对应的内容放到doubleSpace.txt。 echo goo >> doubleSpace.txt e…

无代码集成励销云CRM连接更多应用

场景描述: 基于励销云的开放API,实现无代码集成连接励销云与其它应用。通过Aboter可轻松搭建业务自动化流程,实现多个应用之间的数据连接。 接口能力: 用户模块业务模块拜访签到模块公海客户模块联系人模块合同模块客户模块任务…

EVE-NG 隐藏没有镜像的模板

eve-ng 默认情况下,在添加node时,会列出所有的模板,这样用着很不方便。 通过以下方式,可以使没有设备的模板不可见 cp /opt/unetlab/html/includes/config.php.distribution /opt/unetlab/html/includes/config.php 如下图&#…

大数据面试题:说下Spark中的Transform和Action,为什么Spark要把操作分为Transform和Action?

面试题来源: 《大数据面试题 V4.0》 大数据面试题V3.0,523道题,679页,46w字 可回答:Spark常见的算子介绍一下 参考答案: 我们先来看下Spark算子的作用: 下图描述了Spark在运行转换中通过算…