首页 > 其他分享 >【Android 逆向】frida 检测绕过

【Android 逆向】frida 检测绕过

时间:2023-03-15 18:58:11浏览次数:30  
标签:function 逆向 console hook pthread var frida Android com

1. aaa.apk 安装到手机,是一个叫玩吧的应用

./hooker
......
23248  浏 览 器                                     com.browser2345_oem                             
32541  玩吧                                        com.wodi.who                                    
 2447  电话和短信存储                                   com.android.providers.telephony                 
 2447  电话服务                                      com.android.phone                               
 3264  电量和性能                                     com.miui.powerkeeper  
......

2. 启动hluda版frida server hluda-server-14.2.13-android-arm64 绕过一些对frida特征的检查

执行 frida -Uf com.wodi.who --no-pause,直接崩溃退出

Spawned `com.wodi.who`. Resuming main thread!                           
[MI 5X::com.wodi.who]-> Process terminated
[MI 5X::com.wodi.who]->

说明有对frida 附着到进程存在检测

3. 常用检测有 对 TracerPid 的检测,参考r0trace 的方案进行绕过

var ByPassTracerPid = function () {
    var fgetsPtr = Module.findExportByName("libc.so", "fgets");
    var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']);
    Interceptor.replace(fgetsPtr, new NativeCallback(function (buffer, size, fp) {
        var retval = fgets(buffer, size, fp);
        var bufstr = Memory.readUtf8String(buffer);
        if (bufstr.indexOf("TracerPid:") > -1) {
            Memory.writeUtf8String(buffer, "TracerPid:\t0");
            console.log("tracerpid replaced: " + Memory.readUtf8String(buffer));
        }
        return retval;
    }, 'pointer', ['pointer', 'int', 'pointer']));
};

日志

Spawned `com.wodi.who`. Resuming main thread!                           
[MI 5X::com.wodi.who]-> tracerpid replaced: TracerPid:  0
Process terminated
[MI 5X::com.wodi.who]->

还是不行,看来还有别的地方检测

4.尝试hook pthread_create 来看一下哪里调用到了它

function hook_func() {
    var pthread_creat_addr = Module.findExportByName("libc.so", "pthread_create")
    Interceptor.attach(pthread_creat_addr,{
        onEnter(args){
            console.log("call pthread_create...")
            let func_addr = args[2]
            console.log("The thread function address is " + func_addr)
            console.log('pthread_create called from:\n' 
            + Thread.backtrace(this.context, Backtracer.ACCURATE)
            .map(DebugSymbol.fromAddress)
            .join('\n')
             + '\n');
        }
    })
}

执行日志:


call pthread_create...
The thread function address is 0xc0512129
The libmsaoaidsec.so base 0xc0501000
pthread_create called from:
0xc05123fd libmsaoaidsec.so!0x113fd
0xc0511ab7 libmsaoaidsec.so!0x10ab7
0xc0511bc1 libmsaoaidsec.so!0x10bc1
0xc050d5b9 libmsaoaidsec.so!_init+0x1ac
0xec63662b

......
tracerpid replaced: TracerPid:  0
Process terminated

可以看到 libmsaoaidsec.so 执行了0x113fd 后好像就出问题了,而且这个是在_init+0x1ac,很值得怀疑,看一下反汇编的代码

0xc0512129 - 0xc0501000 = 0x11129
可以看到这里看起来一个线程搞事情

int sub_113E0()
{
  _DWORD *v0; // r4
  pthread_t v2; // [sp+0h] [bp-10h] BYREF
  int v3; // [sp+4h] [bp-Ch]

  v0 = off_1FC04;
  v3 = *(_DWORD *)off_1FC04;
  pthread_create(&v2, 0, (void *(*)(void *))sub_11128, 0);
  return *v0 - v3;
}

那么hook 掉这个 sub_11128 ,让他啥也不干,对应偏移地址 0x000113E0

    
    Interceptor.replace(module.base.add(0x00011128+1), new NativeCallback(function() {
        console.log("0x00011129 replace success!!!")
    }, 'void', []))

执行日志

***
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'xiaomi/tiffany/tiffany:8.1.0/OPM1.171019.019/V11.0.3.0.ODBCNXM:user/release-keys'
Revision: '0'
ABI: 'arm'
pid: 12322, tid: 12322, name: com.wodi.who  >>> com.wodi.who <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x32b1
    r0 0000c6dd  r1 0000008c  r2 8ea8c4cb  r3 0000023d
    r4 00000000  r5 0008d5f4  r6 00003225  r7 000001aa
    r8 dd932900  r9 ffd70784  sl 00000000  fp ffd70878
    ip ea1a962c  sp ffd6e638  lr c052bc95  pc c052bc96  cpsr 200f0030

backtrace:
    #00 pc 00001c96  /data/app/com.wodi.who-Gf4PUi4Emat5i9N3B4wFBA==/lib/arm/libmsaoaidsec.so (offset 0x12000)
    #01 pc 00001c91  /data/app/com.wodi.who-Gf4PUi4Emat5i9N3B4wFBA==/lib/arm/libmsaoaidsec.so (offset 0x12000)
***

还是崩了,说明还有地方在检测,比如这个00001c96+0x12000处,
可以看到这里在检测linker的情况,查询了符号表和字符串表,估计实在检查一些函数是否被hook,那先hooker当前这个函数

    Interceptor.replace(module.base.add(0x00013AB0+1), new NativeCallback(function() {
        console.log("0x00013AB1 replace success!!!")
    }, 'void', []))

注意: Thumb指令的地址 ,hook的时候要加1,然后就ok了,进程不再崩溃,执行frida命令ok

日志

Process

tracerpid replaced: TracerPid:  0
tracerpid replaced: TracerPid:  0
[MI 5X::com.wodi.who]-> Process
{
    "arch": "arm",
    "codeSigningPolicy": "optional",
    "id": 12563,
    "pageSize": 4096,
    "platform": "linux",
    "pointerSize": 4
}
[MI 5X::com.wodi.who]-> tracerpid replaced: TracerPid:  0

全部代码

var ByPassTracerPid = function () {
    var fgetsPtr = Module.findExportByName("libc.so", "fgets");
    var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']);
    Interceptor.replace(fgetsPtr, new NativeCallback(function (buffer, size, fp) {
        var retval = fgets(buffer, size, fp);
        var bufstr = Memory.readUtf8String(buffer);
        if (bufstr.indexOf("TracerPid:") > -1) {
            Memory.writeUtf8String(buffer, "TracerPid:\t0");
            console.log("tracerpid replaced: " + Memory.readUtf8String(buffer));
        }
        return retval;
    }, 'pointer', ['pointer', 'int', 'pointer']));
};
//setImmediate(ByPassTracerPid);

function hook_dlopen(soName) {
    Interceptor.attach(Module.findExportByName(null, "dlopen"),
        {
            onEnter: function (args) {
                var pathptr = args[0];
                if (pathptr !== undefined && pathptr != null) {
                    var path = ptr(pathptr).readCString();
                    if (path.indexOf(soName) >= 0) {
                        this.is_can_hook = true;
                    }
                }
            },
            onLeave: function (retval) {
                if (this.is_can_hook) {
                    console.log("hook start...");
                    hook_func()
                }
            }
        }
    );
 
    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();
                    if (path.indexOf(soName) >= 0) {
                        this.is_can_hook = true;
                    }
                }
            },
            onLeave: function (retval) {
                if (this.is_can_hook) {
                    console.log("hook start...");
                    hook_func()
                }
            }
        }
    );
}

function hook_func() {
    var pthread_creat_addr = Module.findExportByName("libc.so", "pthread_create")
    Interceptor.attach(pthread_creat_addr,{
        onEnter(args){
            console.log("call pthread_create...")
            let func_addr = args[2]
            console.log("The thread function address is " + func_addr)
 
            let libmsaoaidsec = Process.findModuleByName("libmsaoaidsec.so")
            if (libmsaoaidsec != null){
                console.log("The libmsaoaidsec.so base " + libmsaoaidsec.base)
                bypass_thread(libmsaoaidsec)
            }

            console.log('pthread_create called from:\n' 
            + Thread.backtrace(this.context, Backtracer.ACCURATE)
            .map(DebugSymbol.fromAddress)
            .join('\n')
             + '\n');
        }
    })
}

function bypass_thread(module) {
    // Interceptor.replace(module.base.add(0x0000FA98+1), new NativeCallback(function() {
    //     console.log("0x0000FA99 replace success!!!")
    // }, 'void', []))
    
    Interceptor.replace(module.base.add(0x00011128+1), new NativeCallback(function() {
        console.log("0x00011129 replace success!!!")
    }, 'void', []))

    
P
}

function main() {
    ByPassTracerPid()
    hook_dlopen("libc.so")
}

setImmediate(main)

标签:function,逆向,console,hook,pthread,var,frida,Android,com
From: https://www.cnblogs.com/gradyblog/p/17219605.html

相关文章

  • Android权限
    权限 我们知道,Android应用都运行在沙盒中,默认情况下这些应用只能访问他们自己的域,即自己的文件和非常少量的系统服务。为了能够和系统或者其他应用交互,app就需要申请额外......
  • maui BlazorWebView Android 中混合使用https和http
    <BlazorWebViewHostPage="wwwroot/index.html"BlazorWebViewInitialized="blazorWebView_BlazorWebViewInitialized"> privatevoidblazorWebView_BlazorWebVie......
  • 【Android Studio】 SQLite 数据库 增删改查
    今日目标:参照标题实现效果:  实现过程:1、创建实现页面 页面设计思路:最外层垂直线性布局、内部使用三个线性布局、后两个用的水平排版,用来显示数值。实例化四......
  • 20201306 Ep1 逆向及Bof基础实践
    1逆向及Bof基础实践说明1.1实践目标本次实践的对象是一个名为pwn1的linux可执行文件。该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串......
  • Android compileSdkVersion、buildToolsVersion、minSdkVersion、targetSdkVersion
    1、CompileSdkVersion是你SDK的版本号,也就是APILevel,指定了Gradle编译你的App时使用的AndroidAPI版本  2、buildeToolVersion是你构建工具的版本,其中包括了打包工具......
  • 【验证码逆向专栏】某验四代五子棋、消消乐验证码逆向分析
    声明本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切......
  • Android App开发JNI环境配置
    因为想写一个native_crash的app做测试,所以搭建一个这样的jni环境。jni环境配置可以自己写配置文件,也可以使用AndroidStudio自动生成。下面我们用AndroidStudio为IDE来进......
  • android 10虚拟相机
    虚拟相机有很多用途,比如可以实现Android手机直播,刷脸等场景,最近无意间发现有人实现了这个功能,nvsh.xyz,根据官网https://nvsh.xyz视频可以实现用一个视频来替换摄像头,......
  • Android Studio学习笔记1
    Toast浮窗提示默认是底部弹出Menu隐藏菜单,不占据内存(表现为右上角的三个点)Intent进行启动活动(页面跳转),具有显示跳转和隐式跳转两个方式也可以传递信息控件——......
  • 几道rust逆向
    以前做了一两次rs题,唯一感觉就是这是什么大粪语言今天好好练一下,两个简单题和一个又臭又长的题checkin-rs用来入门rust逆向感觉挺不错的首先得找main函数但是这玩意......