如何修复错误:frida 上的 java.lang.ClassNotFoundException

Posted

技术标签:

【中文标题】如何修复错误:frida 上的 java.lang.ClassNotFoundException【英文标题】:how to fix Error: java.lang.ClassNotFoundException on frida 【发布时间】:2021-10-06 21:24:47 【问题描述】:

我正在尝试绕过使用 Frida 的 android 应用程序上的根检测机制,我尝试了很多不同的脚本(frida 代码共享)和不同的方法(如隐藏根),但没有成功!

所以我试图找到负责检查设备是否已root并更改其返回值的类和方法。

这是我的脚本:

setTimeout(function()  // avoid java.lang.ClassNotFoundException
  Java.perform(function() 
    var hook = Java.use("app.name.RootUtils");
    console.log("info: hooking target class");

    hook.isRooted.overload().implementation = function() 
      console.log("info: entered target method");
      return Java.use("java.lang.Boolean").$new(false);
    
  );
,0);

如果我正常注入此代码,它将无法工作,因为看起来 isRooted 方法会在它之前被调用

如果我使用 spawn 运行应用程序并更改此方法返回值,它会失败并出现错误:

frida.core.RPCException:错误:java.lang.ClassNotFoundException:找不到类...

我也尝试过生成应用程序,然后使用反对来运行“android root disable”,但它会返回此错误:

frida.core.RPCException: TypeError: cannot read property 'getApplicationContext' of null 在 getApplicationContext (src/android/lib/libjava.ts:21)

我不确定这是 Frida 或我的系统的问题还是...

我想如果我能够让我的主代码在类被加载之后运行(比如使用循环检查或使用钩子)问题就会得到解决,但我不知道如何编写那种frida 的 js 代码。

我在 macOS 11.5.1 上使用 python 3.9 并安装了最新版本的 frida 和 objection

我已经在一部带有 android 10 的 root 手机和带有 android 6 的模拟器上进行了测试

【问题讨论】:

【参考方案1】:

找不到类

你怎么知道这个类是app.name.RootUtils你有没有使用Jadx或apktool反编译成应用程序?调用RootUtils.isRooted()的方法怎么样?是否有任何特殊代码可以加载 RootUtils 类,例如来自应用程序中包含的非标准 dex 文件?如果该类是从一个特殊的 dex 文件加载的,您可以挂钩此 dex 加载机制并首先执行它,然后为 RootUtils.isRooted() 安装您的挂钩。

或者假设 RootUtils.isRooted() 仅从另一种方法调用并且不使用特殊代码来加载 RootUtils 类,您可以挂钩该方法并使用此挂钩安装您的 RootUtils.isRooted() 挂钩。

错误处理

javascript 中处理错误的正确方法是使用 try catch 块,而不是 setTimeout 函数:

Java.perform(() => 
    try 
        var hook = Java.use("app.name.RootUtils");
        ...
     catch (e) 
        console.log("Failed to hook root detection" + e);
    

关于你在课堂上的问题

【讨论】:

我使用 Objection (android hooking search/watch/list) 来查找 app.name.RootUtils 和 isRooted 方法,做了一些测试并看到它被调用,所以我知道这是我需要的方法钩。我不确定 dex 文件,有 3 个关于 setTimeout 的文件(classes0.dex.dat,classes1.dex.dat,classes2.dex),它在某处被建议,我尝试使用它当然没有运气。同样使用 try catch 也不能解决主要问题,它只会显示一个很好的错误:) @Mahdi 这两个 dex.dat 文件非常不寻常,Android 不会自动加载这些文件,因此必须有某种加载器代码。您应该检查这些 dex.dat 文件是否以某种方式加密或修改以防止它们被静态分析。【参考方案2】:

我能够通过一个简单但技术含量不高的解决方案来解决这个问题。

我使用 setInteval 一遍又一遍地运行我的钩子,直到它开始工作,(正如@Robert 提到的,我还需要将钩子包装在 try catch 中以防止代码在第一次尝试后停止)

这可能对每个人都不起作用,但因为它对我有用,所以我将发布最终代码,希望它在未来对其他人有所帮助:)

Java.perform(function() 
  var it = setInterval(function()
    try
      var hook = Java.use("app.name.RootUtils");
      console.log("info: hooking target class");

      hook.isRooted.overload().implementation = function() 
        console.log("info: entered target method");
        clearInterval(it);
        return Java.use("java.lang.Boolean").$new(false);
      
     catch(e) 
      console.log("failed!");
    
  ,200); // runs every 200milisecods
);

PS :您可能需要更改间隔时间以满足您的应用需求,它对我有用 200 毫秒。

【讨论】:

好吧,这也是一种可能的方式,可能不是每次都有效,但那又怎样。但我会更改clearInterval(it); 的位置。您可以将其移至 catch(e) 之前的行,那么您不需要 hooked 变量。【参考方案3】:

有时应用会在其类加载器中进行加密,您可能需要将 Java.classFactory.loader 替换为应用的自定义类加载器,以使 Java.use 正常运行。

这是如何完成的:

Java.perform(function() 

    //get real classloader
    //from http://www.lixiaopeng.top/article/63.html
    var application = Java.use("android.app.Application");
    var classloader;
    application.attach.overload('android.content.Context')
        .implementation = function(context) 
            var result = this.attach(context); // run attach as it is
            classloader = context.getClassLoader(); // get real classloader
            Java.classFactory.loader = classloader;
        return result;
    
    
    //interesting classes
    const interestingClassPath = "com.myApp.SometingInteresting";
    interestingClass = Java.use(interestingClassPath);

   //do whatever you like here
)

【讨论】:

以上是关于如何修复错误:frida 上的 java.lang.ClassNotFoundException的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 java.lang.OutOfMemoryError:Java 堆空间错误? [复制]

如何修复错误:无法将类型“java.lang.String”的值转换为所需类型“java.lang.Long”;

如何修复 Android Studio 中的 Lottie 错误 - 'Error:Execution failed for task' java.lang.RuntimeException [...

如何修复java.lang.ClassCastException:java.lang.Double无法转换为变量表达式的java.math.BigDecimal错误?

嗨,我不知道如何修复此游标错误,“java.lang.IllegalStateException:无法从 CursorWindow 读取第 0 行,第 1 列。”

使用 buildozer 打包我的 kivy 应用程序时如何修复“java.lang.module.FindException:找不到模块 java.se.ee”错误