frida icon indicating copy to clipboard operation
frida copied to clipboard

Frida doesn't catch Java exceptions in Java hooks

Open andreafioraldi opened this issue 6 years ago • 1 comments

Frida ignore Java exception generated by NativeFunction calls and propagate (so setExceptionHandler miss them) and le the app crash when the exception is generated by the app itself.

Here an example reproducer (in the comment there is the exception from logcat):

/*
2019-12-18 16:07:56.197 17107-17107/com.example.ndktest1 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.ndktest1, PID: 17107
    java.lang.IllegalStateException: Could not execute method for android:onClick
        at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
        at android.view.View.performClick(View.java:7125)
        at android.view.View.performClickInternal(View.java:7102)
        at android.view.View.access$3500(View.java:801)
        at android.view.View$PerformClick.run(View.java:27336)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
        at android.view.View.performClick(View.java:7125) 
        at android.view.View.performClickInternal(View.java:7102) 
        at android.view.View.access$3500(View.java:801) 
        at android.view.View$PerformClick.run(View.java:27336) 
        at android.os.Handler.handleCallback(Handler.java:883) 
        at android.os.Handler.dispatchMessage(Handler.java:100) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7356) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 
     Caused by: java.lang.ArithmeticException: divide by zero
        at com.example.ndktest1.MainActivity.test_java_func(MainActivity.java:22)
        at com.example.ndktest1.MainActivity.genExc(MainActivity.java:35)
        at java.lang.reflect.Method.invoke(Native Method) 
        at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385) 
        at android.view.View.performClick(View.java:7125) 
        at android.view.View.performClickInternal(View.java:7102) 
        at android.view.View.access$3500(View.java:801) 
        at android.view.View$PerformClick.run(View.java:27336) 
        at android.os.Handler.handleCallback(Handler.java:883) 
        at android.os.Handler.dispatchMessage(Handler.java:100) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7356) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 
*/

Process.setExceptionHandler(function(d) {
  console.log(d)
  return false
})

// To be compatible with frida-fuzzer
rpc.exports.loop = function () { }

Java.perform(function() {

  var MainActivity = Java.use('com.example.ndktest1.MainActivity');
  
  MainActivity.sendMessage.implementation = function () {
  
    console.log (" >> Button clicked!");
  
    var activity = this;
    var JString = Java.use('java.lang.String');
  
    // decomment to try with propagate
    //var test_java_func_steal = activity.test_java_func.clone({ exceptions: 'steal' });

    var fuzzer_test_one_input = function (payload, size) {

      var arr = Java.array('byte', Array.from(payload.readByteArray(size)));
      var str = JString.$new(arr);

      console.log (payload.readByteArray(size));
  
      //test_java_func_steal.call(activity, str);
      activity.test_java_func(str);

    }

    var mem = Memory.allocUtf8String("bbb");
    fuzzer_test_one_input(mem, 1);

    // input that trigger the ArithmeticException
    mem = Memory.allocUtf8String("aaa");

    try {
      fuzzer_test_one_input(mem, 1);
    } catch (err) {
      // should catch here the ArithmeticException...
      console.log("CATCHED!\n" + err.stack);
      throw err;
    }
    
    // execute again as nothing happened
    mem = Memory.allocUtf8String("bbb");
    fuzzer_test_one_input(mem, 1);
  
  }

});

I attach the code of the sample app and the APK. ndktest1.zip app-debug.apk.zip

With the button "Button" you trigger the sendMessage hook in the script, with the button "Crash" you trigger the ArithmeticException (it is simply an hardcoded call to test_java_func("aaa")).

andreafioraldi avatar Dec 18 '19 15:12 andreafioraldi

Hi, is this solved?

prajwal-333 avatar Jun 23 '22 23:06 prajwal-333