
After installing the merged apk back to my device, it would crash very quickly, hinting at an error or some integrity checks.
Opening the logcat window in Android Studio and filtering to the package name showed the app was crashing due to an error from a native function 'verifyNativeIntegrity' called from the function 'x1'.

Loading the apk into JADX, I found the function definition using search, and found the class it's called in. Looking inside the class you will see a 'System.LoadLibrary' call, showing you which library to investigate.

To further investigate 'verifyNativeIntegrity', extract the library from the libs folder in JADX, and open in Ghidra or IDA. Open the functions dropdown and look for functions beginning with 'Java_'. These are the native methods which are callable from the Java code using JNI.
Ghidra will provide a pseudocode representation of the function for you, however, you may be able to ignore this if the code is basic enough. In my case, verifyNativeIntegrity returns a boolean, so for patching it will be as simple as setting the return value to true.

For patching there are 2 main options:
To patch with frida, we will be writing a frida script for all patches and injecting this along with the frida gadget and the gadget config.
First, create the 'frida-gadget.config' file and insert the following
{
"interaction": {
"type": "listen",
"address": "127.0.0.1",
"port": 27042,
"on_port_conflict": "fail",
"on_load": "wait"
}
}
Next, create the 'frida.js' file and use the following template to patch the native function
Java.perform(function () {
let Log = Java.use("android.util.Log");
Log.d("Frida", "Frida script loaded");
Interceptor.attach(Module.getExportByName('libnativelibrary.so', 'Java_com_example_verifyNativeIntegrity'), {
onEnter: function (args) {
},
onLeave: function (retval) {
Log.d("Frida", `verifyNativeIntegrity was called`);
let result = retval.toInt32();
Log.d("Frida", `verifyNativeIntegrity result=${result} forced to 1`);
retval.replace(1);
}
});
});
Next, run
objection patchapk -2 -c frida-gadget.config -l frida.js -s apkname_antisplit.apk


let exit = Java.use("java.lang.System").exit;
let Exception = Java.use('java.lang.Exception');
exit.implementation = function (code) {
Log.d("frida", `System.exit is called with code=${code}`);
let currentException = Exception.$new();
Log.d("frida", `Called from: ${currentException.getStackTrace()[1]}`);
if (code == 0) {
Log.d("frida", `System.exit bypassed`);
return;
}
this.exit(code);
};
we can view which function is calling exit.
Then we can navigate to this function in JADX to work out why it was called.

Note: checkPNAndAdIdWrapper has been renamed in JADX to make decompilation easier. It is good practice to do similar if you can work out the purpose of any methods.
checkPNAndAdIdWrapper calls several functions including the one below for signature checking, one for checking the package name and more integrity checks
As all of these are being called by K1, and K1 has no other functionality, patching out these checks can be easily done by replacing K1's implementation to disable its functionality completely.
First right click the function's definition and copy as frida snippet. Then edit the frida snippet to remove the original function call. Like this:
let exampleActivity = Java.use("com.example.activity");
exampleActivity["K1"].implementation = function () {
console.log(`com.example.activity.K1 was called`);
// this["K1"](); // REMOVE THIS LINE OR COMMENT IT OUT LIKE THIS
};
After adding this snippet to the frida.js file, restart the app again and rerun frida. You should now see this check has also been bypassed. If more checks are present, repeat the steps adding to the frida.js file until all methods have been patched.
With the apk open in JADX, I noticed the `com.kimchangyoun.rootbeerFresh` package.


Searching for `RootBeer` in JADX showed that the methods were only called in one single function which returned false if no triggers where hit.
Patching this is very easy, simply copy as frida snippet and replace the return value to always be false.
let rc = Java.use("rc"); // Where rc is the class containing function l where l is the function calling RootBeer
rc["l"].implementation = function (context) {
return false;
};
Then rerun the app and execute frida again
Once you have implemented all the patches into frida.js, it's time to make the frida script run automatically, without the need for adb and another device.
To do this, we will edit the frida-gadget.config like so:
{
"interaction": {
"type": "script",
"path": "libfrida-gadget.script.so"
}
}
Then rebuild and patch the apk with objection, this time passing the frida.js script to be included within the apk.
objection patchapk -2 -c frida-gadget.config -l frida.js -s apkname_antisplit.apk