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 MSTG 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 MSTG 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 MSTG 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:
1
$ pip install angr
Copied!
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:
1
$ pip install frida-tools
Copied!
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:
1
$ frida --version
Copied!
Or you can run the following command to automatically detect Frida version and download the right frida-server binary:
1
$ wget https://github.com/frida/frida/releases/download/$(frida --version)/frida-server-$(frida --version)-android-arm.xz
Copied!
Copy frida-server to the device and run it:
1
$ adb push frida-server /data/local/tmp/
2
$ adb shell "chmod 755 /data/local/tmp/frida-server"
3
$ adb shell "su -c /data/local/tmp/frida-server &"
Copied!
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):
1
$ frida-ps -U
2
PID Name
3
----- --------------------------------------------------------------
4
276 adbd
5
956 android.process.media
6
198 bridgemgrd
7
30692 com.android.chrome
8
30774 com.android.chrome:privileged_process0
9
30747 com.android.chrome:sandboxed
10
30834 com.android.chrome:sandboxed
11
3059 com.android.nfc
12
1526 com.android.phone
13
17104 com.android.settings
14
1302 com.android.systemui
15
(...)
Copied!
Or restrict the list with the -Uai flag combination to get all apps (-a) currently installed (-i) on the connected USB device (-U):
1
$ frida-ps -Uai
2
PID Name Identifier
3
----- ---------------------------------------- ------------------------------
4
766 Android System android
5
30692 Chrome com.android.chrome
6
3520 Contacts Storage com.android.providers.contacts
7
- Uncrackable1 sg.vantagepoint.uncrackable1
8
- drozer Agent com.mwr.dz
Copied!
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:
1
$ frida-trace -U com.android.chrome -i "open"
Copied!
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.
1
$ frida -U com.android.chrome
Copied!
With the -l option, you can also use the Frida CLI to load scripts , e.g., to load myscript.js:
1
$ frida -U -l myscript.js com.android.chrome
Copied!
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:
1
Java.perform(function () {
2
var Activity = Java.use("android.app.Activity");
3
Activity.onResume.implementation = function () {
4
console.log("[*] onResume() got called!");
5
this.onResume();
6
};
7
});
Copied!
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.
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:
1
setImmediate(function() {
2
console.log("[*] Starting script");
3
Java.perform(function () {
4
Java.choose("android.view.View", {
5
"onMatch":function(instance){
6
console.log("[*] Instance found: " + instance.toString());
7
},
8
"onComplete":function() {
9
console.log("[*] Finished heap search")
10
}
11
});
12
});
13
});
Copied!
The output would look like this:
1
[*] Starting script
2
[*] Instance found: android.view.View{7ccea78 G.ED..... ......ID 0,0-0,0 #7f0c01fc app:id/action_bar_black_background}
3
[*] Instance found: android.view.View{2809551 V.ED..... ........ 0,1731-0,1731 #7f0c01ff app:id/menu_anchor_stub}
4
[*] Instance found: android.view.View{be471b6 G.ED..... ......I. 0,0-0,0 #7f0c01f5 app:id/location_bar_verbose_status_separator}
5
[*] Instance found: android.view.View{3ae0eb7 V.ED..... ........ 0,0-1080,63 #102002f android:id/statusBarBackground}
6
[*] Finished heap search
Copied!
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:
1
Java.perform(function () {
2
var view = Java.use("android.view.View");
3
var methods = view.class.getMethods();
4
for(var i = 0; i < methods.length; i++) {
5
console.log(methods[i].toString());
6
}
7
});
Copied!
This will print a very long list of methods to the terminal:
1
public boolean android.view.View.canResolveLayoutDirection()
2
public boolean android.view.View.canResolveTextAlignment()
3
public boolean android.view.View.canResolveTextDirection()
4
public boolean android.view.View.canScrollHorizontally(int)
5
public boolean android.view.View.canScrollVertically(int)
6
public final void android.view.View.cancelDragAndDrop()
7
public void android.view.View.cancelLongPress()
8
public final void android.view.View.cancelPendingInputEvents()
9
...
Copied!

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:
1
$ frida-trace -U YourApp -m "*[NSURL* *HTTP*]"
Copied!
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:
1
$ frida-ps -U
2
PID Name
3
--- ----------------
4
963 Mail
5
952 Safari
6
416 BTServer
7
422 BlueTool
8
791 CalendarWidget
9
451 CloudKeychainPro
10
239 CommCenter
11
764 ContactsCoreSpot
12
(...)
Copied!

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:
1
# frida_python.py
2
import frida
3
4
session = frida.get_usb_device().attach('com.android.chrome')
5
6
source = """
7
Java.perform(function () {
8
var view = Java.use("android.view.View");
9
var methods = view.class.getMethods();
10
for(var i = 0; i < methods.length; i++) {
11
console.log(methods[i].toString());
12
}
13
});
14
"""
15
16
script = session.create_script(source)
17
script.load()
18
19
session.detach()
Copied!
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:
1
# python3 frida_python_send.py
2
import frida
3
4
session = frida.get_usb_device().attach('com.android.chrome')
5
6
# 1. we want to store method names inside a list
7
android_view_methods = []
8
9
source = """
10
Java.perform(function () {
11
var view = Java.use("android.view.View");
12
var methods = view.class.getMethods();
13
for(var i = 0; i < methods.length; i++) {
14
send(methods[i].toString());
15
}
16
});
17
"""
18
19
script = session.create_script(source)
20
21
# 2. this is a callback function, only method names containing "Text" will be appended to the list
22
def on_message(message, data):
23
if "Text" in message['payload']:
24
android_view_methods.append(message['payload'])
25
26
# 3. we tell the script to run our callback each time a message is received
27
script.on('message', on_message)
28
29
script.load()
30
31
# 4. we do something with the collected data, in this case we just print it
32
for method in android_view_methods:
33
print(method)
34
35
session.detach()
Copied!
This effectively filters the methods and prints only the ones containing the string "Text":
1
$ python3 frida_python_send.py
2
public boolean android.view.View.canResolveTextAlignment()
3
public boolean android.view.View.canResolveTextDirection()
4
public void android.view.View.setTextAlignment(int)
5
public void android.view.View.setTextDirection(int)
6
public void android.view.View.setTooltipText(java.lang.CharSequence)
7
...
Copied!
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:
1
$ frida --codeshare mrmacete/objc-method-observer -f YOUR_BINARY
Copied!

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.
1
$ docker pull opensecurity/mobile-security-framework-mobsf
2
$ docker run -it -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest
Copied!
Or install and start it locally on your host computer by running:
1
# Setup
2
git clone https://github.com/MobSF/Mobile-Security-Framework-MobSF.git
3
cd Mobile-Security-Framework-MobSF
4
./setup.sh # For Linux and Mac
5
setup.bat # For Windows
6
7
# Installation process
8
./run.sh # For Linux and Mac
9
run.bat # For Windows
Copied!
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.
1
$ pip3 install objection
Copied!

Objection for Android

Objection offers several features specific to Android. A full list of the features of Objection can be found on the project's homepage, 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
The ability to perform advanced dynamic analysis on non-rooted devices is one of the features that makes Objection incredibly useful. An application may contain advanced RASP controls which detect your rooting method and injecting a frida-gadget may be the easiest way to bypass those controls. Furthermore, the included Frida scripts make it very easy to quickly analyze an application, or get around basic security controls.
Finally, in case you do have access to a rooted device, Objection can connect directly to the running Frida server to provide all its functionality without needing to repackage the application. However, if you want to test on a non-rooted device, you will first need to include the Frida gadget in the application. The Objection Wiki describes the needed steps in detail, but after making the right preparations, you'll be able to patch an APK by calling the objection command:
1
$ objection patchapk --source app-release.apk
Copied!
The patched application then needs to be installed using adb, as explained in "Basic Testing Operations - Installing Apps".
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.
1
# Connecting to a patched APK
2
objection explore
3
4
# Find the correct name using frida-ps
5
$ frida-ps -Ua | grep -i telegram
6
30268 Telegram org.telegram.messenger
7
8
# Connecting to the Telegram app through Frida-server
9
$ objection --gadget="org.telegram.messenger" explore
Copied!
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:
1
# Show the different storage locations belonging to the app
2
$ env
3
4
# Disable popular ssl pinning methods
5
$ android sslpinning disable
6
7
# List items in the keystore
8
$ android keystore list
9
10
# Try to circumvent root detection
11
$ android root disable
Copied!
More information on using the Objection REPL can be found on the Objection Wiki

Objection for iOS

Objection offers several features specific to iOS. A full list of the features of Objection can be found on the project's homepage, 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:
1
OWASP.iGoat-Swift on (iPhone: 12.0) [usb] # ios hooking list classes
2
OWASP.iGoat-Swift on (iPhone: 12.0) [usb] # ios hooking list class_methods <ClassName>
3
OWASP.iGoat-Swift on (iPhone: 12.0) [usb] # ios bundles list_bundles
Copied!
The ability to perform advanced dynamic analysis on non-jailbroken devices is one of the features that makes Objection incredibly useful. It is not always possible to jailbreak the latest version of iOS, or you may have an application with advanced jailbreak detection mechanisms. Furthermore, the included Frida scripts make it very easy to quickly analyze an application, or get around basic security controls.
Finally, in case you do have access to a jailbroken device, Objection can connect directly to the running Frida server to provide all its functionality without needing to repackage the application. However, if you want to test on a non-jailbroken device, you will first need to include the Frida gadget in the application. The Objection Wiki describes the needed steps in detail, but after making the right preparations, you'll be able to patch an IPA by calling the objection command:
1
$ objection patchipa --source my-app.ipa --codesign-signature 0C2E8200Dxxxx
Copied!
Finally, the application needs to be sideloaded and run with debugging communication enabled. Detailed steps can be found on the Objection Wiki, but for macOS users it can easily be done by using ios-deploy:
1
$ ios-deploy --bundle Payload/my-app.app -W -d
Copied!
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.
1
# Connecting to a patched IPA
2
$ objection explore
3
4
# Using frida-ps to get the correct application name
5
$ frida-ps -Ua | grep -i Telegram
6
983 Telegram
7
8
# Connecting to the Telegram app through Frida-server
9
$ objection --gadget="Telegram" explore
Copied!
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:
1
# Show the different storage locations belonging to the app
2
$ env
3
4
# Disable popular ssl pinning methods
5
$ ios sslpinning disable
6
7
# Dump the Keychain
8
$ ios keychain dump
9
10
# Dump the Keychain, including access modifiers. The result will be written to the host in myfile.json
11
$ ios keychain dump --json <myfile.json>
12
13
# Show the content of a plist file
14
$ ios plist cat <myfile.plist>
Copied!
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:
1
$ r2 frida://1234
Copied!
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://?.
1
[0x00000000]> \i
2
arch x86
3
bits 64
4
os linux
5
pid 2218
6
uid 1000
7
objc false
8
runtime V8
9
java false
10
cylang false
11
pageSize 4096
12
pointerSize 8
13
codeSigningPolicy optional
14
isDebuggerAttached false
Copied!
To search in memory for a specific keyword, you may use the search command \/:
1
[0x00000000]> \/ unacceptable
2
Searching 12 bytes: 75 6e 61 63 63 65 70 74 61 62 6c 65
3
Searching 12 bytes in [0x0000561f05ebf000-0x0000561f05eca000]
4
...
5
Searching 12 bytes in [0xffffffffff600000-0xffffffffff601000]
6
hits: 23
7
0x561f072d89ee hit12_0 unacceptable policyunsupported md algorithmvar bad valuec
8
0x561f0732a91a hit12_1 unacceptableSearching 12 bytes: 75 6e 61 63 63 65 70 74 61
Copied!
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:
1
[0x00000000]> \/j unacceptable
2
Searching 12 bytes: 75 6e 61 63 63 65 70 74 61 62 6c 65
3
Searching 12 bytes in [0x0000561f05ebf000-0x0000561f05eca000]
4
...
5
Searching 12 bytes in [0xffffffffff600000-0xffffffffff601000]
6
hits: 23
7
{"address":"0x561f072c4223","size":12,"flag":"hit14_1","content":"unacceptable \
8
policyunsupported md algorithmvar bad valuec0"},{"address":"0x561f072c4275", \
9
"size":12,"flag":"hit14_2","content":"unacceptableSearching 12 bytes: 75 6e 61 \
10
63 63 65 70 74 61"},{"address":"0x561f072c42c8","size":12,"flag":"hit14_3", \
11
"content":"unacceptableSearching 12 bytes: 75 6e 61 63 63 65 70 74 61 "},
12
...
Copied!
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:
1
[0x00000000]> \il~keystore,ssl,crypto
2
0x00007f3357b8e000 libssl.so.1.1
3
0x00007f3357716000 libcrypto.so.1.1
Copied!
Similarly, to list the exports and filter the results by a specific keyword:
1
[0x00000000]> \iE libssl.so.1.1~CIPHER
2
0x7f3357bb7ef0 f SSL_CIPHER_get_bits
3
0x7f3357bb8260 f SSL_CIPHER_find
4
0x7f3357bb82c0 f SSL_CIPHER_get_digest_nid
5
0x7f3357bb8380 f SSL_CIPHER_is_aead
6
0x7f3357bb8270 f SSL_CIPHER_get_cipher_nid
7
0x7f3357bb7ed0 f SSL_CIPHER_get_name
8
0x7f3357bb8340 f SSL_CIPHER_get_auth_nid
9
0x7f3357bb7930 f SSL_CIPHER_description
10
0x7f3357bb8300 f SSL_CIPHER_get_kx_nid
11
0x7f3357bb7ea0 f SSL_CIPHER_get_version
12
0x7f3357bb7f10 f SSL_CIPHER_get_id
Copied!
To list or set a breakpoint use the command db. This is useful when analyzing/modifying memory:
1
[0x00000000]> \db
Copied!
Finally, remember that you can also run Frida JavaScript code with \. plus the name of the script:
1
[0x00000000]> \. agent.js
Copied!
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 Cutter. 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):
1
# Permissions
2
$ rafind2 -ZS permission AndroidManifest.xml
3
# Activities
4
$ rafind2 -ZS activity AndroidManifest.xml
5
# Content providers
6
$ rafind2 -ZS provider AndroidManifest.xml
7
# Services
8
$ rafind2 -ZS service AndroidManifest.xml
9
# Receivers
10
$ rafind2 -ZS receiver AndroidManifest.xml
Copied!
Or use rabin2 to get information about a binary file:
1
$ rabin2 -I UnCrackable-Level1/classes.dex
2
arch dalvik
3
baddr 0x0
4
binsz 5528
5
bintype class
6
bits 32
7
canary false
8
retguard false
9
class 035
10
crypto false
11
endian little
12
havecode true
13
laddr 0x0
14
lang dalvik
15
linenum false
16
lsyms false
17
machine Dalvik VM
18
maxopsz 16
19
minopsz 1
20
nx false
21
os linux
22
pcalign 0
23
pic false
24
relocs false
25
sanitiz false
26
static true
27
stripped false
28
subsys java
29
va true
30
sha1 12-5508c b7fafe72cb521450c4470043caa332da61d1bec7
31
adler32 12-5528c 00000000
Copied!
Type rabin2 -h to see all options:
1
$ rabin2 -h
2
Usage: rabin2 [-AcdeEghHiIjlLMqrRsSUvVxzZ] [[email protected] at] [-a arch] [-b bits] [-B addr]
3
[-C F:C:D] [-f str] [-m addr] [-n str] [-N m:M] [-P[-P] pdb]
4
[-o str] [-O str] [-k query] [-D lang symname] file
5
[email protected] [addr] show section, symbol or import at addr
6
-A list sub-binaries and their arch-bits pairs
7
-a [arch] set arch (x86, arm, .. or <arch>_<bits>)
8
-b [bits] set bits (32, 64 ...)
9
-B [addr] override base address (pie bins)
10
-c list classes
11
-cc list classes in header format
12
-H header fields
13
-i imports (symbols imported from libraries)
14
-I binary info
15
-j output in json
16
...
Copied!
Use the main r2 utility to access the r2 shell. You can load DEX binaries just like any other binary:
1
$ r2 classes.dex
Copied!
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.
1
[0x000009c8]> izq
2
0xc50 39 39 /dev/com.koushikdutta.superuser.daemon/
3
0xc79 25 25 /system/app/Superuser.apk
4
...
5
0xd23 44 44 5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=
6
0xd51 32 32 8d127684cbc37c17616d806cf50473cc
7
0xd76 6 6 <init>
8
0xd83 10 10 AES error:
9
0xd8f 20 20 AES/ECB/PKCS7Padding
10
0xda5 18 18 App is debuggable!
11
0xdc0 9 9 CodeCheck
12
0x11ac 7 7 Nope...
13
0x11bf 14 14 Root detected!
Copied!
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).
1
[0x000009c8]> izj~{}
2
[
3
{
4
"vaddr": 3152,
5
"paddr": 3152,
6
"ordinal": 1,
7
"size": 39,
8
"length": 39,
9
"section": "file",
10
"type": "ascii",
11
"string": "L2Rldi9jb20ua291c2hpa2R1dHRhLnN1cGVydXNlci5kYWVtb24v"
12
},
13
{
14
"vaddr": 3193,
15
"paddr": 3193,
16
"ordinal": 2,
17
"size": 25,
18
"length": 25,
19
"section": "file",
20
"type": "ascii",
21
"string": "L3N5c3RlbS9hcHAvU3VwZXJ1c2VyLmFwaw=="
22
},
Copied!
You can print the class names and their methods with the r2 command ic (information classes).
1
[0x000009c8]> ic
2
...
3
0x0000073c [0x00000958 - 0x00000abc] 356 class 5 Lsg/vantagepoint/uncrackable1/MainActivity
4
:: Landroid/app/Activity;
5
0x00000958 method 0 pC Lsg/vantagepoint/uncrackable1/MainActivity.method.<init>()V
6
0x00000970 method 1 P Lsg/vantagepoint/uncrackable1/MainActivity.method.a(Ljava/lang/String;)V
7
0x000009c8 method 2 r Lsg/vantagepoint/uncrackable1/MainActivity.method.onCreate (Landroid/os/Bundle;)V
8
0x00000a38 method 3 p Lsg/vantagepoint/uncrackable1/MainActivity.method.verify (Landroid/view/View;)V
9
0x0000075c [0x00000acc - 0x00000bb2] 230 class 6 Lsg/vantagepoint/uncrackable1/a :: Ljava/lang/Object;
10
0x00000acc method 0 sp Lsg/vantagepoint/uncrackable1/a.method.a(Ljava/lang/String;)Z
11
0x00000b5c method 1 sp Lsg/vantagepoint/uncrackable1/a.method.b(Ljava/lang/String;)[B
Copied!
You can print the imported methods with the r2 command ii (information imports).
1
[0x000009c8]> ii
2
[Imports]
3
Num Vaddr Bind Type Name
4
...
5
29 0x000005cc NONE FUNC Ljava/lang/StringBuilder.method.append(Ljava/lang/String;) Ljava/lang/StringBuilder;
6
30 0x000005d4 NONE FUNC Ljava/lang/StringBuilder.method.toString()Ljava/lang/String;
7
31 0x000005dc NONE FUNC Ljava/lang/System.method.exit(I)V
8
32 0x000005e4 NONE FUNC Ljava/lang/System.method.getenv(Ljava/lang/String;)Ljava/lang/String;
9
33 0x000005ec NONE FUNC Ljavax/crypto/Cipher.method.doFinal([B)[B
10
34 0x000005f4 NONE FUNC Ljavax/crypto/Cipher.method.getInstance(Ljava/lang/String;) Ljavax/crypto/Cipher;
11
35 0x000005fc NONE FUNC Ljavax/crypto/Cipher.method.init(ILjava/security/Key;)V
12
36 0x00000604 NONE FUNC Ljavax/crypto/spec/SecretKeySpec.method.<init>([BLjava/lang/String;)V
Copied!
A common approach when inspecting a binary is to search for something, navigate to it and visualize it in order to interpret the code. One of the ways to find something using radare2 is by filtering the output of specific commands, i.e. to grep them using ~ plus a keyword (~+ for case-insensitive). For example, we might know that the app is verifying something, we can inspect all radare2 flags and see where we find something related to "verify".
When loading a file, radare2 tags everything it's able to find. These tagged names or references are called flags. You can access them via the command f.
In this case we will grep the flags using the keyword "verify":
1
[0x000009c8]> f~+verify
2
0x00000a38 132 sym.Lsg_vantagepoint_uncrackable1_MainActivity.method. \
3
verify_Landroid_view_View__V
4
0x00000a38 132 method.public.Lsg_vantagepoint_uncrackable1_MainActivity. \
5
Lsg_vantagepoint_uncrackable1
6
_MainActivity.method.verify_Landroid_view_View__V
7
0x00001400 6 str.verify
Copied!
It seems that we've found one method in 0x00000a38 (that was tagged two times) and one string in 0x00001400. Let's navigate (seek) to that method by using its flag:
1
[0x000009c8]> s sym.Lsg_vantagepoint_uncrackable1_MainActivity.method. \
2
verify_Landroid_view_View__V
Copied!
And of course you can also use the disassembler capabilities of r2 and print the disassembly with the command pd (or pdf if you know you're already located in a function).
1
[0x00000a38]> pd
Copied!
r2 commands normally accept options (see pd?), e.g. you can limit the opcodes displayed by appending a number ("N") to the command pd N.
\
Instead of just printing the disassembly to the console you may want to enter the so-called Visual Mode by typing V.
\
By default, you will see the hexadecimal view. By typing p you can switch to different views, such as the disassembly view:
\
Radare2 offers a Graph Mode that is very useful to follow the flow of the code. You can access it from the Visual Mode by typing V:
\
This is only a selection of some radare2 commands to start getting some basic information from Android binaries. Radare2 is very powerful and has dozens of commands that you can find on the radare2 command documentation. Radare2 will be used throughout the guide for different purposes such as reversing code, debugging or performing binary analysis. We will also use it in combination with other frameworks, especially Frida (see the r2frida section for more information).
Please refer to the chapter "Tampering and Reverse Engineering on Android" for more detailed use of radare2 on Android, especially when analyzing native libraries. You may also want to read the official radare2 book.

Radare2 (iOS)

Radare2 is a complete framework for reverse-engineering and analyzing binaries. The installation instructions can be found in the GitHub repository. To learn more on radare2 you may want to read the official radare2 book.

RMS Runtime Mobile Security

RMS - Runtime Mobile Security is a runtime mobile application analysis toolkit, supporting Android and iOS Apps. It offers a web GUI and is written in Python.
It's leveraging a running Frida server on a jailbroken device with the following out-of-box functionalities:
  • Execute popular Frida scripts
  • Execute custom Frida scripts
  • Dump all the loaded classes and relative methods
  • Hook methods on the fly
  • (Android) Monitor Android APIs and usage of native APIs
The installation instructions and "how-to guide" of RMS can be found in the Readme of the Github repo.

Tools for Android

Adb

adb (Android Debug Bridge), shipped with the Android SDK, bridges the gap between your local development environment and a connected Android device. You'll usually leverage it to test apps on the emulator or a connected device via USB or Wi-Fi. Use the adb devices command to list the connected devices and execute it with the -l argument to retrieve more details on them.
1
$ adb devices -l
2
List of devices attached
3
090c285c0b97f748 device usb:1-1 product:razor model:Nexus_7 device:flo
4
emulator-5554 device product:sdk_google_phone_x86 model:Android_SDK_built_for_x86 device:generic_x86 transport_id:1
Copied!
adb provides other useful commands such as adb shell to start an interactive shell on a target and adb forward to forward traffic on a specific host port to a different port on a connect device.
1
$ adb forward tcp:<host port> tcp:<device port>
Copied!
1
$ adb -s emulator-5554 shell
2
3
acct
4
cache
5
charger
6
config
7
...
Copied!
You'll come across different use cases on how you can use adb commands when testing later in this book. Note that you must define the serialnummer of the target device with the -s argument (as shown by the previous code snippet) in case you have multiple devices connected.

Android NDK

The Android NDK contains prebuilt versions of the native compiler and toolchain. Both the GCC and Clang compilers have traditionally been supported, but active support for GCC ended with NDK revision 14. The device architecture and host OS determine the appropriate version. The prebuilt toolchains are in the toolchains directory of the NDK, which contains one subdirectory for each architecture.
Architecture
Toolchain name
ARM-based
arm-linux-androideabi-<gcc-version>
x86-based
x86-<gcc-version>
MIPS-based
mipsel-linux-android-<gcc-version>
ARM64-based
aarch64-linux-android-<gcc-version>
X86-64-based
x86_64-<gcc-version>
MIPS64-based
mips64el-linux-android-<gcc-version>
Besides picking the right architecture, you need to specify the correct sysroot for the native API level you want to target. The sysroot is a directory that contains the system headers and libraries for your target. Native APIs vary by Android API level. Available sysroot directories for each Android API level can be found in $NDK/platforms/. Each API level directory contains subdirectories for the various CPUs and architectures.
One possibility for setting up the build system is exporting the compiler path and necessary flags as environment variables. To make things easier, however, the NDK allows you to create a so-called standalone toolchain, which is a temporary toolchain that incorporates the required settings.
To set up a standalone toolchain, download the latest stable version of the NDK. Extract the ZIP file, change into the NDK root directory, and run the following command:
1
$ ./build/tools/make_standalone_toolchain.py --arch arm --api 24 --install-dir /tmp/android-7-toolchain
Copied!
This creates a standalone toolchain for Android 7.0 (API level 24) in the directory /tmp/android-7-toolchain. For convenience, you can export an environment variable that points to your toolchain directory, (we'll be using this in the examples). Run the following command or add it to your .bash_profile or other startup script:
1
$ export TOOLCHAIN=/tmp/android-7-toolchain
Copied!

Android SDK

Local Android SDK installations are managed via Android Studio. Create an empty project in Android Studio and select Tools -> SDK Manager to open the SDK Manager GUI. The SDK Platforms tab is where you install SDKs for multiple API levels. Recent API levels are:
  • Android 11.0 (API level 30)
  • Android 10.0 (API level 29)
  • Android 9.0 (API level 28)
  • Android 8.1 (API level 27)
  • Android 8.0 (API level 26)
An overview of all Android codenames, their version number and API levels can be found in the Android Developer Documentation.
\
Installed SDKs are on the following paths:
Windows:
1
C:\Users\<username>\AppData\Local\Android\sdk
Copied!
MacOS:
1
/Users/<username>/Library/Android/sdk
Copied!
Note: On Linux, you need to choose an SDK directory. /opt, /srv, and /usr/local are common choices.

Android Studio

The official IDE for Google's Android operating system, built on JetBrains' IntelliJ IDEA software and designed specifically for Android development - https://developer.android.com/studio/index.html

Android-SSL-TrustKiller

Android-SSL-TrustKiller is a Cydia Substrate Module acting as a blackbox tool to bypass SSL certificate pinning for most applications running on a device - https://github.com/iSECPartners/Android-SSL-TrustKiller

Apktool