This section shows the usage of a tool called Frida to perform dynamic instrumentation of Android applications.
Frida is an open source dynamic instrumentation toolkit that enables reverse engineers and programmers to debug a running process. It's a client-server model that uses Frida core and Google v8 engine to hook a process.
Unlike the Xposed framework, it's very easy to use and doesn't need extensive programming and there is no need to restart the device either. With a wide range of platform support on Android, iOS, Linux, Mac, and Windows and powerful APIs, it's one of the best tools to create reverse engineering tools during penetration testing. Frida currently has API bindings for Python, node.js, and .NET and provides them if you would like to create bindings for other programming languages.
As discussed in Chapter 1, Setting Up the Lab, we need the following to get Frida working with our test app:
frida-ps –R
command to see a process listingTo demonstrate the capabilities of Frida, we will use a slightly modified version of the app we have used for the Xposed framework. However, the package name of the vulnerable app is still: com.androidpentesting.hackingandroidvulnapp1
The modified code is shown as following:
The preceding code contains a modified version of setOutput
which only returns true
or false
. When setOutput
is called, the value of i is passed to it which is initialized to 0
. If the value of i
is set to 1
, this application will display the text Cracked. But, since the initialized value is 0
, this app always displays the text Cant crack it.
Let's now use Frida to print the Cracked message on to the activity; however, we won't be doing coding like we did in the Xposed framework section. Frida by nature is a dynamic instrumentation toolkit designed to solve this problem with minimal coding.
Once you install this app, launch it and you should see the familiar screen we saw earlier.
Frida provides lots of features and functionality like hooking functions, modifying function arguments, sending messages, receiving messages, and much more. Covering all of these will take a full chapter in itself; however, we will cover enough to get you started with the more advanced topics in Frida.
Let's see an example of modifying the implementation of our setOutput
to always return true
irrespective of variable i's value.
We need to follow these steps to accomplish modifying our setOutput
method:
create_script
call.script.load
method.We connect to our process using the following code:
session = frida.get_remote_device().attach("com.androidpentesting.hackingandroidvulnapp1")
Next we need to identify the class. In our case, we only have one class, namely the MainActivity
class and the function we are trying to hook is setOutput
. We can use the following code snippets to accomplish that:
Java.perform(function () { var Activity = Java.use("com.androidpentesting.hackingandroidvulnapp1.MainActivity"); Activity.setOutput.implementation = function () { send("setOutput() got called! Let's always return true"); return true; }; });
Since we are trying to make setOutput
always return true
, we have changed the implementation of our call by using the .implementation
function. The send call sends a message to the client side on our desktop from the process here, which is used for sending messages.
You can read more about the Frida's JavaScript API at:
http://www.frida.re/docs/javascript-api/#java
We can also modify the arguments to the methods and if needed can instantiate new objects to pass an argument to the method.
The entire hook.py
, which will hook our setOutput
method using Frida looks like the following:
import frida import sys def on_message(message, data): print message code =""" Java.perform(function () { var Activity = Java.use("com.androidpentesting.hackingandroidvulnapp1.MainActivity"); Activity.setOutput.implementation = function () { send("setOutput() got called! Let's return always true"); return true; }; }); """ session = frida.get_remote_device().attach("com.androidpentesting.hackingandroidvulnapp1") script = session.create_script(code) script.on('message', on_message) print "Executing the JS code" script.load() sys.stdin.read()
Let's run this Python script and trigger the onClick
event of our Crack Me button on the app:
C:\hackingAndroid>python hook.py Executing the JS code {u'type': u'send', u'payload': u"setOutput() got called! Let's return always true"} {u'type': u'send', u'payload': u"setOutput() got called! Let's return always true"}
As you can see, I have pressed the Crack Me button twice and every time we press that button setOutput
got called and our hook always returned true
.
As we can see, we have successfully changed the behavior of the app with dynamic instrumentation using Frida without any reboots or without us having to write lengthy code. We suggest you explore Frida's well written documentation and examples on their official page.