A brief but fun introduction to compromising data integrity on an Android application. **
This article will give an overview of setting up a rooted Android emulator, installing a tool called Frida, creating Frida scripts to intercept code at runtime, and replacing data in an application.
Having a rooted device or emulator image is essential to breaching mobile applications effectively in terms of time and functionality.
A common tool to allow root access in Android devices is called Magisk. The application enables you to modify the filesystem, root access, boot image, and processes.
MagiskOnEmulator is a collection of scripts that automates the Android emulator installation process. Use this to backup and generate a custom emulator image with root access installed.
Frida is a suite of tools that provides an API to dynamically instrument code in native applications. ‘Hooking’ is a scripting API that injects code into the entire device’s memory including a target application.
Frida operates in a client/server model where the server must be installed on the target device. There a couple ways to install the server:
Frida Loader is an Android application that will manage installation for you. Ensure you are breaching the correct device and double check using a command like `frida-ls-devices’. It should return something like:
The USB emulator device is our target. To view a list of process on the device, use `frida-ps -D emulator-5554` or `frida-ps–U` for the USB device.
The goal is to write Frida scripts to intercept and manipulate data for:
As an analogy, I will call these use cases the 3 parrots. The use cases will just echo back data or a message inside the application.
Writing Frida hooks is easy when you have the source code and a debug build. In the real world, you must locate the obfuscated methods after disassembling them. The process usually looks as follows:
Once you have located the target code to hook or have the source code, you can start writing scripts to exploit potential vulnerabilities.
From the source code we know that the ‘JokeService’ class returns a ‘JokeResponse’ when querying the API.
The following Frida script intercepts the network service and returns spoofed data as a response:
The basic premise of the code is:
Kotlin coroutines internally passes an intrinsic parameter to signal the function has suspended instead of returned. In Frida we need to handle this on lines 14-16 before performing the overload by checking for the constant COROUTINE_SUSPENDED.
The command to run the script (frida -U --no-pause -f com.github.ryjen.jokeapp -l network.js) shows application parrots back the hacked response every network call.
The logging should look something like this in the Frida console:
JokeResponse(id=kOfaUvP7Muc, joke=What did the Dorito farmer say to the other Dorito farmer? Cool Ranch!, status=200)
When the user adds a favourite joke, we want to hook into the methods that insert the joke to the database. Then we can replace the data with arbitrary values designed to trick the application. The following script accomplishes the task.
The difference from the previous script is replacing the method call with a spoofed parameter instead of returning spoofed data.
Running the script and saving a joke in the application adds the hacked data to the database.
Again, our logging should log the original data for snooping.
Joke(id=EYo4TCAdUf, content=I tried to write a chemistry joke, but could never get a reaction., created=null, isFavorite=true)
When the user shares a joke, we want to send a hacked web address for the user to follow. We accomplish this by intercepting the android intent system and replacing the joke message.
In the chooser we only look for SEND intents and replace the text value. After running the script, sharing a joke will result in the spoofed content instead. Logging would show the original joke content as expected.
I have shown how to run Frida on a rooted emulator which is a powerful tool for active discovery, testing and manipulation of information in a native application.
Spoofing data in memory is a small sample of what Frida can accomplish (ex. By-passing SSL pinning or encryption).
The best way to avoid hacking by Frida is to 1) avoid rooted mobile devices and 2) detect if the application binary has been tampered with.
If your application is distributed via the play store a verification API from Google play store is available to add an additional security layer to user actions. Additional backend checks might be necessary depending on your architecture.
At the application level some best practices include:
Enterprise applications requiring extra security should consider a service like NowSecure which is provided by the creators of Frida. Other options include VeraCode, Fortify, or Checkmarx.
Dynamic analysis security services (AKA Penetration Testing) can be run ad-hoc per identified risk. Static analysis security services can be integrated into continuous integration per release.
As vulnerabilities and mitigations are constantly evolving, an application must be pro-active in keeping up to date and knowing its risk factors.
In summary, there are several options to prevent hackers from breaching security at the device level and the application level. A service specializing in detection can be practical and adaptable in a cybersecurity landscape.
** DISCLAIMER: This is partially setting up a penetration testing environment. Do not use on targets without authorization as you would be potentially breaking the law. Bugcrowd has a list of projects accepting testing within limits.