Search code examples
javascriptjavaandroidfrida

how to fix Error: java.lang.ClassNotFoundException on frida


I'm trying to bypass a root detection mechanism on an android app using Frida, I've tried so many different scripts (frida code share) and different approaches (like hiding root) with no luck!

So I tried to locate the class and method responsible for checking if the device is rooted or not and changing it's return value.

This is my script :

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);

If I inject this code normally it won't work because it looks like the isRooted method will get called before it

If I use spawn to run the app and change this method return value it fails with error :

frida.core.RPCException: Error: java.lang.ClassNotFoundException: Didn't find class ...

I've also tried spawning the app and then using objection to run "android root disable" but it will return this error :

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

I'm not sure if this is a problem with Frida or my system or ...

I think if I was able to make my main code runs at exactly after the class gets loaded (like using a loop to check or using a hook) the problem would be fixed but I don't know how to write that kind of code in js for frida.

I'm on macOS 11.5.1 using python 3.9 and installed latest version of frida and objection

I've tested on one rooted phone with android 10 and an emulator with android 6


Solution

  • I was able to solve this issue with a simple yet not very technical solution.

    I used a setInteval to run my hooking over and over until it gets to work, (as @Robert mentioned, I also needed to wrap hooking inside a try catch to prevent the code from stoping after first try)

    This may not work for everyone but since it worked for me I will post the final code, may it helps someone else in the future :)

    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 : you may need to change interval time to match your app needs, it worked for me with 200 miliseconds.