网站LOGO
紫血小站
页面加载中
3月20日
网站LOGO 紫血小站
人山人海人来人往,自尊自爱自由自在
菜单
frida常用检测点及其原理--一把梭方案
正文
  • 用户的头像
    首次访问
    上次留言
    累计留言
    我的等级
    我的角色
    打赏二维码
    打赏博主
    frida常用检测点及其原理--一把梭方案
    点击复制本页信息
    微信扫一扫
    文章二维码
    文章图片 文章标题
    创建时间
  • 一 言
    确认删除此评论么? 确认
  • 本弹窗介绍内容来自,本网站不对其中内容负责。

    frida常用检测点及其原理--一把梭方案

    Dem0li · 转载 ·
    工具安卓 · frida
    共 10171 字 · 约 3 分钟 · 734
    本文最后更新于2024年05月31日,已经过了292天没有更新,若内容或图片失效,请留言反馈

    frida反调试

    查看哪个so在检测frida

    python 代码:
        function hook_dlopen() {
        Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
            {
                onEnter: function (args) {
                    var pathptr = args[0];
                    if (pathptr !== undefined && pathptr != null) {
                        var path = ptr(pathptr).readCString();
                        console.log("load " + path);
                    }
                }
            }
        );
    }
    so的加载流程,那么就会知道linker会先对so进行加载与链接,然后调用so的.init_proc函数,接着调用.init_array中的函数,最后才是JNI_OnLoad函数,所以我需要先确定检测点大概在哪个函数中。

    管他检测啥、直接一把梭

    python 代码:
        function replace_str() {
        var pt_strstr = Module.findExportByName("libc.so", 'strstr');
        var pt_strcmp = Module.findExportByName("libc.so", 'strcmp');
     
        Interceptor.attach(pt_strstr, {
            onEnter: function (args) {
                var str1 = args[0].readCString();
                var str2 = args[1].readCString();
                if (
                    str2.indexOf("REJECT") !== -1 ||
                    str2.indexOf("tmp") !== -1 ||
                    str2.indexOf("frida") !== -1 ||
                    str2.indexOf("gum-js-loop") !== -1 ||
                    str2.indexOf("gmain") !== -1 ||
                    str2.indexOf("linjector") !== -1
                ) {
                    console.log("strstr-->", str1, str2);
                    this.hook = true;
                }
            }, onLeave: function (retval) {
                if (this.hook) {
                    retval.replace(0);
                }
            }
        });
     
        Interceptor.attach(pt_strcmp, {
            onEnter: function (args) {
                var str1 = args[0].readCString();
                var str2 = args[1].readCString();
                if (
                    str2.indexOf("REJECT") !== -1 ||
                    str2.indexOf("tmp") !== -1 ||
                    str2.indexOf("frida") !== -1 ||
                    str2.indexOf("gum-js-loop") !== -1 ||
                    str2.indexOf("gmain") !== -1 ||
                    str2.indexOf("linjector") !== -1
                ) {
                    //console.log("strcmp-->", str1, str2);
                    this.hook = true;
                }
            }, onLeave: function (retval) {
                if (this.hook) {
                    retval.replace(0);
                }
            }
        })
     
    }
     
    replace_str();
    测试小红书 、bilibili都可以过

    检测文件名(改名)、端口名27042(改端口)、双进程保护(spawn启动)

    检测D-Bus

    检测的原因是因为安卓系统中,D-Bus通信并不常见,而且不同于在传统Linux系统中广泛使用,安卓系统使用Binder机制来实现进程间通信(IPC),而不是使用D-Bus
    D-Bus是一种进程间通信(IPC)和远程过程调用(RPC)机制,最初是为Linux开发的,目的是用一个统一的协议替代现有的和竞争的IPC解决方案。
    python 代码:
        //遍历连接手机所有端口发送D-bus消息,如果返回"REJECT"这个特征则认为存在frida-server。
     
    //内存中存在frida rpc字符串,认为有frida-server
    /*
     * 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);
    }
    检测D-Bus可以通过hook系统库函数,比如strstr、strcmp等等
    python 代码:
        function replace_str() {
        var pt_strstr = Module.findExportByName("libc.so", 'strstr');
        var pt_strcmp = Module.findExportByName("libc.so", 'strcmp');
     
        Interceptor.attach(pt_strstr, {
            onEnter: function (args) {
                var str1 = args[0].readCString();
                var str2 = args[1].readCString();
                if (str2.indexOf("REJECT") !== -1) {
                    //console.log("strcmp-->", str1, str2);
                    this.hook = true;
                }
            }, onLeave: function (retval) {
                if (this.hook) {
                    retval.replace(0);
                }
            }
        });
     
        Interceptor.attach(pt_strcmp, {
            onEnter: function (args) {
                var str1 = args[0].readCString();
                var str2 = args[1].readCString();
                if (str2.indexOf("REJECT") !== -1) {
                    //console.log("strcmp-->", str1, str2);
                    this.hook = true;
                }
            }, onLeave: function (retval) {
                if (this.hook) {
                    retval.replace(0);
                }
            }
        })
     
    }
     
    replace_str();

    检测/proc/pid/maps依赖文件

    maps文件中存储的是APP运行时加载的依赖
    当启动frida后,在maps文件中就会存在 frida-agent-64.so、frida-agent-32.so 文件。
    java 代码:
        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. */
        }
    }
    绕过方案
    python 代码:
        function replace_str_maps() {
        var pt_strstr = Module.findExportByName("libc.so", 'strstr');
        var pt_strcmp = Module.findExportByName("libc.so", 'strcmp');
     
        Interceptor.attach(pt_strstr, {
            onEnter: function (args) {
                var str1 = args[0].readCString();
                var str2 = args[1].readCString();
                if (str2.indexOf("REJECT") !== -1  || str2.indexOf("frida") !== -1) {
                    this.hook = true;
                }
            }, onLeave: function (retval) {
                if (this.hook) {
                    retval.replace(0);
                }
            }
        });
     
        Interceptor.attach(pt_strcmp, {
            onEnter: function (args) {
                var str1 = args[0].readCString();
                var str2 = args[1].readCString();
                if (str2.indexOf("REJECT") !== -1  || str2.indexOf("frida") !== -1) {
                    this.hook = true;
                }
            }, onLeave: function (retval) {
                if (this.hook) {
                    retval.replace(0);
                }
            }
        })
     
    }
     
    replace_str();

    检测/proc/pid/tast下线程、fd目录下打开文件

    在 /proc/pid/task 目录下,可以通过查看不同的线程子目录,来获取进程中每个线程的运行时信息。这些信息包括线程的状态、线程的寄存器内容、线程占用的CPU时间、线程的堆栈信息等。通过这些信息,可以实时观察和监控进程中每个线程的运行状态,帮助进行调试、性能优化和问题排查等工作。

    /proc/pid/fd 目录的作用在于提供了一种方便的方式来查看进程的文件描述符信息,这对于调试和监控进程非常有用。通过查看文件描述符信息,可以了解进程打开了哪些文件、网络连接等,帮助开发者和系统管理员进行问题排查和分析工作。

    打开frida调试后这个task目录下会多出几个线程,检测点在查看这些多出来的线程是否和frida调试相关。
    在某些app中就会去读取 /proc/stask/线程ID/status 文件,如果是运行frida产生的,则进行反调试。例如:gmain/gdbus/gum-js-loop/pool-frida等

    1. gmain:Frida 使用 Glib 库,其中的主事件循环被称为 GMainLoop。在 Frida 中,gmain 表示 GMainLoop 的线程。
    2. gdbus:GDBus 是 Glib 提供的一个用于 D-Bus 通信的库。在 Frida 中,gdbus 表示 GDBus 相关的线程。
    3. gum-js-loop:Gum 是 Frida 的运行时引擎,用于执行注入的 JavaScript 代码。gum-js-loop 表示 Gum 引擎执行 JavaScript 代码的线程。
    4. pool-frida:Frida 中的某些功能可能会使用线程池来处理任务,pool-frida 表示 Frida 中的线程池。
    5. linjector 是一种用于 Android 设备的开源工具,它允许用户在运行时向 Android 应用程序注入动态链接库(DLL)文件。通过注入 DLL 文件,用户可以修改应用程序的行为、调试应用程序、监视函数调用等,这在逆向工程、安全研究和动态分析中是非常有用的。

    绕过

    python 代码:
        function replace_str() {
        var pt_strstr = Module.findExportByName("libc.so", 'strstr');
        var pt_strcmp = Module.findExportByName("libc.so", 'strcmp');
     
        Interceptor.attach(pt_strstr, {
            onEnter: function (args) {
                var str1 = args[0].readCString();
     
                var str2 = args[1].readCString();
                if (str2.indexOf("tmp") !== -1 ||
                    str2.indexOf("frida") !== -1 ||
                    str2.indexOf("gum-js-loop") !== -1 ||
                    str2.indexOf("gmain") !== -1 ||
                    str2.indexOf("gdbus") !== -1 ||
                    str2.indexOf("pool-frida") !== -1||
                    str2.indexOf("linjector") !== -1) {
                    //console.log("strcmp-->", str1, str2);
                    this.hook = true;
                }
            }, onLeave: function (retval) {
                if (this.hook) {
                    retval.replace(0);
                }
            }
        });
     
        Interceptor.attach(pt_strcmp, {
            onEnter: function (args) {
                var str1 = args[0].readCString();
                var str2 = args[1].readCString();
                if (str2.indexOf("tmp") !== -1 ||
                    str2.indexOf("frida") !== -1 ||
                    str2.indexOf("gum-js-loop") !== -1 ||
                    str2.indexOf("gmain") !== -1 ||
                    str2.indexOf("gdbus") !== -1 ||
                    str2.indexOf("pool-frida") !== -1||
                    str2.indexOf("linjector") !== -1) {
                    //console.log("strcmp-->", str1, str2);
                    this.hook = true;
                }
            }, onLeave: function (retval) {
                if (this.hook) {
                    retval.replace(0);
                }
            }
        })
     
    }
     
    replace_str();

    frida-server启动

    当frida-server启动时,在 /data/local/tmp/目录下会生成一个文件夹并且会生成一下带有frida的特征。

    1. 重新编译去特征
    2. hook

    直接调用openat的syscall的检测在text节表中搜索frida-gadget.so / frida-agent.so字符串,避免了hook libc来anti-anti的方法

    注入方式改为

    1. frida-inject
    2. ptrace注入 配置文件的形式注入
    3. 编译rom注入

    从inlinehook角度检测frida

    https://zhuanlan.zhihu.com/p/557713016
    https://bbs.kanxue.com/thread-269862.htm

    hook_open函数可以查看是哪里检测了so文件

    python 代码:
        function hook_open(){
        var pth = Module.findExportByName(null,"open");
        Interceptor.attach(ptr(pth),{
            onEnter:function(args){
                this.filename = args[0];
                console.log("",this.filename.readCString())
                if (this.filename.readCString().indexOf(".so") != -1){
                    args[0] = ptr(0)
                }
            },onLeave:function(retval){
                return retval;
            }
        })
    }
    setImmediate(hook_open)
    替换成一个正常的

    本文转载自看雪论坛,原文链接:https://bbs.kanxue.com/thread-278145.htm

    声明:本文由 Zixue(博主)依据 CC BY-NC 4.0 许可协议 授权转载。
    转载自: 看雪论坛。原作者是: Dem0li

    还没有人喜爱这篇文章呢

    现在已有

    1

    条评论
    我要发表评论
    1. 头像 不乖学长
      · ·
      • 等级:Lv.1
      • 角色:访客
      • 在线:很久之前
      头像
      不乖学长
      沙发

      哥哥牛逼

      评论
    博客logo 紫血小站 人山人海人来人往,自尊自爱自由自在
    MOEICP 萌ICP备20241077号 ICP 粤ICP备15110322号-2

    💻️ Zixue 昨天 14:49 在线

    🕛

    本站已运行 1 年 89 天 10 小时 33 分
    紫血小站. © 2023 ~ 2025.
    网站logo

    紫血小站 人山人海人来人往,自尊自爱自由自在