APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

admin 2024年12月23日10:35:14评论22 views字数 6258阅读20分51秒阅读模式
此文章只为学习而生,请勿干违法违禁之事,本公众号只在技术的学习上做以分享,通过现实的几个案例来实战锻炼水平,有个大佬公众号私聊我讨论了一下看了看,遇到所以试过,所有行为与本公众号无关。

sdfd

01

日常截图

APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

漏洞盒子众测的某金融APP用了爱马氏加密啊,检测Frida难受啊。

APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

然后又测试了一下梆某人的加密啊,又检测Frida难受啊,还不能通用,烦死了。

02

反调思路来源

1. 绕过bilibili frida反调试:https://bbs.kanxue.com/thread-277034.htm

2. frida常用检测点及其原理-一把梭方案:https://bbs.kanxue.com/thread-278145.htm

3. 绕过最新版bilibili app反frida机制:https://bbs.kanxue.com/thread-281584.htm

4. 某车联网APPx梆反调试分析:https://bbs.kanxue.com/thread-277692.htm

5. 记一次爱加密反调试分析及绕过思路:https://bbs.kanxue.com/thread-259619.htm

03

起手式

 第一个肯定先看的金融APP的爱马仕加密。

APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

在启动后就Process terminated。

01

Hook android_dlopen_ext

大佬们说检测Frida一般都在Native层实现,会用线程轮询的方式来检测,那hook线程创建函数android_dlopen_ext,来看看由哪个so实现或者在加载到哪个so时候触发反调试进程终止。

// 检测SO代码然后将hook到的so文件进行过检测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);                }            }        }    );}// 调用查看检测的hook_dlopen()

APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

发现了libexecmain.so执行后进程退出。

我们可以猜测libexecmain.so中创建了一个线程检测到了Frida使其退出。

02

HOOK pthread_create

 现在这步是确认是否由libexecmain创建的检测线程,用以下脚本:

function hook_pthread_create(){    Interceptor.attach(Module.findExportByName(null, "pthread_create"),        {            onEnter: function (args) {                var module = Process.findModuleByAddress(ptr(this.returnAddress))                if (module != null) {                    console.log("[pthread_create] called from", module.name)                }                else {                    console.log("[pthread_create] called from", ptr(this.returnAddress))                }            },        })}hook_pthread_create()

APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

发现只有libexec.so一直在创建进程,而libexecmain.so从未出现,而libexec.so是上一个调用的,可能就是由libexec.so创建的检测线程。

03

Patch pthread_create

 知道App通过哪些SO进行pthrea_create自己创建的线程了,我们可以尝试进行Patch HOOK过掉看看能不能过掉检测。

// 1. patch  pthread_create函数function patchPthreadCreate(){    let pthread_create = Module.findExportByName(null, "pthread_create")        let org_pthread_create = new NativeFunction(pthread_create, "int", ["pointer", "pointer", "pointer", "pointer"])        let my_pthread_create = new NativeCallback(function (a, b, c, d) {            let m = Process.getModuleByName("libexec.so");            let base = m.base            console.log(Process.getModuleByAddress(c).name)            if (Process.getModuleByAddress(c).name == m.name) {                console.log("pthread_create")                return 0;            }            return org_pthread_create(a, b, c, d)        }, "int", ["pointer", "pointer", "pointer", "pointer"])        Interceptor.replace(pthread_create, my_pthread_create)}patchPthreadCreate()

APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

发现应用跑无响应了,但是经过了很长的时间没有退出说明有点戏,试试另一个方法。

04

Patch 所有调用pthread_create 函数的caller

function patchPthreadCreateCaller(){    let pthread_create = Module.findExportByName(null, "pthread_create")    Interceptor.attach(pthread_create, {        onEnter: function (args) {            this.isHook = false            let m = Process.getModuleByName("libexec.so");            let base = m.base            console.log(Process.getModuleByAddress(args[2]).name)            if (Process.getModuleByAddress(args[2]).name == m.name) {                              //start_rtn地址  start_rtn偏移       caller地址                               console.log(args[2], args[2].sub(base), this.context.lr.sub(m.base))            }            let addr = args[2].sub(base)            console.log(addr)        }    })}patchPthreadCreateCaller()

APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

单独列出来的addr就是创建线程的偏移量,所以再改进一下。

function patchPthreadCreateCaller(){    let pthread_create = Module.findExportByName(null, "pthread_create")    Interceptor.attach(pthread_create, {        onEnter: function (args) {            this.isHook = false            let m = Process.getModuleByName("libexec.so");            let base = m.base            console.log(Process.getModuleByAddress(args[2]).name)            if (Process.getModuleByAddress(args[2]).name == m.name) {                              //start_rtn地址  start_rtn偏移       caller地址                               console.log(args[2], args[2].sub(base), this.context.lr.sub(m.base))                if (args[2] >= base && args[2] < base.add(m.size)) {                    Memory.patchCode(args[2], 4, code => {                        console.log("Patching thread function at " + args[2]);                        const cw = new Arm64Writer(code, {pc: args[2]});                        cw.putLdrRegU64('x0', 0);                        cw.flush();                      });                }            }        }    })  }patchPthreadCreateCaller()

APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

还是不行,直到看到一位大神评论:

APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

04

初级脚本最终版

01

爱马仕加密最终方案:自建pthread_create

function hook_pthread() {  var pthread_create_addr = Module.findExportByName(null, 'pthread_create');  console.log("pthread_create_addr,", pthread_create_addr);  var pthread_create = new NativeFunction(pthread_create_addr, "int", ["pointer", "pointer", "pointer", "pointer"]);  Interceptor.replace(pthread_create_addr, new NativeCallback(function (parg0, parg1, parg2, parg3) {    var so_name = Process.findModuleByAddress(parg2).name;    var so_path = Process.findModuleByAddress(parg2).path;    var so_base = Module.getBaseAddress(so_name);    var offset = parg2 - so_base;    console.log("so_name", so_name, "offset", offset, "path", so_path, "parg2", parg2);    var PC = 0;    if ((so_name.indexOf("libexec.so") > -1) || (so_name.indexOf("xxxx") > -1)) {      console.log("find thread func offset", so_name, offset);      if ((207076 === offset)) {        console.log("anti bypass");      } else if (207308 === offset) {        console.log("anti bypass");      } else if (283820 === offset) {        console.log("anti bypass");      } else if (286488 === offset) {        console.log("anti bypass");      } else if (292416 === offset) {        console.log("anti bypass");      } else if (293768 === offset) {        console.log("anti bypass");      } else if (107264 === offset) {        console.log("anti bypass");      } else {        PC = pthread_create(parg0, parg1, parg2, parg3);        console.log("ordinary sequence", PC)      }    } else {      PC = pthread_create(parg0, parg1, parg2, parg3);      // console.log("ordinary sequence", PC)    }    return PC;  }, "int", ["pointer", "pointer", "pointer", "pointer"]))}hook_pthread();

 爱马仕加密的初步反调可以用此脚本无脑过。

APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

我们直接看if elseif我改为1使其错误,得到offset偏移量:

APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

然后一个个填进if elseif里即可无脑过。

APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

02

梆某人最终脚本

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("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("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()

so的加载流程,那么就会知道linker会先对so进行加载与链接,然后调用so的.init_proc函数,接着调用.init_array中的函数,最后才是JNI_OnLoad函数,但是啥也不管一把梭是最方便的,可能会有点卡,多起几次。(https://bbs.kanxue.com/thread-278145.htm)

APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

05

小叙

最近和前启明师傅聊了一下过抓包检测的问题,佬给我提供了一个很好的思路,过几天再更新通杀APP抓包。

原文始发于微信公众号(进击的HACK):APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月23日10:35:14
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   APP渗透|安服仔们又稳了!过爱/梆企业版初级反调的Frida检测(含脚本)https://cn-sec.com/archives/3541795.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息