Skip to content

Commit 6a37b08

Browse files
authored
Merge pull request #1186 from HackTricks-wiki/update_Android_Services_101_20250725_182755
Android Services 101
2 parents 055d75e + 03a3bdf commit 6a37b08

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

src/mobile-pentesting/android-app-pentesting/android-applications-basics.md

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,112 @@ if (dpm.isAdminActive(adminComponent)) {
395395
}
396396
```
397397

398+
399+
## Enumerating and Exploiting AIDL / Binder Services
400+
401+
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).
402+
403+
### 1. Discover running services
404+
405+
```bash
406+
# from an adb shell (USB or wireless)
407+
service list # simple one-liner
408+
am list services # identical output, ActivityManager wrapper
409+
```
410+
411+
Output is a numbered list such as:
412+
```
413+
145 mtkconnmetrics: [com.mediatek.net.connectivity.IMtkIpConnectivityMetrics]
414+
146 wifi : [android.net.wifi.IWifiManager]
415+
```
416+
* The **index** (first column) is assigned at runtime – do ***not*** rely on it across reboots.
417+
* The **Binder name** (e.g. `mtkconnmetrics`) is what will be passed to `service call`.
418+
* The value inside the brackets is the fully-qualified **AIDL interface** that the stub was generated from.
419+
420+
### 2. Obtain the interface descriptor (PING)
421+
Every Binder stub automatically implements **transaction code `0x5f4e5446`** (`1598968902` decimal, ASCII "_NTF").
422+
423+
```bash
424+
# "ping" the service
425+
service call mtkconnmetrics 1 # 1 == decimal 1598968902 mod 2^32
426+
```
427+
A valid reply returns the interface name encoded as a UTF-16 string inside a `Parcel`.
428+
429+
### 3. Calling a transaction
430+
Syntax: `service call <name> <code> [type value ...]`
431+
432+
Common argument specifiers:
433+
* `i32 <int>` – signed 32-bit value
434+
* `i64 <long>` – signed 64-bit value
435+
* `s16 <string>` – UTF-16 string (Android 13+ uses `utf16`)
436+
437+
Example – start network monitoring with uid **1** on a MediaTek handset:
438+
```bash
439+
service call mtkconnmetrics 8 i32 1
440+
```
441+
442+
### 4. Brute-forcing unknown methods
443+
When header files are unavailable you can **iterate the code** until the error changes from:
444+
```
445+
Result: Parcel(00000000 00000000) # "Not a data message"
446+
```
447+
to a normal `Parcel` response or `SecurityException`.
448+
449+
```bash
450+
for i in $(seq 1 50); do
451+
printf "[+] %2d -> " $i
452+
service call mtkconnmetrics $i 2>/dev/null | head -1
453+
done
454+
```
455+
456+
If the service was compiled **with proguard** the mapping must be guessed – see next step.
457+
458+
### 5. Mapping codes ↔ methods via onTransact()
459+
Decompile the jar/odex that implements the interface (for AOSP stubs check `/system/framework`; OEMs often use `/system_ext` or `/vendor`).
460+
Search for `Stub.onTransact()` – it contains a giant `switch(transactionCode)`:
461+
462+
```java
463+
case TRANSACTION_updateCtaAppStatus: // 5
464+
data.enforceInterface(DESCRIPTOR);
465+
int appId = data.readInt();
466+
boolean ok = data.readInt() != 0;
467+
updateCtaAppStatus(appId, ok);
468+
reply.writeNoException();
469+
return true;
470+
```
471+
472+
Now the prototype and **parameter types** are crystal clear.
473+
474+
### 6. Spotting missing permission checks
475+
The implementation (often an inner `Impl` class) is responsible for authorisation:
476+
477+
```java
478+
private void updateCtaAppStatus(int uid, boolean status) {
479+
if (!isPermissionAllowed()) {
480+
throw new SecurityException("uid " + uid + " rejected");
481+
}
482+
/* privileged code */
483+
}
484+
```
485+
Absence of such logic or a whitelist of privileged UIDs (e.g. `uid == 1000 /*system*/`) is a **vulnerability indicator**.
486+
487+
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.
488+
489+
### 7. Automating the assessment
490+
Tools / scripts that speed-up Binder reconnaissance:
491+
* [binderfs](https://android.googlesource.com/platform/frameworks/native/+/master/cmds/binderfs/) – exposes `/dev/binderfs` with per-service nodes
492+
* [`binder-scanner.py`](https://github.com/adenflare/binder-scanner) – walks the binder table and prints ACLs
493+
* Frida shortcut: `Java.perform(()=>console.log(android.os.ServiceManager.listServices().toArray()))`
494+
495+
---
496+
497+
## References
498+
499+
- [Android Services 101 – Pentest Partners](https://www.pentestpartners.com/security-blog/android-services-101/)
500+
- [Android Developer Docs – AIDL](https://developer.android.com/guide/components/aidl)
501+
- [Android Developer Docs – IBinder](https://developer.android.com/reference/android/os/IBinder)
502+
- [Understanding Binder, Talk @ Google](https://www.youtube.com/watch?v=O-UHvFjxwZ8)
503+
398504
{{#include ../../banners/hacktricks-training.md}}
399505

400506

0 commit comments

Comments
 (0)