Open gebing opened 5 years ago
Can you share the patch? I'm facing same problem. Thanks!
Sorry for reply later, because i am on vacation. Below is may patch for this problem and also including use user-defined class loader:
function javaUse(className, classLoader, ignoreClasses) {
ignoreClasses = Array.isArray(ignoreClasses) ? ignoreClasses : [].slice.call(arguments, 2);
const classObject = Java.use("java.lang.Object").class;
const classOverload = !ignoreClasses.length ? null : (classLoader ? classLoader : Java.use("java.lang.ClassLoader")).loadClass.overload('java.lang.String');
const oldImpl = classOverload ? classOverload.implementation : null;
const oldLoader = classLoader ? Java.classFactory.loader : null;
if (classLoader) Java.classFactory.loader = classLoader || null;
if (classOverload) classOverload.implementation = function (name) {
try {
return classOverload.call(this, name);
} catch (error) {
if (error.message.indexOf("java.lang.ClassNotFoundException") < 0 || ignoreClasses.indexOf(name) < 0) throw error;
return classObject;
}
};
try {
return Java.use(className);
} catch (error) {
throw error;
} finally {
if (classOverload) classOverload.implementation = oldImpl;
if (classLoader) Java.classFactory.loader = oldLoader;
}
};
And sample usage is: javaUse('re.frida.NewApiClass', null, ['java.time.Duration'])
Enjoy Your Vacation ⭐️ Thank you so much 💯
My old code: Java.use("com.xxx.app.Push.MyPushReceiver");
It throw exception:
Abort message: 'java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: JNI GetArrayLength called with pending exception java.lang.NoClassDefFoundError: Failed resolution of: Lcom/xiaomi/mipush/sdk/MiPushMessage;'
My new code: javaUse("com.xxx.app.Push.MyPushReceiver", null, ['com.xiaomi.mipush.sdk.MiPushMessage']);
It now throw new Exception: returned class java.lang.Object instead of com.xiaomi.mipush.sdk.MiPushMessage
Class com.xiaomi.mipush.sdk.MiPushMessage
not packed in the apk.
The class com.xiaomi.mipush.sdk.MiPushMessage
showed as it being imported in the java decompiled code of com.xxx.app.Push.MyPushReceiver
, but in the smali code it only appear few times, which is not always executed during normal program's flow. Somehow Frida pickup the not found class when I do Java.use
.
Now it look like a casting problem. Hopefully you can take a look.
I have included partial crash log here (with adb logcat -b crash
):
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Revision: '0'
ABI: 'arm'
pid: 28237, tid: 28237, name: .cloud.app >>> com.xxx.cloud.app <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: JNI GetArrayLength called with pending exception java.lang.NoClassDefFoundError: Initiating class loader of type dalvik.system.PathClassLoader returned class java.lang.Object instead of com.xiaomi.mipush.sdk.MiPushMessage.'
r0 00000000 r1 00006e4d r2 00000006 r3 00000008
r4 00006e4d r5 00006e4d r6 ff95830c r7 0000010c
r8 00000002 r9 e5090740 r10 e5e23d2c r11 e4bac90e
ip e84223d8 sp ff9582f8 lr e8391621 pc e8388e5e
backtrace:
#00 pc 0001ce5e /system/lib/libc.so (offset 0x1c000) (abort+58)
#01 pc 00000307 <anonymous:e598f000>
EOF
***
So I fixed my problem 🍳 It work great for me. Instead of
if (error.message.indexOf("java.lang.ClassNotFoundException") < 0 || ignoreClasses.indexOf(name) < 0)
throw error;
return classObject;
I used Java.registerClass
to automatic register a new class.
if (error.message.indexOf("java.lang.ClassNotFoundException") < 0 || ignoreClasses.indexOf(name) < 0)
throw error;
return Java.registerClass({name: name}).class;
I am glad that you solved your problem. Obviously my patch is not very suitable for your case, but your modification is a more general solution.
i found Java.use() will throw ClassNotFoundException when some of the class's constructors or methods have undefined return type or parameter type.
The sample class is like below:
And the exception is like below:
This is very common in Android because of the difference of SDK version, and can work fine under different SDK version, but these classes can not manipulate under frida.
So my suggestion is:
Add an option parameter for Java.use to supply optional ignored classes array, such like:
Java.use('re.frida.NewApiClass', ['java.time.Duration'])
In implement of factory.use(), when calling getDeclaredConstructors/getDeclaredMethods, hook the loadClass function call and return java.lang.Object when loadClass throws ClassNotFoundException and class name is in ignore classes array.
@oleavr If you agree this suggestion, i can make a pull request includes implementation and unit test.