本文不构成任何技术操作指导或建议,仅供技术交流与学习参考。如发现本文内容存在可能违反法律规定的情况,请立即联系本人删除相关内容。(已对图片中出现的包名和应用名进行处理)

学习一篇文章:SO 加载
参考文档:bilibili frida 检测分析绕过

1. 绕过 frida 反调试
学习到在 linux 系统中,so 的加载是 dlopen 函数 (系统级) 在处理,frida 检测往往在 SO 文件中,那我们就要排查是哪个 SO 文件在做这个事情,即查看调用栈。可以通过 hook 这个函数来查看调用栈:

	function hook_dlopen(soName = '') {
    Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), {
        onEnter: function(args) {
            var pathptr = args[0];
            if (pathptr) {
                var path = ptr(pathptr).readCString();
                console.log("Loading: " + path);
                if (path.indexOf(soName) >= 0) {
                    console.log("Already loading: " + soName);
                    // hook_system_property_get();
                }
            }
        }
    });
}
setImmediate(hook_dlopen);

结果如下:

[ONEPLUS A6010::com.xxxxxxxxxx ]-> Loading: /system/framework/oat/arm64/embryo.odex
Loading: /system/framework/oat/arm64/org.apache.http.legacy.boot.odex
Loading: /data/app/com.xxxxxxxxxx-YbqwF-6pNu60XJkbEOJhjg==/oat/arm64/base.odex
Loading: /data/app/com.xxxxxxxxxx-YbqwF-6pNu60XJkbEOJhjg==/lib/arm64/libnicai.so
Loading: /data/app/com.xxxxxxxxxx-YbqwF-6pNu60XJkbEOJhjg==/lib/arm64/libmsaoaidsec.so
Already loading: libmsaoaidsec.so
Process terminated
[ONEPLUS A6010::com.xxxxxxxxxx ]->

frida 检测点就应该在 libmsaoaidsec.so 中,继续缩小范围,从下面这张图,我们可以了解到,在加载 so 时,在 jni_onload()函数之前会先加载 init() 函数,我们可以通过设置 jni 钩子来判断检测点处在哪个阶段。

Pastedimage20250529000502.png


代码如下:

function hook_JNI_OnLoad(){
    let module = Process.findModuleByName("libmsaoaidsec.so")
    Interceptor.attach(module.base.add(0x13a4c + 1), {
        onEnter(args){
            console.log("JNI_OnLoad")
        }
    })
}

hook 后,没有任何回显,frida 被毙掉,那么监测点就在 init 函数后,jni 函数前。搜索:

Pastedimage20250529001012.png


定位.init_proc函数,但是发现有平坦化混淆:

Pastedimage20250528182508.png


通过 D810 去混淆结果如下:

void init_proc()
{
  const char *v0; // x23
  __int64 v1; // x0
  unsigned int v2; // w0
  unsigned __int64 StatusReg; // [xsp+0h] [xbp-870h] BYREF
  void *v4; // [xsp+8h] [xbp-868h]
  int v6; // [xsp+18h] [xbp-858h]
  int v7; // [xsp+1Ch] [xbp-854h]
  void *v8; // [xsp+20h] [xbp-850h]
  char *v10; // [xsp+30h] [xbp-840h]
  FILE *v11; // [xsp+38h] [xbp-838h]
  char v12[2000]; // [xsp+40h] [xbp-830h] BYREF
  __int64 v13; // [xsp+810h] [xbp-60h]

  StatusReg = _ReadStatusReg(ARM64_SYSREG(3, 3, 0xD, 0, 2));
  v13 = *(StatusReg + 40);
  v4 = &StatusReg + -0xFA;
  *off_47FB8 = sub_123F0();
  sub_12550();
  sub_12440();
  if ( *off_47FB8 > 23 )
    *off_47ED8 = 1;
  if ( (sub_25A48() & 1) == 0 )
  {
    v10 = v12;
    memset(v10, 0, 0x7D0uLL);
    v2 = getpid();
    _sprintf_chk(v12, 0LL, 2000LL, "/proc/%d/cmdline", v2);
    v11 = fopen(v12, "r");
    if ( v11 )
    {
      v8 = v4;
      memset(v4, 0, 0x7D0uLL);
      v0 = v4;
      fscanf(v11, "%s", v4);
      fclose(v11);
      if ( !strchr(v0, 58) )
        sub_1BEC4();
    }
    v1 = sub_13728();
    sub_23AD4(v1);
    v6 = sub_C830();
    if ( v6 != 1 || (v7 = sub_95C8()) != 0 )
      sub_9150();
  }
}

主要是绕过if ( (sub_25A48() & 1) == 0 )分支,加上这段被混淆了,要善用 Graph,下面框中的代码块就是需要绕过的逻辑

Pastedimage20250528234902.png


修改调度器函数如下:

Pastedimage20250528235132.png


然后 apply patch,重打包 app,安装到手机上,看看效果:

Pastedimage20250528235536.png


耶!成功!!!