Objection: Complete Guide to Mobile Application Runtime Security Testing Using Kali Linux

Objection: Complete Guide to Mobile Application Runtime Security Testing Using Kali Linux

Objection is a runtime mobile exploration toolkit, built on top of Frida, developed and maintained by SensePost. It was created to help security testers assess the security posture of mobile applications without requiring a jailbroken iOS device or a rooted Android device for many of its core functions (though a rooted/jailbroken device unlocks the toolkit’s full capability). Objection is not a jailbreak or root bypass tool itself — it operates within the same sandbox constraints Frida is subject to — but it dramatically simplifies dynamic instrumentation by wrapping dozens of the most common Frida-based testing tasks into short, memorable, human-readable commands.

Instead of hand-writing custom JavaScript for every routine task, a tester can launch an interactive Objection REPL session attached to a target app and simply type commands such as android sslpinning disable or ios jailbreak disable. Objection’s key capabilities include:

  • Patching iOS and Android applications to embed a Frida Gadget, enabling instrumentation on non-rooted/non-jailbroken devices.
  • Exploring and interacting with the application’s container file system (list, upload, download files).
  • Performing memory-related tasks: listing loaded modules, dumping memory ranges, searching memory for patterns.
  • Bypassing common SSL/TLS certificate pinning implementations with a single command.
  • Bypassing common root/jailbreak detection checks.
  • Listing, searching, and hooking (watching) Java classes and methods at runtime to dump arguments, return values, and backtraces.
  • Interacting with SQLite databases, keychains (iOS), and shared preferences (Android) found within the app’s sandbox.
  • Executing arbitrary shell commands within the context of the Android app (android shell_exec).
  • Taking screenshots and manipulating UI-level security flags (e.g., FLAG_SECURE).

How to Install

Objection is distributed as a Python package and installed via pip3. It requires Frida (client tools) to already be installed, since Objection depends on the frida Python bindings.

# Ensure pip3 is installed
sudo apt update
sudo apt install python3-pip -y

# Install Objection (this will also pull in the frida Python bindings as a dependency)
pip3 install objection --break-system-packages

# To update an existing installation later
pip3 install --upgrade objection --break-system-packages

Verify installation:

$ objection version
objection: 1.11.0

Prerequisite: frida-server must be running on the target device (see the Frida section, 23.4, for full deployment instructions):

adb push frida-server /data/local/tmp/frida-server
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "/data/local/tmp/frida-server &"

Syntax

objection [options] explore
objection --gadget <package_or_bundle_id> explore
objection -n <process_name> explore
objection patchapk -s <path_to_apk>

Once inside the interactive REPL (after explore), the syntax for in-session commands follows this general pattern:

<category> <subcategory> <action> [arguments] [--flags]

For example: android hooking watch class_method com.example.MainActivity.checkLogin --dump-args --dump-return

All Command-Line Options

Top-level objection CLI flags (used before explore):

OptionDescription
-n, --network <NAME>Attach to a running process by name (equivalent to Frida’s -n)
-p, --pid <PID>Attach to a running process by PID
-g, --gadget <IDENTIFIER>Attach to an app running an embedded Frida Gadget (used for non-rooted/patched apps)
-h, --host <HOST>Connect to a remote Frida server on HOST
-P, --port <PORT>Port for the remote Frida server connection
-S, --serial <SERIAL>Target a specific device serial (multiple devices connected)
-d, --debugEnable debug-level output for the objection session
--startup-command <CMD>Run a command immediately after the REPL starts (before returning control)
--startup-script <FILE>Run a Frida JS script immediately after the REPL starts

objection patchapk options (embedding the Frida Gadget into an APK for non-rooted testing):

OptionDescription
-s, --source <APK>Path to the source APK to patch
-a, --architecture <ARCH>Target architecture of the Gadget to embed (e.g., arm, arm64, x86, x86_64)
-n, --networkEnables network communication config patch (cleartext traffic)
-p, --pausePause the app on launch, waiting for a debugger/Frida to attach
-o, --output <FILE>Output filename for the patched APK

Key in-REPL command categories (subset — not an exhaustive list, as Objection has dozens of commands):

CommandDescription
envPrint environment paths (data directory, cache directory, etc.) where the app is stored
fridaPrint information about the connected Frida version
file download <remote> [local]Download a file from the device to the host
file upload <local> [remote]Upload a file from the host to the device
import <script.js>Import and run a custom Frida JavaScript file
jobs listList currently running background hooks/jobs
jobs kill <id>Stop a specific background job
android sslpinning disableAttempt to bypass common Android SSL pinning implementations
android root disableAttempt to disable root detection checks
android root simulateSimulate a rooted environment for the app to detect (testing anti-tamper logic)
android shell_exec <cmd>Execute a shell command in the context of the app’s process
android ui screenshot <path>Take a screenshot of the current app UI
android ui FLAG_SECURE falseDisable the FLAG_SECURE UI protection to allow screenshots via hardware keys
android hooking list classesList all currently loaded Java classes
android hooking list class_loadersList all active class loaders (useful for packed/dynamically loaded DEX)
android hooking search classes <pattern>Search loaded classes by name pattern
android hooking list class_methods <class>List all methods of a specific class
android hooking watch class <class>Watch/hook all methods of a class
android hooking watch class_method <class.method>Watch/hook a specific method, with optional flags
android heap search instances <class>Search the heap for live instances of a class
android intent launch_activity <activity>Launch a specific Android activity
android keystore listList entries in the Android KeyStore
ios sslpinning disableAttempt to bypass common iOS SSL pinning implementations
ios jailbreak disableAttempt to disable jailbreak detection checks
ios keychain dumpDump the iOS keychain contents
ios nsuserdefaults getDump NSUserDefaults contents
sqlite connect <db_file>Connect to and query a SQLite database inside the app’s sandbox
memory list modulesList loaded native modules and their base addresses
memory dump all <destination>Dump the entire process memory to a local file
memory dump from_base <address> <size> <destination>Dump a specific memory range starting at a base address
exit / quitExit the Objection REPL

--dump-args, --dump-backtrace, --dump-return are common flags appended to android hooking watch class_method to control what data is printed for each intercepted call.

Basic Usage (Expected Output in Bash)

Attach Objection to a running app (rooted device, package already running):

$ objection -g com.android.insecurebankv2 explore
     _   _         _   _
    | | | |       | | (_)
 ___| |__| | ___  ___| |_ _  ___  _ __
/ __|  __  |/ _ \/ __| __| |/ _ \| '_ \
\__ \ |  | |  __/ (__| |_| | (_) | | | |
|___/_|  |_|\___|\___|\__|_|\___/|_| |_|
     objection: runtime mobile exploration
by: @leonjza from @sensepost

com.android.insecurebankv2 on (google: 13) [usb] # 

Run a single command against the app to check environment paths:

com.android.insecurebankv2 on (google: 13) [usb] # env
Name                Path
------------------  -----------------------------------------------------
cacheDirectory      /data/user/0/com.android.insecurebankv2/cache
codeCacheDirectory  /data/user/0/com.android.insecurebankv2/code_cache
externalCacheDirectory  /storage/emulated/0/Android/data/com.android.insecurebankv2/cache
filesDirectory      /data/user/0/com.android.insecurebankv2/files

Practical Examples with Output

Example 1 — Attach to a running process by name and explore:

$ frida-ps -Uai | grep -i insecurebank
 2214  InsecureBankv2    com.android.insecurebankv2

$ objection -n InsecureBankv2 explore
com.android.insecurebankv2 on (google: 13) [usb] # 

Example 2 — Bypass SSL pinning with a single command:

com.android.insecurebankv2 on (google: 13) [usb] # android sslpinning disable
(agent) Custom TrustManager ready, overriding SSLContext.init()
(agent) Found okhttp3.CertificatePinner, overriding check()...
(agent) Registering job 3g7h2. Type: android-ssl-pinning-bypass

Example 3 — Attempt to disable root detection:

com.android.insecurebankv2 on (google: 13) [usb] # android root disable
(agent) Job 5f6e0 registered. Trying to bypass some root detection methods
(agent) Registering job 5f6e0. Type: android-root-detection-disable

Example 4 — List currently loaded Java classes:

com.android.insecurebankv2 on (google: 13) [usb] # android hooking list classes
com.android.insecurebankv2.LoginActivity
com.android.insecurebankv2.DoLogin
com.android.insecurebankv2.CryptoUtil
com.android.insecurebankv2.RootDetectionActivity
android.app.Activity
javax.crypto.Cipher
... (912 classes found)

Example 5 — Search for specific classes by pattern:

com.android.insecurebankv2 on (google: 13) [usb] # android hooking search classes Crypto
com.android.insecurebankv2.CryptoUtil
javax.crypto.Cipher
javax.crypto.spec.SecretKeySpec

Example 6 — List methods of a specific class:

com.android.insecurebankv2 on (google: 13) [usb] # android hooking list class_methods com.android.insecurebankv2.CryptoUtil
public static byte[] com.android.insecurebankv2.CryptoUtil.encrypt(java.lang.String,java.lang.String)
public static byte[] com.android.insecurebankv2.CryptoUtil.decrypt(java.lang.String,java.lang.String)

Example 7 — Hook and watch a method, dumping arguments, backtrace, and return value:

com.android.insecurebankv2 on (google: 13) [usb] # android hooking watch class_method com.android.insecurebankv2.CryptoUtil.decrypt --dump-args --dump-backtrace --dump-return
(agent) Job 8a1c9 registered. Method hooked: com.android.insecurebankv2.CryptoUtil.decrypt
(agent) [8a1c9] Called: com.android.insecurebankv2.CryptoUtil.decrypt(java.lang.String, java.lang.String)
(agent) [8a1c9] Arguments com.android.insecurebankv2.CryptoUtil.decrypt(java.lang.String, java.lang.String)
(agent)     arg0: gk8sY3+plaintextciphertext==
(agent)     arg1: MyHardcodedKey123
(agent) [8a1c9] Return Value: SuperSecretPassword1

Example 8 — Execute a shell command in the context of the app:

com.android.insecurebankv2 on (google: 13) [usb] # android shell_exec whoami
u0_a142

Example 9 — Take a screenshot, bypassing FLAG_SECURE:

com.android.insecurebankv2 on (google: 13) [usb] # android ui FLAG_SECURE false
(agent) FLAG_SECURE was successfully removed
com.android.insecurebankv2 on (google: 13) [usb] # android ui screenshot /tmp/screenshot.png
(agent) Screenshot saved to: /tmp/screenshot.png

Example 10 — Download a file from the app’s sandbox to the host:

com.android.insecurebankv2 on (google: 13) [usb] # file download /data/data/com.android.insecurebankv2/databases/users.db ./users.db
Downloading /data/data/com.android.insecurebankv2/databases/users.db to ./users.db
Streaming file from device...
Writing bytes to destination...
Successfully downloaded 20480 bytes

Example 11 — Connect to and query a SQLite database found on the device:

com.android.insecurebankv2 on (google: 13) [usb] # sqlite connect users.db
Caching local copy of users.db
Connection to SQLite database at users.db successful
SQLite @ users.db > .tables
users
sessions
com.android.insecurebankv2 on (users.db) [usb] # select * from users;
+----+----------+------------------+
| id | username | password         |
+----+----------+------------------+
|  1 | dinesh   | Dinesh@123$      |
|  2 | admin    | Admin@123        |
+----+----------+------------------+

Example 12 — Patch an APK with a Frida Gadget for non-rooted device testing:

$ objection patchapk -s InsecureBankv2.apk -a arm64
INFO: Patching InsecureBankv2.apk with the Frida Gadget for architecture arm64
INFO: Extracting InsecureBankv2.apk to /tmp/objection-patch
INFO: Downloading Frida Gadget for arm64
INFO: Injecting Gadget into the APK
INFO: Rebuilding the APK with apktool
INFO: Signing InsecureBankv2.objection.apk
INFO: Copying final apk from /tmp/objection-patch to current directory
INFO: Cleaning up temp files...
Patching Complete. Find the patched apk here: InsecureBankv2.objection.apk

Common Use Cases

  • Rapid SSL pinning and root detection bypass – Getting past common client-side protections instantly with android sslpinning disable and android root disable, without writing a single line of custom Frida JS.
  • Non-rooted device testing – Using objection patchapk to embed the Frida Gadget directly into a target APK, enabling full dynamic instrumentation on devices where root is not available or desired.
  • Runtime data extraction from insecure storage – Using file download, sqlite connect, and android keystore list to pull sensitive data (session tokens, cached credentials, PII) directly from the running app’s sandbox.
  • Live method call auditing – Using android hooking watch class_method with --dump-args/--dump-return to trace exactly what data flows into and out of a suspicious function (e.g., a custom crypto routine) during real interaction with the app.
  • Anti-tampering and detection-logic testing – Using android root simulate to verify an app’s own anti-tampering/root-detection code actually triggers correctly when a rooted environment is present, from the developer’s side of testing.

Automation with Bash

The following script automates attaching Objection to a target app and running a sequence of common bypass and reconnaissance commands using --startup-command, then chains subsequent commands via a piped command file.

#!/bin/bash
# objection_auto_recon.sh - Automated Objection bypass and recon session

PACKAGE="$1"

if [ -z "$PACKAGE" ]; then
    echo "Usage: $0 <package_name>"
    exit 1
fi

echo "[*] Verifying frida-server connectivity..."
frida-ps -U > /dev/null 2>&1 || { echo "[-] frida-server unreachable. Start it first."; exit 1; }

echo "[*] Confirming target app is running..."
frida-ps -Ua | grep -qi "$PACKAGE" || { echo "[-] $PACKAGE is not running on the device."; exit 1; }

echo "[*] Launching Objection with automated SSL pinning bypass and root detection bypass..."
objection -g "$PACKAGE" \
  --startup-command "android sslpinning disable" \
  explore <<'EOF'
android root disable
android hooking list classes
env
exit
EOF

echo "[+] Automated recon session complete."

Sample run:

$ chmod +x objection_auto_recon.sh
$ ./objection_auto_recon.sh com.android.insecurebankv2
[*] Verifying frida-server connectivity...
[*] Confirming target app is running...
[*] Launching Objection with automated SSL pinning bypass and root detection bypass...
(agent) Registering job 3g7h2. Type: android-ssl-pinning-bypass
com.android.insecurebankv2 on (google: 13) [usb] # android root disable
(agent) Registering job 5f6e0. Type: android-root-detection-disable
com.android.insecurebankv2 on (google: 13) [usb] # android hooking list classes
com.android.insecurebankv2.LoginActivity
com.android.insecurebankv2.DoLogin
...
com.android.insecurebankv2 on (google: 13) [usb] # env
Name                Path
------------------  -----------------------------------------------------
filesDirectory      /data/user/0/com.android.insecurebankv2/files
com.android.insecurebankv2 on (google: 13) [usb] # exit
[+] Automated recon session complete.

Tips and Best Practices

  • Use objection -n <name> or -g <gadget_identifier> for attaching to already-running processes rather than spawning, to avoid disrupting an app that’s already mid-session (e.g., already logged in).
  • Use --startup-command (or --startup-script for more complex logic) to run SSL pinning/root detection bypasses before the REPL finishes loading — this is critical for apps that perform these checks early, such as in Application.onCreate().
  • Combine jobs list and jobs kill <id> to manage long-running hooks (like android hooking watch class_method) without needing to exit and restart the whole session.
  • When android sslpinning disable doesn’t fully work against a custom pinning implementation, use android hooking list classes and android hooking search classes to locate the app’s specific pinning class, then write a targeted Frida script and load it with import <script.js>.
  • Remember that Objection cannot instantiate new objects or call methods that require complex object arguments — for advanced manipulation beyond what Objection’s built-in commands support, drop down to raw Frida scripting.
  • Always test hooking on a rooted test device or emulator first before attempting objection patchapk workflows on production or client-provided applications, since embedding a Gadget modifies and re-signs the APK.
  • Use sqlite connect immediately after file download-ing a .db file locally, or connect directly to the remote path, to explore local storage without needing a separate SQLite browser tool.

Troubleshooting

ProblemCauseSolution
Failed to attach to process on explorefrida-server not running, or version mismatchVerify frida-ps -U works first; confirm client/server Frida versions match
android sslpinning disable doesn’t stop pinning errorsApp uses a custom, non-standard pinning implementationUse android hooking search classes to find the custom pinning class and write a manual Frida hook
Objection REPL hangs or is unresponsiveApp is heavily obfuscated or crashed silently after hook injectionRestart the app, reduce the number of simultaneously active hooks, check adb logcat for a crash trace
patchapk fails during rebuild stepApktool not installed or resource decoding failure in the target APKEnsure apktool is installed and up to date; try patching with -n disabled if network config injection is the failure point
Patched APK won’t install (INSTALL_FAILED_...)Architecture mismatch between Gadget and device, or signature conflict with an already-installed original appMatch -a to the exact device architecture; uninstall the original unpatched app first
file download fails with permission deniedTarget file is outside the app’s accessible sandbox, and device is not rootedEnsure the device is rooted or use a Gadget-patched APK for elevated context
Commands appear to run but produce no visible effect on the appThe hooked class/method was not actually invoked during your test interactionTrigger the corresponding UI action in the running app for the hook to catch the call

References

  • Objection GitHub Repository: https://github.com/sensepost/objection
  • Objection Official Wiki: https://github.com/sensepost/objection/wiki
  • HackTricks – Objection Tutorial: https://hacktricks.wiki/en/mobile-pentesting/android-app-pentesting/frida-tutorial/objection-tutorial.html
  • HackTricks – iOS Hooking With Objection: https://book.hacktricks.xyz/mobile-pentesting/ios-pentesting/ios-hooking-with-objection
  • Kali Linux Tools – Objection: https://www.kali.org/tools/objection/
  • OWASP MASTG – Dynamic Analysis and SSL Pinning Bypass: https://mas.owasp.org/MASTG/Android/0x05c-Reverse-Engineering-and-Static-Analysis/
Total
1
Shares

Leave a Reply

Previous Post
Frida: Complete Guide to Dynamic Application Instrumentation and Runtime Analysis Using Kali Linux

Frida: Complete Guide to Dynamic Application Instrumentation and Runtime Analysis Using Kali Linux

Next Post
Active Directory Penetration Testing: Complete Attack Path Guide

Active Directory Penetration Testing: Complete Attack Path Guide

Related Posts