Android Software Reverse Engineering & Decompilation

MIPS Android Exploitation Lab: Bypassing DEP/ASLR in Legacy Native Applications

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction to MIPS Android Exploitation

While ARM-based processors dominate the modern Android landscape, understanding legacy architectures like MIPS remains crucial for security researchers and reverse engineers. Many older Android devices, industrial control systems (ICS) devices, and embedded systems still utilize MIPS CPUs, often running outdated Android versions with less robust security mitigations. This article delves into the intricacies of exploiting native MIPS applications on Android, specifically focusing on techniques to bypass Data Execution Prevention (DEP) and Address Space Layout Randomization (ASLR), two fundamental security features designed to prevent arbitrary code execution.

Exploiting MIPS-based Android applications requires a deep understanding of the architecture’s calling conventions, instruction set, and memory management. Unlike the widespread documentation for ARM exploitation, MIPS-specific Android exploitation resources can be scarcer, making this an invaluable skill for those targeting legacy systems.

Setting Up Your MIPS Android Exploitation Environment

A robust exploitation environment is key to success. Here’s what you’ll need:

Essential Tools

  • Android Debug Bridge (ADB): For interacting with the Android device/emulator.
  • Android NDK: Provides cross-compilation tools and a MIPS-compatible GDB server.
  • IDA Pro or Ghidra: Industry-standard reverse engineering tools with excellent MIPS support.
  • QEMU (with MIPS Android Image) or a physical MIPS Android Device: An emulator is often easier for initial setup and experimentation.
  • ROPgadget: A powerful tool for finding ROP gadgets in MIPS binaries.

Preparing the Target Application

First, identify your target. Native Android binaries are typically `.so` (shared object) files within an APK. You can determine the architecture using the `file` command:

$ file libnative-lib.so
libnative-lib.so: ELF 32-bit MSB shared object, MIPS, MIPS32 rel2, N32 ABI, version 1 (SYSV), dynamically linked, not stripped

Next, push your `gdbserver` to the device and prepare for remote debugging. Assume `libvuln.so` is our vulnerable MIPS library.

$ adb push <NDK_ROOT>/prebuilt/android-mips/gdbserver/gdbserver /data/local/tmp/
$ adb shell
# chmod 755 /data/local/tmp/gdbserver
# /data/local/tmp/gdbserver :1234 /data/app/com.example.vulnerableapp-1/lib/mips/libvuln.so

Replace `/data/app/com.example.vulnerableapp-1/lib/mips/libvuln.so` with the actual path to your vulnerable library or executable on the device.

Dissecting a Vulnerable MIPS Binary

The foundation of any exploit is identifying a vulnerability, commonly a buffer overflow. Tools like IDA Pro or Ghidra are indispensable here.

Identifying the Vulnerability (Buffer Overflow)

In your disassembler, search for common insecure functions like `strcpy`, `sprintf`, `strcat`, `memcpy` (without proper size checks), or custom functions that copy user-controlled input into fixed-size buffers. MIPS assembly for such a vulnerability might look like this (simplified):

.text:00400800  la      $t9, strcpy
.text:00400804  addiu   $sp, $sp, -0x100
.text:00400808  sw      $ra, 0xFC+var_4($sp)   ; Save return address
.text:0040080C  sw      $s0, 0xFC+var_8($sp)   ; Save stack frame register
.text:00400810  move    $s0, $sp
.text:00400814  li      $a0, 0x100             ; Destination buffer size (e.g., stack buffer)
.text:00400818  lw      $a1, 0x10($s0)         ; Source pointer (user controlled)
.text:0040081C  jalr    $t9                    ; Call strcpy
.text:00400820  nop

Here, `strcpy` copies data from `$a1` (user input) to a stack buffer at `$a0`. If the input length exceeds 0x100 bytes, it will overwrite the saved return address (`$ra`) on the stack.

Understanding MIPS Calling Conventions

MIPS uses a specific calling convention:

  • Arguments: Passed in registers `$a0` through `$a3`. Additional arguments are pushed onto the stack.
  • Return Values: Stored in `$v0` and `$v1`.
  • Return Address: Stored in `$ra`.
  • Stack Pointer: `$sp` points to the top of the stack.
  • Frame Pointer: `$fp` or `$s8` (though not always used).

Controlling `$ra` is our primary goal for redirection of execution flow.

Bypassing Data Execution Prevention (DEP)

DEP (often referred to as W^X or NX bit) prevents code from being executed from data segments of memory, such as the stack or heap. On MIPS, this is typically enforced by the MMU (Memory Management Unit).

The Principle of DEP on MIPS

When the NX bit is set for a memory page, the CPU will raise an exception if it tries to fetch an instruction from that page. This means we cannot simply inject shellcode onto the stack and jump to it.

Return-Oriented Programming (ROP) on MIPS

The standard technique to bypass DEP is Return-Oriented Programming (ROP). ROP chains together small sequences of existing executable instructions (gadgets) already present in the binary or linked libraries. A typical gadget ends with a `jr $ra` or `j $t9` instruction, allowing control flow to return to the next address on the stack.

To find gadgets in MIPS binaries (e.g., `libc.so`), you can use `ROPgadget`:

$ ROPgadget --binary <path_to_libc.so> --mips

Common MIPS gadgets include sequences that manipulate registers and then return, such as:

0x00012345:  li $v0, 1234; jr $ra; addiu $sp, $sp, 0x10
0x00054321:  lw $a0, 0x10($sp); jr $ra; addiu $sp, $sp, 0x18

We leverage existing executable code sections, primarily the `.text` segment of loaded libraries like `libc.so`, which are marked as executable.

Overcoming Address Space Layout Randomization (ASLR)

ASLR randomizes the base addresses of key memory regions (stack, heap, libraries) to make exploitation harder by preventing attackers from predicting absolute addresses.

ASLR on Legacy Android

Older Android versions and MIPS implementations often exhibit weaker ASLR. Specifically:

  • Partial ASLR: The base address of `libc.so` or other shared libraries might be randomized only within a small, predictable range, or not at all for certain regions.
  • Information Leaks: Vulnerabilities like format string bugs or heap leaks can sometimes reveal a library’s base address, effectively bypassing ASLR.

Practical Approach for MIPS

If ASLR is strong, a two-stage attack is needed: an info leak to get a base address, then the ROP exploit. However, for legacy MIPS Android, it’s worth checking memory maps first. Connect to your device via ADB shell and inspect `/proc//maps` for your target process:

$ adb shell
# cat /proc/<PID>/maps
00008000-0000a000 r-xp 00000000 103:02 1195       /data/app/com.example.vulnerableapp-1/lib/mips/libvuln.so
40000000-4014d000 r-xp 00000000 103:02 966        /system/lib/libc.so
...

Notice that `/system/lib/libc.so` might appear at a relatively fixed address (e.g., `0x40000000`). If this is the case, ASLR for `libc` is either absent or weak enough to be predictable. This is a common characteristic of older MIPS Android versions, greatly simplifying ROP chain construction.

Crafting the MIPS ROP Chain: A Practical Example

Let’s assume our goal is to execute `system(“/system/bin/id”)`. We’ll need the address of the `system` function in `libc.so` and a pointer to the string `”/system/bin/id”`.

The Goal: Calling `system(“/system/bin/id”)`

First, find the address of `system` using IDA Pro or Ghidra on `libc.so`. Let’s assume it’s at `0x4003456C`. Next, we need the string `”/system/bin/id”`. If it’s not present in a readable segment, we might need to write it to a writable memory region (e.g., `.data` section or heap) first. For simplicity, let’s assume we can push it onto the stack right before our ROP chain, or find a writable global buffer.

Building the Chain

Our ROP chain will typically look like this on the stack, starting from the overwrite point of `$ra`:

  1. Gadget to load `$a0`: Find a gadget that pops a value from the stack into `$a0` and then returns. A common pattern is `lw $a0, X($sp); …; jr $ra; addiu $sp, $sp, Y`. Let’s say we find one at `0x4001AABB` that takes the next stack value and puts it in `$a0`, then advances `$sp` by 8 bytes.
  2. Address of the string: The address of `”/system/bin/id”`. If pushed on the stack, this will be `<buffer_start_address + offset_to_string>`.
  3. Address of `system()`: The target function to execute.

The exploit payload on the stack would then resemble:

[... filler to overwrite saved $ra ...]
[0x4001AABB]  ; Address of gadget to load $a0
[0xdeadbeef]  ; Placeholder/junk for gadget's stack alignment (if any)
[0x400XXXXX]  ; Address of "/system/bin/id" string
[0x4003456C]  ; Address of system() function

When the vulnerable function returns, `$ra` is popped, pointing to `0x4001AABB`. The gadget executes, loading the string address into `$a0`. The gadget then returns via `jr $ra`, which now points to `0x4003456C` (the address of `system`). `system()` is called with `”/system/bin/id”` as its argument, executing the command.

Conclusion and Further Research

Exploiting MIPS-based Android applications, especially those on older systems, offers a unique set of challenges and rewards. By meticulously understanding the architecture, identifying vulnerabilities, and crafting precise ROP chains, it’s possible to bypass fundamental security mitigations like DEP and ASLR. The key takeaways are to leverage available tools for reverse engineering and gadget finding, understand MIPS calling conventions, and critically analyze the strength of ASLR on the target system. This foundational knowledge can be extended to explore more advanced MIPS exploitation techniques, including Jump-Oriented Programming (JOP) and various kernel-level exploits specific to the MIPS architecture, paving the way for deeper security research in embedded and legacy Android environments.

Android Mobile Specs & Compare Directory

Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!

Compare Devices Specs →
Google AdSense Inline Placement - Content Footer banner