OWASP MASTG
Search
⌃K

Testing Tools

To perform security testing different tools are available in order to be able to manipulate requests and responses, decompile apps, investigate the behavior of running apps and other test cases and automate them.
The MASTG project has no preference in any of the tools below, or in promoting or selling any of the tools. All tools below have been verified if they are "alive", meaning that updates have been pushed recently. Nevertheless, not all tools have been used/tested by the authors, but they might still be useful when analyzing a mobile app. The listing is sorted in alphabetical order. The list is also pointing out commercial tools.
Disclaimer: At the time of writing, we ensure that the tools being used in the MASTG examples are properly working. However, the tools might be broken or not work properly depending on your OS version of both your host computer and your test device. The functioning of the tooling can be further impeded by whether you're using a rooted/jailbroken device, the specific version of the rooting/jailbreak method and/or the version of the tool. The MASTG does not take any responsibility over the working status of the tools. If you find a broken tool or example, please search or file an issue in the tool original page, e.g. in the GitHub issues page.

Tools for all Platforms

Angr

Angr (Android)

Angr is a Python framework for analyzing binaries. It is useful for both static and dynamic symbolic ("concolic") analysis. In other words: given a binary and a requested state, Angr will try to get to that state, using formal methods (a technique used for static code analysis) to find a path, as well as brute forcing. Using angr to get to the requested state is often much faster than taking manual steps for debugging and searching the path towards the required state. Angr operates on the VEX intermediate language and comes with a loader for ELF/ARM binaries, so it is perfect for dealing with native code, such as native Android binaries.
Angr allows for disassembly, program instrumentation, symbolic execution, control-flow analysis, data-dependency analysis, decompilation and more, given a large set of plugins.
Since version 8, Angr is based on Python 3, and can be installed with pip on *nix operating systems, macOS and Windows:
pip install angr
Some of angr's dependencies contain forked versions of the Python modules Z3 and PyVEX, which would overwrite the original versions. If you're using those modules for anything else, you should create a dedicated virtual environment with Virtualenv. Alternatively, you can always use the provided docker container. See the installation guide for more details.
Comprehensive documentation, including an installation guide, tutorials, and usage examples are available on Angr's Gitbooks page. A complete API reference is also available.
You can use angr from a Python REPL - such as iPython - or script your approaches. Although angr has a bit of a steep learning curve, we do recommend using it when you want to brute force your way to a given state of an executable. Please see the "Symbolic Execution" section of the "Reverse Engineering and Tampering" chapter as a great example on how this can work.

Frida

​Frida is a free and open source dynamic code instrumentation toolkit written by Ole André Vadla Ravnås that works by injecting the QuickJS JavaScript engine (previously Duktape and V8) into the instrumented process. Frida lets you execute snippets of JavaScript into native apps on Android and iOS (as well as on other platforms).
To install Frida locally, simply run:
pip install frida-tools
Or refer to the installation page for more details.
Code can be injected in several ways. For example, Xposed permanently modifies the Android app loader, providing hooks for running your own code every time a new process is started. In contrast, Frida implements code injection by writing code directly into the process memory. When attached to a running app:
  • Frida uses ptrace to hijack a thread of a running process. This thread is used to allocate a chunk of memory and populate it with a mini-bootstrapper.
  • The bootstrapper starts a fresh thread, connects to the Frida debugging server that's running on the device, and loads a shared library that contains the Frida agent (frida-agent.so).
  • The agent establishes a bi-directional communication channel back to the tool (e.g. the Frida REPL or your custom Python script).
  • The hijacked thread resumes after being restored to its original state, and process execution continues as usual.
​
​
Frida offers three modes of operation:
  1. 1.
    Injected: this is the most common scenario when frida-server is running as a daemon in the iOS or Android device. frida-core is exposed over TCP, listening on localhost:27042 by default. Running in this mode is not possible on devices that are not rooted or jailbroken.
  2. 2.
    Embedded: this is the case when your device is not rooted nor jailbroken (you cannot use ptrace as an unprivileged user), you're responsible for the injection of the frida-gadget library by embedding it into your app, manually or via third-party tools such as Objection.
  3. 3.
    Preloaded: similar to LD_PRELOAD or DYLD_INSERT_LIBRARIES. You can configure the frida-gadget to run autonomously and load a script from the filesystem (e.g. path relative to where the Gadget binary resides).
Independently of the chosen mode, you can make use of the Frida JavaScript APIs to interact with the running process and its memory. Some of the fundamental APIs are:
  • ​Interceptor: When using the Interceptor API, Frida injects a trampoline (aka in-line hooking) at the function prologue which provokes a redirection to our custom code, executes our code, and returns to the original function. Note that while very effective for our purpose, this introduces a considerable overhead (due to the trampoline related jumping and context switching) and cannot be considered transparent as it overwrites the original code and acts similar to a debugger (putting breakpoints) and therefore can be detected in a similar manner, e.g. by applications that periodically checksum their own code.
  • ​Stalker: If your tracing requirements include transparency, performance and high granularity, Stalker should be your API of choice. When tracing code with the Stalker API, Frida leverages just-in-time dynamic recompilation (by using Capstone): when a thread is about to execute its next instructions, Stalker allocates some memory, copies the original code over, and interlaces the copy with your custom code for instrumentation. Finally, it executes the copy (leaving the original code untouched, and therefore avoiding any anti-debugging checks). This approach increases instrumentation performance considerably and allows for very high granularity when tracing (e.g. by tracing exclusively CALL or RET instructions). You can learn more in-depth details in the blog post "Anatomy of a code tracer" by Frida's creator Ole [#vadla]. Some examples of use for Stalker are, for example who-does-it-call or diff-calls.
  • ​Java: When working on Android you can use this API to enumerate loaded classes, enumerate class loaders, create and use specific class instances, enumerate live instances of classes by scanning the heap, etc.
  • ​ObjC: When working on iOS you can use this API to get a mapping of all registered classes, register or use specific class or protocol instances, enumerate live instances of classes by scanning the heap, etc.
Frida also provides a couple of simple tools built on top of the Frida API and available right from your terminal after installing frida-tools via pip. For instance:
  • You can use the Frida CLI (frida) for quick script prototyping and try/error scenarios.
  • ​frida-ps to obtain a list of all apps (or processes) running on the device including their names, identifiers and PIDs.
  • ​frida-ls-devices to list your connected devices running Frida servers or agents.
  • ​frida-trace to quickly trace methods that are part of an iOS app or that are implemented inside an Android native library.
In addition, you'll also find several open source Frida-based tools, such as:
  • ​Passionfruit: an iOS app blackbox assessment tool.
  • ​Fridump: a memory dumping tool for both Android and iOS.
  • ​Objection: a runtime mobile security assessment framework.
  • ​r2frida: a project merging the powerful reverse engineering capabilities of radare2 with the dynamic instrumentation toolkit of Frida.
  • ​jnitrace: a tool for tracing usage of the Android JNI runtime methods by a native library.
We will be using all of these tools throughout the guide.
You can use these tools as-is, tweak them to your needs, or take as excellent examples on how to use the APIs. Having them as an example is very helpful when you write your own hooking scripts or when you build introspection tools to support your reverse engineering workflow.

Frida for Android

Frida supports interaction with the Android Java runtime though the Java API. You'll be able to hook and call both Java and native functions inside the process and its native libraries. Your JavaScript snippets have full access to memory, e.g. to read and/or write any structured data.
Here are some tasks that Frida APIs offers and are relevant or exclusive on Android:
  • Instantiate Java objects and call static and non-static class methods (Java API).
  • Replace Java method implementations (Java API).
  • Enumerate live instances of specific classes by scanning the Java heap (Java API).
  • Scan process memory for occurrences of a string (Memory API).
  • Intercept native function calls to run your own code at function entry and exit (Interceptor API).
Remember that on Android, you can also benefit from the built-in tools provided when installing Frida, that includes the Frida CLI (frida), frida-ps, frida-ls-devices and frida-trace, to name some of them.
Frida is often compared to Xposed, however this comparison is far from fair as both frameworks were designed with different goals in mind. This is important to understand as an app security tester so that you can know which framework to use in which situation:
  • Frida is standalone, all you need is to run the frida-server binary from a known location in your target Android device (see "Installing Frida" below). This means that, in contrast to Xposed, it is not deep installed in the target OS.
  • Reversing an app is an iterative process. As a consequence of the previous point, you obtain a shorter feedback loop when testing as you don't need to (soft) reboot to apply or simply update your hooks. So you might prefer to use Xposed when implementing more permanent hooks.
  • You may inject and update your Frida JavaScript code on the fly at any point during the runtime of your process (similarly to Cycript on iOS). This way you can perform the so-called early instrumentation by letting Frida spawn your app or you may prefer to attach to a running app that you might have brought to a certain state.
  • Frida is able to handle both Java as well as native code (JNI), allowing you to modify both of them. This is unfortunately a limitation of Xposed which lacks of native code support.
Note that Xposed, as of early 2019, does not work on Android 9 (API level 28) yet.
Installing Frida on Android
In order to set up Frida on your Android device:
We assume a rooted device here unless otherwise noted. Download the frida-server binary from the Frida releases page. Make sure that you download the right frida-server binary for the architecture of your Android device or emulator: x86, x86_64, arm or arm64. Make sure that the server version (at least the major version number) matches the version of your local Frida installation. PyPI usually installs the latest version of Frida. If you're unsure which version is installed, you can check with the Frida command line tool:
frida --version
Or you can run the following command to automatically detect Frida version and download the right frida-server binary:
wget https://github.com/frida/frida/releases/download/$(frida --version)/frida-server-$(frida --version)-android-arm.xz
Copy frida-server to the device and run it:
adb push frida-server /data/local/tmp/
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "su -c /data/local/tmp/frida-server &"
Using Frida on Android
With frida-server running, you should now be able to get a list of running processes with the following command (use the -U option to indicate Frida to use a connected USB devices or emulator):
$ frida-ps -U
PID Name
----- --------------------------------------------------------------
276 adbd
956 android.process.media
198 bridgemgrd
30692 com.android.chrome
30774 com.android.chrome:privileged_process0
30747 com.android.chrome:sandboxed
30834 com.android.chrome:sandboxed
3059 com.android.nfc
1526 com.android.phone
17104 com.android.settings
1302 com.android.systemui
(...)
Or restrict the list with the -Uai flag combination to get all apps (-a) currently installed (-i) on the connected USB device (-U):
$ frida-ps -Uai
PID Name Identifier
----- ---------------------------------------- ------------------------------
766 Android System android
30692 Chrome com.android.chrome
3520 Contacts Storage com.android.providers.contacts
- Uncrackable1 sg.vantagepoint.uncrackable1
- drozer Agent com.mwr.dz
This will show the names and identifiers of all apps, if they are currently running it will also show their PIDs. Search for your app in the list and take a note of the PID or its name/identifier. From now on you'll refer to your app by using one of them. A recommendation is to use the identifiers, as the PIDs will change on each run of the app. For example let's take com.android.chrome. You can use this string now on all Frida tools, e.g. on the Frida CLI, on frida-trace or from a Python script.
Tracing Native Libraries with frida-trace
To trace specific (low-level) library calls, you can use the frida-trace command line tool:
frida-trace -U com.android.chrome -i "open"
This generates a little JavaScript in __handlers__/libc.so/open.js, which Frida injects into the process. The script traces all calls to the open function in libc.so. You can modify the generated script according to your needs with Frida JavaScript API.
Unfortunately tracing high-level methods of Java classes is not yet supported (but might be in the future).
Frida CLI and the Java API
Use the Frida CLI tool (frida) to work with Frida interactively. It hooks into a process and gives you a command line interface to Frida's API.
frida -U com.android.chrome
With the -l option, you can also use the Frida CLI to load scripts , e.g., to load myscript.js:
frida -U -l myscript.js com.android.chrome
Frida also provides a Java API, which is especially helpful for dealing with Android apps. It lets you work with Java classes and objects directly. Here is a script to overwrite the onResume function of an Activity class:
Java.perform(function () {
var Activity = Java.use("android.app.Activity");
Activity.onResume.implementation = function () {
console.log("[*] onResume() got called!");
this.onResume();
};
});
The above script calls Java.perform to make sure that your code gets executed in the context of the Java VM. It instantiates a wrapper for the android.app.Activity class via Java.use and overwrites the onResume function. The new onResume function implementation prints a notice to the console and calls the original onResume method by invoking this.onResume every time an activity is resumed in the app.
The JADX decompiler (v1.3.3 and above) can generate Frida snippets through its graphical code browser. To use this feature, open the APK or DEX with jadx-gui, browse to the target method, right click the method name, and select "Copy as frida snippet (f)". For example using the MASTG UnCrackable App for Android Level 1:
​
​
The above steps place the following output in the pasteboard, which you can then paste in a JavaScript file and feed into frida -U -l.
let a = Java.use("sg.vantagepoint.a.a");
a["a"].implementation = function (bArr, bArr2) {
console.log('a is called' + ', ' + 'bArr: ' + bArr + ', ' + 'bArr2: ' + bArr2);
let ret = this.a(bArr, bArr2);
console.log('a ret value is ' + ret);
return ret;
};
The above code hooks the a method within the sg.vantagepoint.a.a class and logs its input parameters and return values.
Frida also lets you search for and work with instantiated objects that are on the heap. The following script searches for instances of android.view.View objects and calls their toString method. The result is printed to the console:
setImmediate(function() {
console.log("[*] Starting script");
Java.perform(function () {
Java.choose("android.view.View", {
"onMatch":function(instance){
console.log("[*] Instance found: " + instance.toString());
},
"onComplete":function() {
console.log("[*] Finished heap search")
}
});
});
});
The output would look like this:
[*] Starting script
[*] Instance found: android.view.View{7ccea78 G.ED..... ......ID 0,0-0,0 #7f0c01fc app:id/action_bar_black_background}
[*] Instance found: android.view.View{2809551 V.ED..... ........ 0,1731-0,1731 #7f0c01ff app:id/menu_anchor_stub}
[*] Instance found: android.view.View{be471b6 G.ED..... ......I. 0,0-0,0 #7f0c01f5 app:id/location_bar_verbose_status_separator}
[*] Instance found: android.view.View{3ae0eb7 V.ED..... ........ 0,0-1080,63 #102002f android:id/statusBarBackground}
[*] Finished heap search
You can also use Java's reflection capabilities. To list the public methods of the android.view.View class, you could create a wrapper for this class in Frida and call getMethods from the wrapper's class property:
Java.perform(function () {
var view = Java.use("android.view.View");
var methods = view.class.getMethods();
for(var i = 0; i < methods.length; i++) {
console.log(methods[i].toString());
}
});
This will print a very long list of methods to the terminal:
public boolean android.view.View.canResolveLayoutDirection()
public boolean android.view.View.canResolveTextAlignment()
public boolean android.view.View.canResolveTextDirection()
public boolean android.view.View.canScrollHorizontally(int)
public boolean android.view.View.canScrollVertically(int)
public final void android.view.View.cancelDragAndDrop()
public void android.view.View.cancelLongPress()
public final void android.view.View.cancelPendingInputEvents()
...

Frida for iOS

Frida supports interaction with the Objective-C runtime through the ObjC API. You'll be able to hook and call both Objective-C and native functions inside the process and its native libraries. Your JavaScript snippets have full access to memory, e.g. to read and/or write any structured data.
Here are some tasks that Frida APIs offers and are relevant or exclusive on iOS:
  • Instantiate Objective-C objects and call static and non-static class methods (ObjC API).
  • Trace Objective-C method calls and/or replace their implementations (Interceptor API).
  • Enumerate live instances of specific classes by scanning the heap (ObjC API).
  • Scan process memory for occurrences of a string (Memory API).
  • Intercept native function calls to run your own code at function entry and exit (Interceptor API).
Remember that on iOS, you can also benefit from the built-in tools provided when installing Frida, which include the Frida CLI (frida), frida-ps, frida-ls-devices and frida-trace, to name a few.
There's a frida-trace feature exclusive on iOS worth highlighting: tracing Objective-C APIs using the -m flag and wildcards. For example, tracing all methods including "HTTP" in their name and belonging to any class whose name starts with "NSURL" is as easy as running:
frida-trace -U YourApp -m "*[NSURL* *HTTP*]"
For a quick start you can go through the iOS examples.
Installing Frida on iOS
To connect Frida to an iOS app, you need a way to inject the Frida runtime into that app. This is easy to do on a jailbroken device: just install frida-server through Cydia. Once it has been installed, the Frida server will automatically run with root privileges, allowing you to easily inject code into any process.
Start Cydia and add Frida's repository by navigating to Manage -> Sources -> Edit -> Add and entering https://build.frida.re. You should then be able to find and install the Frida package.
Using Frida on iOS
Connect your device via USB and make sure that Frida works by running the frida-ps command and the flag '-U'. This should return the list of processes running on the device:
$ frida-ps -U
PID Name
--- ----------------
963 Mail
952 Safari
416 BTServer
422 BlueTool
791 CalendarWidget
451 CloudKeychainPro
239 CommCenter
764 ContactsCoreSpot
(...)

Frida Bindings

In order to extend the scripting experience, Frida offers bindings to programming languages such as Python, C, NodeJS, and Swift.
Taking Python as an example, the first thing to note is that no further installation steps are required. Start your Python script with import frida and you're ready to go. See the following script that simply runs the previous JavaScript snippet:
# frida_python.py
import frida
​
session = frida.get_usb_device().attach('com.android.chrome')
​
source = """
Java.perform(function () {
var view = Java.use("android.view.View");
var methods = view.class.getMethods();
for(var i = 0; i < methods.length; i++) {
console.log(methods[i].toString());
}
});
"""
​
script = session.create_script(source)
script.load()
​
session.detach()
In this case, running the Python script (python3 frida_python.py) has the same result as the previous example: it will print all methods of the android.view.View class to the terminal. However, you might want to work with that data from Python. Using send instead of console.log will send data in JSON format from JavaScript to Python. Please read the comments in the example below:
# python3 frida_python_send.py
import frida
​
session = frida.get_usb_device().attach('com.android.chrome')
​
# 1. we want to store method names inside a list
android_view_methods = []
​
source = """
Java.perform(function () {
var view = Java.use("android.view.View");
var methods = view.class.getMethods();
for(var i = 0; i < methods.length; i++) {
send(methods[i].toString());
}
});
"""
​
script = session.create_script(source)
​
# 2. this is a callback function, only method names containing "Text" will be appended to the list
def on_message(message, data):
if "Text" in message['payload']:
android_view_methods.append(message['payload'])
​
# 3. we tell the script to run our callback each time a message is received
script.on('message', on_message)
​
script.load()
​
# 4. we do something with the collected data, in this case we just print it
for method in android_view_methods:
print(method)
​
session.detach()
This effectively filters the methods and prints only the ones containing the string "Text":
$ python3 frida_python_send.py
public boolean android.view.View.canResolveTextAlignment()
public boolean android.view.View.canResolveTextDirection()
public void android.view.View.setTextAlignment(int)
public void android.view.View.setTextDirection(int)
public void android.view.View.setTooltipText(java.lang.CharSequence)
...
In the end, it is up to you to decide where would you like to work with the data. Sometimes it will be more convenient to do it from JavaScript and in other cases Python will be the best choice. Of course you can also send messages from Python to JavaScript by using script.post. Refer to the Frida docs for more information about sending and receiving messages.

Frida CodeShare

​Frida CodeShare is a repository containing a collection of ready-to-run Frida scripts which can enormously help when performing concrete tasks both on Android as on iOS as well as also serve as inspiration to build your own scripts. Two representative examples are:
Using them is as simple as including the --codeshare <handler> flag and a handler when using the Frida CLI. For example, to use "ObjC method observer", enter the following:
frida --codeshare mrmacete/objc-method-observer -f YOUR_BINARY

Ghidra

Ghidra is an open source software reverse engineering (SRE) suite of tools developed by the United State of America's National Security Agency's (NSA) Research Directorate. Ghidra is a versatile tool which comprises of a disassembler, decompiler and a built-in scripting engine for advanced usage. Please refer to the installation guide on how to install it and also look at the cheat sheet for a first overview of available commands and shortcuts. In this section, we will have walk-through on how to create a project, view disassembly and decompiled code for a binary.
Start Ghidra using ghidraRun (*nix) or ghidraRun.bat (Windows), depending on the platform you are on. Once Ghidra is fired up, create a new project by specifying the project directory. You will be greeted by a window as shown below:
​
​
In your new Active Project you can import an app binary by going to File -> Import File and choosing the desired file.
​
​
If the file can be properly processed, Ghidra will show meta-information about the binary before starting the analysis.
​
​
To get the disassembled code for the binary file chosen above, double click the imported file from the Active Project window. Click yes and analyze for auto-analysis on the subsequent windows. Auto-analysis will take some time depending on the size of the binary, the progress can be tracked in the bottom right corner of the code browser window. Once auto-analysis is completed you can start exploring the binary.
​
​
The most important windows to explore a binary in Ghidra are the Listing (Disassembly) window, the Symbol Tree window and the Decompiler window, which shows the decompiled version of the function selected for disassembly. The Display Function Graph option shows control flow graph of the selected function.
​
​
There are many other functionalities available in Ghidra and most of them can be explored by opening the Window menu. For example, if you want to examine the strings present in the binary, open the Defined Strings option. We will discuss other advanced functionalities while analyzing various binaries for Android and iOS platforms in the coming chapters.
​
​

Hopper (Commercial Tool)

A reverse engineering tool for macOS and Linux used to disassemble, decompile and debug 32/64bits Intel Mac, Linux, Windows and iOS executables - https://www.hopperapp.com/​

IDA Pro (Commercial Tool)

A Windows, Linux or macOS hosted multi-processor disassembler and debugger - https://www.hex-rays.com/products/ida/index.shtml​

LIEF

The purpose of LIEF is to provide a cross platform library to parse, modify and abstract ELF, PE and MachO formats. With it you can, for instance, inject a certain library as a dependency of a native library, which an application already loads by default. - https://lief.quarkslab.com/​

MobSF

​MobSF (Mobile Security Framework) is an automated, all-in-one mobile application pentesting framework capable of performing static and dynamic analysis. The easiest way of getting MobSF started is via Docker.
docker pull opensecurity/mobile-security-framework-mobsf
docker run -it -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest
Or install and start it locally on your host computer by running:
# Setup
git clone https://github.com/MobSF/Mobile-Security-Framework-MobSF.git
cd Mobile-Security-Framework-MobSF
./setup.sh # For Linux and Mac
setup.bat # For Windows
​
# Installation process
./run.sh # For Linux and Mac
run.bat # For Windows
Once you have MobSF up and running you can open it in your browser by navigating to http://127.0.0.1:8000. Simply drag the APK you want to analyze into the upload area and MobSF will start its job.

MobSF for Android

After MobSF is done with its analysis, you will receive a one-page overview of all the tests that were executed. The page is split up into multiple sections giving some first hints on the attack surface of the application.
​
​
The following is displayed:
  • Basic information about the app and its binary file.
  • Some options to:
    • View the AndroidManifest.xml file.
    • View the IPC components of the app.
  • Signer certificate.
  • App permissions.
  • A security analysis showing known defects e.g. if the app backups are enabled.
  • List of libraries used by the app binary and list of all files inside the unzipped APK.
  • Malware analysis that checks for malicious URLs.
Refer to MobSF documentation for more details.

MobSF for iOS

By running MobSF locally on a macOS host you'll benefit from a slightly better class-dump output.
Once you have MobSF up and running you can open it in your browser by navigating to http://127.0.0.1:8000. Simply drag the IPA you want to analyze into the upload area and MobSF will start its job.
After MobSF is done with its analysis, you will receive a one-page overview of all the tests that were executed. The page is split up into multiple sections giving some first hints on the attack surface of the application.
​
​
The following is displayed:
  • Basic information about the app and its binary file.
  • Some options to:
    • View the Info.plist file.
    • View the strings contained in the app binary.
    • Download a class-dump, if the app was written in Objective-C; if it is written in Swift no class-dump can be created.
  • List all Purpose Strings extracted from the Info.plist which give some hints on the app's permissions.
  • Exceptions in the App Transport Security (ATS) configuration will be listed.
  • A brief binary analysis showing if free binary security features are activated or e.g. if the binary makes use of banned APIs.
  • List of libraries used by the app binary and list of all files inside the unzipped IPA.
In contrast to the Android use case, MobSF does not offer any dynamic analysis features for iOS apps.
Refer to MobSF documentation for more details.

nm

nm is a tool that displays the name list (symbol table) of the given binary. You can find more information for the Android (GNU) version and for iOS.

Objection

​Objection is a "runtime mobile exploration toolkit, powered by Frida". Its main goal is to allow security testing on non-rooted devices through an intuitive interface.
Objection achieves this goal by providing you with the tools to easily inject the Frida gadget into an application by repackaging it. This way, you can deploy the repackaged app to the non-rooted/non-jailbroken device by sideloading it. Objection also provides a REPL that allows you to interact with the application, giving you the ability to perform any action that the application can perform.
Objection can be installed through pip as described on Objection's Wiki.
pip3 install objection

Objection for Android

Objection offers several features specific to Android. You can find the full list of features on the project's page, but here are a few interesting ones:
  • Repackage applications to include the Frida gadget
  • Disable SSL pinning for popular methods
  • Access application storage to download or upload files
  • Execute custom Frida scripts
  • List the Activities, Services and Broadcast receivers
  • Start Activities
If you have a rooted device with frida-server installed, Objection can connect directly to the running Frida server to provide all its functionality without needing to repackage the application. However, it is not always possible to root an Android device or the app may contain advanced RASP controls for root detection, so injecting a frida-gadget may be the easiest way to bypass those controls.
The ability to perform advanced dynamic analysis on non-rooted devices is one of the features that makes Objection incredibly useful. After following the repackaging process you will be able to run all the aforementioned commands which make it very easy to quickly analyze an application, or bypass basic security controls.
Using Objection on Android
Starting up Objection depends on whether you've patched the APK or whether you are using a rooted device running Frida-server. For running a patched APK, objection will automatically find any attached devices and search for a listening Frida gadget. However, when using frida-server, you need to explicitly tell frida-server which application you want to analyze.
# Connecting to a patched APK
objection explore
​
# Find the correct name using frida-ps
$ frida-ps -Ua | grep -i telegram
30268 Telegram org.telegram.messenger
​
# Connecting to the Telegram app through Frida-server
$ objection --gadget="org.telegram.messenger" explore
Once you are in the Objection REPL, you can execute any of the available commands. Below is an overview of some of the most useful ones:
# Show the different storage locations belonging to the app
$ env
​
# Disable popular ssl pinning methods
$ android sslpinning disable
​
# List items in the keystore
$ android keystore list
​
# Try to circumvent root detection
$ android root disable
​
More information on using the Objection REPL can be found on the Objection Wiki​

Objection for iOS

Objection offers several features specific to iOS. You can find the full list of features on the project's page, but here are a few interesting ones:
  • Repackage applications to include the Frida gadget
  • Disable SSL pinning for popular methods
  • Access application storage to download or upload files
  • Execute custom Frida scripts
  • Dump the Keychain
  • Read plist files
All these tasks and more can be easily done by using the commands in objection's REPL. For example, you can obtain the classes used in an app, functions of classes or information about the bundles of an app by running:
OWASP.iGoat-Swift on (iPhone: 12.0) [usb] # ios hooking list classes
OWASP.iGoat-Swift on (iPhone: 12.0) [usb] # ios hooking list class_methods <ClassName>
OWASP.iGoat-Swift on (iPhone: 12.0) [usb] # ios bundles list_bundles
If you have a jailbroken device with frida-server installed, Objection can connect directly to the running Frida server to provide all its functionality without needing to repackage the application. However, it is not always possible to jailbreak the latest version of iOS, or you may have an application with advanced jailbreak detection mechanisms.
The ability to perform advanced dynamic analysis on non-jailbroken devices is one of the features that makes Objection incredibly useful. After following the repackaging process you will be able to run all the aforementioned commands which make it very easy to quickly analyze an application, or get around basic security controls.
Using Objection on iOS
Starting up Objection depends on whether you've patched the IPA or whether you are using a jailbroken device running Frida-server. For running a patched IPA, objection will automatically find any attached devices and search for a listening Frida gadget. However, when using frida-server, you need to explicitly tell frida-server which application you want to analyze.
# Connecting to a patched IPA
$ objection explore
​
# Using frida-ps to get the correct application name
$ frida-ps -Ua | grep -i Telegram
983 Telegram
​
# Connecting to the Telegram app through Frida-server
$ objection --gadget="Telegram" explore
Once you are in the Objection REPL, you can execute any of the available commands. Below is an overview of some of the most useful ones:
# Show the different storage locations belonging to the app
$ env
​
# Disable popular ssl pinning methods
$ ios sslpinning disable
​
# Dump the Keychain
$ ios keychain dump
​
# Dump the Keychain, including access modifiers. The result will be written to the host in myfile.json
$ ios keychain dump --json <myfile.json>
​
# Show the content of a plist file
$ ios plist cat <myfile.plist>
​
More information on using the Objection REPL can be found on the Objection Wiki​

r2frida

​r2frida is a project that allows radare2 to connect to Frida, effectively merging the powerful reverse engineering capabilities of radare2 with the dynamic instrumentation toolkit of Frida. r2frida can be used in both on Android and iOS, allowing you to:
  • Attach radare2 to any local process or remote frida-server via USB or TCP.
  • Read/Write memory from the target process.
  • Load Frida information such as maps, symbols, imports, classes and methods into radare2.
  • Call r2 commands from Frida as it exposes the r2pipe interface into the Frida Javascript API.
With frida-server running, you should now be able to attach to it using the pid, spawn path, host and port, or device-id. For example, to attach to PID 1234:
r2 frida://1234
For more examples on how to connect to frida-server, see the usage section in the r2frida's README page.
The following examples were executed using an Android app but also apply to iOS apps.
Once in the r2frida session, all commands start with \ or =!. For example, in radare2 you'd run i to display the binary information, but in r2frida you'd use \i.
See all options with r2 frida://?.
[0x00000000]> \i
arch x86
bits 64
os linux
pid 2218
uid 1000
objc false
runtime V8
java false
cylang false
pageSize 4096
pointerSize 8
codeSigningPolicy optional
isDebuggerAttached false
To search in memory for a specific keyword, you may use the search command \/:
[0x00000000]> \/ unacceptable
Searching 12 bytes: 75 6e 61 63 63 65 70 74 61 62 6c 65
Searching 12 bytes in [0x0000561f05ebf000-0x0000561f05eca000]
...
Searching 12 bytes in [0xffffffffff600000-0xffffffffff601000]
hits: 23
0x561f072d89ee hit12_0 unacceptable policyunsupported md algorithmvar bad valuec
0x561f0732a91a hit12_1 unacceptableSearching 12 bytes: 75 6e 61 63 63 65 70 74 61
To output the search results in JSON format, we simply add j to our previous search command (just as we do in the r2 shell). This can be used in most of the commands:
[0x00000000]> \/j unacceptable
Searching 12 bytes: 75 6e 61 63 63 65 70 74 61 62 6c 65
Searching 12 bytes in [0x0000561f05ebf000-0x0000561f05eca000]
...
Searching 12 bytes in [0xffffffffff600000-0xffffffffff601000]
hits: 23
{"address":"0x561f072c4223","size":12,"flag":"hit14_1","content":"unacceptable \
policyunsupported md algorithmvar bad valuec0"},{"address":"0x561f072c4275", \
"size":12,"flag":"hit14_2","content":"unacceptableSearching 12 bytes: 75 6e 61 \
63 63 65 70 74 61"},{"address":"0x561f072c42c8","size":12,"flag":"hit14_3", \
"content":"unacceptableSearching 12 bytes: 75 6e 61 63 63 65 70 74 61 "},
...
To list the loaded libraries use the command \il and filter the results using the internal grep from radare2 with the command ~. For example, the following command will list the loaded libraries matching the keywords keystore, ssl and crypto:
[0x00000000]> \il~keystore,ssl,crypto
0x00007f3357b8e000 libssl.so.1.1
0x00007f3357716000 libcrypto.so.1.1
Similarly, to list the exports and filter the results by a specific keyword:
[0x00000000]> \iE libssl.so.1.1~CIPHER
0x7f3357bb7ef0 f SSL_CIPHER_get_bits
0x7f3357bb8260 f SSL_CIPHER_find
0x7f3357bb82c0 f SSL_CIPHER_get_digest_nid
0x7f3357bb8380 f SSL_CIPHER_is_aead
0x7f3357bb8270 f SSL_CIPHER_get_cipher_nid
0x7f3357bb7ed0 f SSL_CIPHER_get_name
0x7f3357bb8340 f SSL_CIPHER_get_auth_nid
0x7f3357bb7930 f SSL_CIPHER_description
0x7f3357bb8300 f SSL_CIPHER_get_kx_nid
0x7f3357bb7ea0 f SSL_CIPHER_get_version
0x7f3357bb7f10 f SSL_CIPHER_get_id
To list or set a breakpoint use the command db. This is useful when analyzing/modifying memory:
[0x00000000]> \db
Finally, remember that you can also run Frida JavaScript code with \. plus the name of the script:
[0x00000000]> \. agent.js
You can find more examples on how to use r2frida on their Wiki project.

radare2

radare2 (Android)

​radare2 (r2) is a popular open source reverse engineering framework for disassembling, debugging, patching and analyzing binaries that is scriptable and supports many architectures and file formats including Android and iOS apps. For Android, Dalvik DEX (odex, multidex), ELF (executables, .so, ART) and Java (JNI and Java classes) are supported. It also contains several useful scripts that can help you during mobile application analysis as it offers low level disassembling and safe static analysis that comes in handy when traditional tools fail.
radare2 implements a rich command line interface (CLI) where you can perform the mentioned tasks. However, if you're not really comfortable using the CLI for reverse engineering you may want to consider using the Web UI (via the -H flag) or the even more convenient Qt and C++ GUI version called iaito. Do keep in mind that the CLI, and more concretely its Visual Mode and its scripting capabilities (r2pipe), are the core of radare2's power and it's definitely worth learning how to use it.
Installing radare2
Please refer to radare2's official installation instructions. We highly recommend to always install radare2 from the GitHub version instead of via common package managers such as APT. Radare2 is in very active development, which means that third party repositories are often outdated.
Using radare2
The radare2 framework comprises a set of small utilities that can be used from the r2 shell or independently as CLI tools. These utilities include rabin2, rasm2, rahash2, radiff2, rafind2, ragg2, rarun2, rax2, and of course r2, which is the main one.
For example, you can use rafind2 to read strings directly from an encoded Android Manifest (AndroidManifest.xml):
# Permissions
$ rafind2 -ZS permission AndroidManifest.xml
# Activities
$ rafind2 -ZS activity AndroidManifest.xml
# Content providers
$ rafind2 -ZS provider AndroidManifest.xml
# Services
$ rafind2 -ZS service AndroidManifest.xml
# Receivers
$ rafind2 -ZS receiver AndroidManifest.xml
Or use rabin2 to get information about a binary file:
$ rabin2 -I UnCrackable-Level1/classes.dex
arch dalvik
baddr 0x0
binsz 5528
bintype class
bits 32
canary false
retguard false
class 035
crypto false
endian little
havecode true
laddr 0x0
lang dalvik
linenum false
lsyms false
machine Dalvik VM
maxopsz 16
minopsz 1
nx false
os linux
pcalign 0
pic false
relocs false
sanitiz false
static true
stripped false
subsys java
va true
sha1 12-5508c b7fafe72cb521450c4470043caa332da61d1bec7
adler32 12-5528c 00000000
Type rabin2 -h to see all options:
$ rabin2 -h
Usage: rabin2 [-AcdeEghHiIjlLMqrRsSUvVxzZ] [-@ at] [-a arch] [-b bits] [-B addr]
[-C F:C:D] [-f str] [-m addr] [-n str] [-N m:M] [-P[-P] pdb]
[-o str] [-O str] [-k query] [-D lang symname] file
-@ [addr] show section, symbol or import at addr
-A list sub-binaries and their arch-bits pairs
-a [arch] set arch (x86, arm, .. or <arch>_<bits>)
-b [bits] set bits (32, 64 ...)
-B [addr] override base address (pie bins)
-c list classes
-cc list classes in header format
-H header fields
-i imports (symbols imported from libraries)
-I binary info
-j output in json
...
Use the main r2 utility to access the r2 shell. You can load DEX binaries just like any other binary:
r2 classes.dex
Enter r2 -h to see all available options. A very commonly used flag is -A, which triggers an analysis after loading the target binary. However, this should be used sparingly and with small binaries as it is very time and resource consuming. You can learn more about this in the chapter "Tampering and Reverse Engineering on Android".
Once in the r2 shell, you can also access functions offered by the other radare2 utilities. For example, running i will print the information of the binary, exactly as rabin2 -I does.
To print all the strings use rabin2 -Z or the command iz (or the less verbose izq) from the r2 shell.
[0x000009c8]> izq
0xc50 39 39 /dev/com.koushikdutta.superuser.daemon/
0xc79 25 25 /system/app/Superuser.apk
...
0xd23 44 44 5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=
0xd51 32 32 8d127684cbc37c17616d806cf50473cc
0xd76 6 6 <init>
0xd83 10 10 AES error:
0xd8f 20 20 AES/ECB/PKCS7Padding
0xda5 18 18 App is debuggable!
0xdc0 9 9 CodeCheck
0x11ac 7 7 Nope...
0x11bf 14 14 Root detected!
Most of the time you can append special options to your commands such as q to make the command less verbose (quiet) or j to give the output in JSON format (use ~{} to prettify the JSON string).
[0x000009c8]> izj~{}
[
{
"vaddr": 3152,
"paddr": 3152,
"ordinal": 1,
"size": 39,
"length": 39,
"section": "file",
"type": "ascii",
"string": "L2Rldi9jb20ua291c2hpa2R1dHRhLnN1cGVydXNlci5kYWVtb24v"
},
{
"vaddr": 3193,
"paddr": 3193,
"ordinal": 2,
"size": 25,
"length": 25,
"section": "file",
"type": "ascii",
"string": "L3N5c3RlbS9hcHAvU3VwZXJ1c2VyLmFwaw=="
},
You can print the class names and their methods with the r2 command ic (information classes).
[0x000009c8]> ic
...