I'm trying to intercept and change the isRooted
and isEmulator
but I can't seem to hook the instance.
Java.perform(() => {
var classLoaderToUse = Java.enumerateClassLoadersSync()[2]; //found through trial and error
Java.classFactory.loader = classLoaderToUse;
try {
Java.choose("com.moe.device.DeviceDetails", {
onMatch: function (instance) {
console.log("[ * ] Instance found in memory: " + instance);
a=instance.collect();
a.map.put("isRooted", "false");
a.map.put(DeviceInformationInspector.IS_EMULATOR, String.valueOf(false));
},
onComplete: function () {},
});
} catch (error) {
console.log(error);
}
});
Here is a mockup of the function Im trying to hook:
package com.moe.device;
public final class DeviceDetails{
public static void collect(Context context, Map<String, String> map) {
map.put("deviceManufacturer", Build.MANUFACTURER);
map.put("hardwareModel", Build.MODEL);
map.put("deviceBoard", Build.BOARD);
map.put("deviceBrand", Build.BRAND);
map.put("buildDisplayId", Build.DISPLAY);
map.put("isRooted", isRooted());
map.put(DeviceInformationInspector.IS_EMULATOR, String.valueOf(isEmulator()));
}
private static String isRooted() {
return "False"
}
private static String isEmulator() {
return False
}
}
I cant get the "Instance found in memory:" to show up but any console.log()
in onComplete
does. I'm not sure if I'm doing the map
replacements correct but right now I'm just trying to get inside the method.
The common approach used by Frida is not to hook existing instances of classes in memory. Instead you simply hook the whole class so every existing or instance that is created in future will use your hooked method(s).
The common approach would be this hooking code:
Java.perform(() => {
let DeviceDetailsClass = Java.use("com.moe.device.DeviceDetails");
DeviceDetailsClass.isRooted.implementation = function () {
return "False";
};
DeviceDetailsClass.isEmulator.implementation = function () {
return "False";
};
});