Skip to content
Open
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
73 changes: 72 additions & 1 deletion src/mobile-pentesting/android-app-pentesting/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,77 @@ Minimal indicators when reversing this pattern:
- `usesCleartextTraffic=true`, hidden packages (`isShow=false`), and CDN paths derived from device identifiers
- `sharedUserId=android.uid.system` or platform-signed system APKs inside `/system`, `/product`, `/vendor`, or `/oem`

### Platform-signed OEM malware triage beyond the manifest

When the suspicious package is **already in firmware** and runs as `android.uid.system`, treat it as a **supply-chain implant** rather than as a normal sideloaded app. A useful workflow is:

1. Confirm it is a **system package** and collect the APK path:
```bash
adb shell 'pm list packages -s -U | grep -Ei "hotack|htc|silent|ota|store|update"'
adb shell 'pm path <pkg>'
adb pull $(adb shell pm path <pkg> | cut -d: -f2)
```
2. Check for **boot persistence** patterns in the manifest/code:
- `sharedUserId="android.uid.system"`
- `foregroundServiceType="systemExempted"`
- high-priority `BOOT_COMPLETED` receiver
- service returning `START_STICKY`
- `ConnectivityManager.registerNetworkCallback(...)` to delay C2 until networking is available
3. Treat `usesCleartextTraffic=true`, permissive `TrustManager`, and **HTTP fallback** as a sign that payload traffic or OTA can often be intercepted and replayed in the lab.

#### Bulk recovery of runtime-decoded strings

A very common Android malware pattern is to store URLs, paths, commands, campaign IDs, class names, and SharedPreferences keys as **encrypted byte arrays** and decode them at runtime with a tiny helper. If JADX shows repetitive calls like `g(new byte[]{...}, new byte[]{...})`, do not decrypt them manually one by one: replicate the helper in Python and walk the whole decompiled tree.

Typical clues:
- helper takes **two byte arrays** and XORs them in a loop
- code uses very small classes (`a.java`, `b.java`, `f.java`) after ProGuard/R8
- recovered strings reveal C2 domains, payload directories, `chmod`, `DexClassLoader`, or shell snippets

For rotating-XOR helpers, remember to emulate **Java signed-byte semantics** with `& 0xff` when porting to Python.

#### C2 framing that looks encrypted but leaks the key

Some OEM droppers AES-encrypt the JSON body but still append the **IV and symmetric key in plaintext** to the packet. In practice this is only **network obfuscation**, not confidentiality.

Common reversing pattern:
- request layout similar to `[version][ciphertext][iv][key]`
- custom headers used as a version marker
- random URI paths generated per request to defeat naive path-based signatures
- response layout may differ from request layout, so verify both encode/decode functions separately

Detection ideas:
- match on the **domain + binary packet shape + custom header**, not only on URI paths
- inspect whether `HttpsURLConnection` installs a custom `SSLSocketFactory` / `TrustManager`
- if HTTPS fails, test whether the same endpoint works over cleartext HTTP

#### Firmware-backed reinfection indicators

If disabling or deleting the APK is not durable, move from APK triage into **firmware analysis**. On cheap Android projectors/TV boxes, persistence is often provided by shell scripts and OTA helpers rather than by the APK alone.

Look for:
- boot scripts that disable **Google / Play Protect** receivers with `pm disable`
- preinstall scripts that silently scan directories and install `APK` / `XAPK` files on boot
- OTA clients that fetch updates over **HTTP** or verify only **MD5** before calling `DexClassLoader` or `pm install`
- vendor services that restore the same package after reboot or factory reset

Useful live-response commands:
```bash
adb shell 'dumpsys activity services | grep -i silentsdk'
adb shell 'pm list packages -d | grep -Ei "hotack|htc|silent|ota|store|update"'
adb shell 'ls /data/data/<pkg>/files/'
adb shell 'grep -R "pm disable\|pm install\|xapk\|play protect" /system/bin /vendor/bin /system/etc/init 2>/dev/null'
```

#### Residential-proxy monetisation as the stage-3 objective

A useful analytic pivot for preinstalled Android malware is that the final payload may not be classic spyware; it may be **residential proxy enrolment**. If the device begins querying IP-check or proxy-control domains immediately after joining Wi-Fi, assume the operator may be registering the victim's public IP for resale.

Indicators:
- unexplained DNS requests to **IP-discovery** or **proxy-control** domains before the user launches any app
- periodic stage-2 / stage-3 check-ins even while the device is idle
- downloader/plugin architecture where the visible APK only fetches proxy modules later

### C2-controlled anti-analysis for Android payload delivery

OEM droppers sometimes make the network artifact intentionally non-parsable unless you recover a **server-supplied transform parameter** from the C2 manifest.
Expand Down Expand Up @@ -1090,6 +1161,6 @@ AndroL4b is an Android security virtual machine based on ubuntu-mate includes th
- [MalFixer](https://github.com/Cleafy/Malfixer)
- [BeatBanker: A dual‑mode Android Trojan](https://securelist.com/beatbanker-miner-and-banker/119121/)
- [Pre-installed C2 Infrastructure and RAT Payload on Android Projectors](https://github.com/Kavan00/Android-Projector-C2-Malware)
- [Reverse-engineering pre-installed Android malware with Claude Code](https://zanestjohn.com/blog/reing-with-claude-code)
- [Reverse Engineering Android Malware with Claude Code](https://zanestjohn.com/blog/reing-with-claude-code)

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