Introduction
As cybersecurity consultants, it’s pretty common to come across Android apps that need to be audited. In this short post, I’ll show you a quick and easy way to set up your own lab to make things smoother. I’ll also share some tips on how I usually approach Android app pentesting and what I like to focus on during an assessment.
A bit of theory never hurts, so here we go: First, it’s important to understand that Android applications come in .apk format. This format is a variation of Java’s .jar files and is used to package and distribute components for Android devices. Basically, an APK is just a compressed ZIP file with a different extension, which means it can be opened and inspected using any archive tool — something we’ll look at later on.
This basic understanding of APK structure will come in handy as we start interacting with real applications, modifying their behavior, and inspecting their logic. Before we get to that point, though, we need to make sure our environment is properly configured.
Create environment
To set up our Android pentesting lab, we need to have the following tools installed:
- Genymotion
- Frida
- Burp Suite
- JADX
Each of these tools plays a key role during the assessment process. Genymotion is an Android emulator that allows us to run virtual devices for testing in a controlled environment — it’s fast, flexible, and supports root access. Frida is a powerful dynamic instrumentation toolkit that lets us hook into running processes, modify app behavior on the fly, and bypass security checks like root or SSL pinning. Burp Suite acts as our intercepting proxy, enabling us to analyze and manipulate HTTP/HTTPS traffic between the app and backend services. Finally, JADX is a decompiler that allows us to convert APKs into readable Java code, making it easier to understand the app’s logic and look for hardcoded secrets, insecure API usage, or potential vulnerabilities
First of all, we’re going to create two virtual devices in Genymotion — one running Android 11 and another running Android 13.0 (which is currently the highest version available in Genymotion). The reason for this setup is that, due to a recent update, Genymotion only provides root access up to Android 11. For versions above that, root access is no longer available.

Personally, I use the Android 11 device most of the time, since it allows me to hook and test apps freely. However, when I come across an app with strong anti-root protections that I can’t bypass easily, I switch to the Android 13.0 device to continue the analysis without root interference.
Let’s start by booting up the Android 11 virtual device and opening Burp Suite. Using the following commands, we’ll extract the Burp certificate, install it on the device, and route all traffic through the proxy.
Make sure the Burp proxy listener is configured to bind to all interfaces (*).
$ curl localhost:8080/cert -o cert.der $ openssl x509 -inform der -in cert.der -out cert.pem $ openssl x509 -inform PEM -subject_hash_old -in certificado.pem | head -1 $ mv cert.pem 9a5ba575.0 $ adb shell vbox86p:/ # su 1|:/ # mount -o remount,rw / :/ # exit vbox86p:/ # exit $ adb push 9a5ba575.0 /system/etc/security/cacerts/
In this step, we gain root access to the Android emulator using adb shell and su, then remount the root filesystem with read/write permissions (mount -o remount,rw /) to allow modifications. After that, we use adb push to copy the Burp Suite certificate (9a5ba575.0) into the system’s trusted CA store located at /system/etc/security/cacerts/, enabling the device to trust our proxy and properly intercept HTTPS traffic.
Now we need to set up the proxy on the Android device. To do that, we first need to get our local IP address — you can use ifconfig
or ip a
for that. Once you have your local IP, run the following command to configure the proxy on the emulator:
$ adb shell settings put global http_proxy 192.168.1.82:8080
This tells the Android system to route all HTTP and HTTPS traffic through the specified proxy — in this case, Burp Suite running on port 8080 of your local machine. Now, if you open a browser on the device and search for anything on Google, you should see the traffic being intercepted in Burp Suite.

Set Frida
If we’re going to audit an app that doesn’t implement SSL pinning or root detection, we can start right away with the setup we just configured. All we need to do is install the app and start analyzing the network traffic.
But things won’t always be smooth — more often than not, we’ll run into apps with protection mechanisms like SSL pinning, root detection, and more. That’s where Frida comes in.
Frida is a dynamic instrumentation toolkit that lets us inject JavaScript into running processes, giving us the ability to bypass or modify app behavior at runtime. With Frida, we can hook into specific functions, disable root checks, bypass SSL pinning, monitor internal function calls, and even modify return values — all without needing to recompile the APK. It’s one of the most powerful tools in mobile app pentesting, especially when dealing with hardened apps.
If you’re not familiar with the concepts of SSL pinning and root detection, I recommend checking out these two articles: 1, 2
To use Frida on the Android device, we need to install frida-server on the emulator or physical device. This binary must match the architecture of the Android system (usually x86 for Genymotion or arm64 for real devices). Once downloaded, we push it to the device and run it in the background with the following commands:
$ adb push frida-server /data/local/tmp/ $ adb shell "chmod +x '/data/local/tmp/frida-server'" $ adb shell "su -c '/data/local/tmp/frida-server &'"
This sets the correct permissions and runs Frida with root privileges in the background, allowing us to start injecting scripts into apps from our host machine using the Frida CLI or Python bindings.
Once Frida is up and running on the phone, we can start using it to hook and modify the behavior of applications in real time. As an example, we’ll bypass the root detection protection of an app called fridaen45minutos. This application was created by some colleagues specifically for a talk, and it includes basic checks to prevent execution on rooted devices. You can download it here.
If we install the app on our phone and try to launch it, we’ll quickly notice that it doesn’t allow us to proceed — that’s because the device is rooted. The app detects the root status and immediately blocks access as a security measure. This behavior is exactly what we’ll be targeting and bypassing with Frida.

Evasion of anti-root control
Now we’re going to use a Frida script designed to bypass the root detection mechanisms implemented in the application. Once we hook into the app’s process and inject the script, Frida will override the methods responsible for performing root checks at runtime, effectively disabling the protection. This allows us to run and interact with the application on a rooted device without being blocked.
The script is included in the repository of the frida-en-45-minutos application, so you can find it there and use it directly:
if(Java.available){
Java.perform(function(){
console.log("");
const rootCheckerClass = Java.use("com.nivel4.RootChecker.rootChecker");
rootCheckerClass.checkSu.implementation = function() {
console.log("checkSu returned", this.checkSu());
return false;
}
rootCheckerClass.testKeys.implementation = function() {
console.log("testKeys returned", this.testKeys());
return false;
}
rootCheckerClass.checkPackages.implementation = function() {
console.log("checkPackages returned", this.checkPackages());
return false;
}
})
}
To find the app’s identifier (package name), we can run the following command:
$ frida-ps -Uai PID Name Identifier ---- -------------------- -------------------------------- 6429 Files com.android.documentsui 6366 Google Play Store com.android.vending 3556 Phone com.android.dialer 7039 fridaen45minutos com.nivel4.fridaen45minutos - Amaze com.amaze.filemanager - Aptoide cm.aptoide.pt - Calendar com.android.calendar - Camera com.android.camera2 - Clock com.android.deskclock - Contacts com.android.contacts - Custom Locale com.android.customlocale2 - Dev Tools com.android.development - Development Settings com.android.development_settings - Gallery com.android.gallery3d - JokesPhone com.cashitapp.app.jokesphone - Messaging com.android.messaging - Neatpagos com.neat.mobileappprod - Search com.android.quicksearchbox - Settings com.android.settings - Superuser com.genymotion.superuser - WebView Shell org.chromium.webview_shell
Once we have the correct identifier (in this case, com.nivel4.fridaen45minutos), we can load the script into the running app by executing:
$ frida -U -f com.nivel4.fridaen45minutos -l antiroot.js ____ / _ | Frida 16.5.2 - A world-class dynamic instrumentation toolkit | (_| | > _ | Commands: /_/ |_| help -> Displays the help system . . . . object? -> Display information about 'object' . . . . exit/quit -> Exit . . . . . . . . More info at https://frida.re/docs/home/ . . . . . . . . Connected to Pixel (id=127.0.0.1:6555) Spawned `com.nivel4.fridaen45minutos`. Resuming main thread! [Pixel::com.nivel4.fridaen45minutos ]-> checkSu returned true checkPackages returned true testKeys returned true
This will inject the script and hook the necessary functions to disable the app’s root detection. After that, if we launch the app on a rooted device, it will no longer block access. This confirms that the anti-root bypass was successful, allowing us to interact with the application freely despite the device being rooted.

In the previous example, we saw how Frida combined with a custom script can effectively bypass the root detection mechanisms of an application. This approach allows security testers to analyze and interact with apps that would otherwise refuse to run on rooted devices, opening the door to deeper inspection and testing.
Reverse Engineering
If we need to perform reverse engineering on the APK, one of the most useful tools is Jadx. After installing it, you’ll find a binary called jadx-gui, which launches the graphical interface of the tool — making it easier to explore the app’s internals visually.
To get started, simply open jadx-gui, click on “File” > “Open”, and select the APK you want to analyze. Jadx will automatically decompile the DEX (Dalvik Executable) files inside the APK and present you with a Java-like source code view. You’ll be able to browse through the app’s package structure, classes, methods, and resources like AndroidManifest.xml, layouts, and strings.

This is extremely useful for understanding how the app works under the hood, identifying potential attack surfaces (such as hardcoded API keys, exposed components, insecure logic), and mapping out where you might want to hook or patch with tools like Frida.
While Jadx doesn’t produce 100% accurate Java code (since it’s decompiled from bytecode), it’s more than enough for static analysis and planning dynamic testing.
In summary: We went through how to set up an environment for mobile app testing, how to configure a proxy to intercept traffic, and how to use Frida to bypass common protections when needed.
Now, I’d like to share some personal tips based on my experience — things that help me perform effective analysis and find interesting vulnerabilities in a short amount of time (because let’s be honest, we rarely have unlimited time during an audit).
Tips
The first thing I usually do is open the APK in jadx-gui and look for any exposed or leaked information — such as hardcoded API keys, credentials, internal endpoints, or file paths. Once I get a general idea of the app’s structure, I install the APK on an emulator and check if it implements security protections like SSL Pinning or Root Detection.
If the app has no protections in place — lucky day! — I jump straight into the ethical hacking phase. But if those protections are present, I try to bypass them using Frida scripts. If the scripts don’t work, then it’s time to go manual — which is great for learning. If you’re interested in learning how to do it manually, I highly recommend this talk (given by some good friends of mine — absolute pros, by the way).
Once the protections are bypassed, I treat the mobile app just like I would a web application. Most mobile apps interact with backend APIs, especially when there’s a login mechanism involved, so the approach becomes very similar to classic API pentesting.
In general, I focus heavily on business logic flaws, injection points, and poor client-side control of iterations, parameters, or flows. I also use multiple mobile testing checklists and guides to make sure I cover as much ground as possible and get the highest value findings in the time I have.