Why Frida?
Becase it can be many things, know more. Its is,
- easy, sure learning curve takes some time, but it pays off spectacularly.
- efficient, a rough estimate for the modification took 30 min in frida vs 2 hours in traditional methods, its way more flexible.
- elegant when compared to traditional ways. you get creative new ideas and implement them easily (implementating manually takes way longer).
My setup
Genymotion, but why? (better than avd) runs way faster than avd, default root, runs via virtual box, image size is small, less cpu usage compared to avd.
latest frida server and client from frida/releases.
- in my case, ‘frida-server-15.0.17-android-arm.xz’
move the fridaserver to android device/emulator and start it.
adb push /data/local/tmp/firda-server adb shell cd /data/local/tmp/frida-server ./frida-server &
Modding with very little effort
Frida has a great feature ‘TRACE’, but without manually injection, by doing it dynamically, more here.
what it does in oneline is you give it ‘wildcard methods’ and a process, it will then log the input params and out values when the traced method is called of the target process
# for tracing all methods which contains 'license'
noone@pc:frida-trace -U Firewall -j '*!*license*/isu'
Trace Logs
26442 ms Settings.isLicenseActive("<instance: android.content.Context, $className: com.protectstar.firewall.activity.ActivityRules>")
26443 ms <= false
26598 ms Settings.isLicenseActive("<instance: android.content.Context, $className: com.protectstar.firewall.activity.ActivityRules>")
26599 ms <= false
26603 ms Settings.isLicenseActive("<instance: android.content.Context, $className: com.protectstar.firewall.activity.ActivityRules>")
26604 ms <= false
39331 ms Settings.isLicenseActive("<instance: android.content.Context, $className: com.protectstar.firewall.activity.settings.Settings>")
39331 ms <= false
45614 ms Settings.isLicenseActive("<instance: android.content.Context, $className: com.protectstar.firewall.activity.settings.Settings>")
45614 ms <= false
49377 ms Settings.isLicenseActive("<instance: android.content.Context, $className: com.protectstar.firewall.activity.ActivityLogs>")
49378 ms <= false
49567 ms <= false
49581 ms Settings.isLicenseActive("<instance: android.content.Context, $className: com.protectstar.firewall.activity.ActivityLogs>")
49581 ms <= false
52637 ms Settings.isLicenseActive("<instance: android.content.Context, $className: com.protectstar.firewall.activity.settings.SettingsInApp>")
52637 ms <= false
52786 ms Settings.isLicenseActive("<instance: android.content.Context, $className: com.protectstar.firewall.activity.settings.SettingsInApp>")
52789 ms <= false
52792 ms SettingsInApp.initLicense()
With just guessing the method name ‘license’, following license methods were found and its input and output params are logged when run via adb, without even decompiling and going through code (isn’t this great!?)
8 directories, 31 files
__handlers__/
├── com.protectstar.firewall.activity.settings.Settings
│ └── isLicenseActive.js <--- this file seems interesting?!
├── com.protectstar.firewall.activity.settings.SettingsInApp
│ ├── initLicense.js
...
│ └── licenseSuccess.js
├── com.protectstar.firewall.cloud.Auth
│ ├── getLicense1Url.js
...
├── com.protectstar.firewall.utility.LicenseActivation
│ ├── access_000.js
...
│ ├── checkLicenseDuration.js <--- this file seems interesting?!
│ └── _init.js
├── com.protectstar.firewall.utility.LicenseActivation_Customer
...
│ ├── access_900.js
│ └── _init.js
├── com.protectstar.firewall.utility.LicenseActivation_Reason
│ ├── valueOf.js
│ └── values.js
├── com.protectstar.firewall.utility.LicenseActivation_ResponseListener
├── error.js
└── licenseSuccess.js
Now navigate though all sections of the app and find any interesting methods invoked through the trace logs.
patching on the fly, without seeing the original code
By observing the invoked methods and its input/output values, we can guess the method name to patch, it is ‘isLicenseActive’ from ‘com.protectstar.firewall.activity.settings.Settings’, in frida-trace, we see the return value is False, so why not make it as true and observe the behaviour?
// patching the method
function main() {
Java.perform(function () {
// match the method signature
Java.use('com.protectstar.firewall.activity.settings.Settings').isLicenseActive.implementation = function (
context
) {
return true;
};
});
}
setImmediate(main);
After patching, navigating the app we now see the premium features are unlocked, that was way easier than conventional methods, greatly reduces the time.
End
I intend to use Frida in the future stuff I do, its simply great. Seeya next time. untill then - aghontpi :)