From d2573dc2bd920d3a3193fc6379331f6d93ff3773 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Wed, 5 Aug 2026 08:38:43 +0000 Subject: [PATCH] Add content from: Octagon: Technical Analysis of a Fake Bahrain Civil Defense ... --- .../android-malware-post-exploitation.md | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/generic-methodologies-and-resources/basic-forensic-methodology/android-malware-post-exploitation.md b/src/generic-methodologies-and-resources/basic-forensic-methodology/android-malware-post-exploitation.md index 19535d5b20e..4ca2afee38a 100644 --- a/src/generic-methodologies-and-resources/basic-forensic-methodology/android-malware-post-exploitation.md +++ b/src/generic-methodologies-and-resources/basic-forensic-methodology/android-malware-post-exploitation.md @@ -145,6 +145,56 @@ Triage ideas: - fake media/font assets later passed into `ZipInputStream`, `DexClassLoader`, or custom RC4 helpers - reflection on `pathList`, `dexElements`, `ContextImpl`, or `LoadedApk` close to asset decryption +### Manifest-declared components resolved only at runtime + +A useful dropper hunting pattern is when `AndroidManifest.xml` declares activities/services that are **missing from the root `classes.dex`**. The visible APK often keeps the real implementations inside an encrypted asset (`*.ttf`, `*.dat`, `*.jar`, `*.base`), decrypts it into private storage, and only then exposes the missing classes through `DexClassLoader` or reflective `DexPathList` injection. + +Practical workflow: + +1. Extract every class name referenced by `AndroidManifest.xml`. +2. Compare them against all packaged `classes*.dex` files, not just the first DEX. +3. Treat unresolved components as a strong signal for staged code loading. +4. Hook asset reads, private-file writes, and class-loader APIs to recover the hidden module at runtime. + +High-signal events to correlate: +- `AssetManager.open()` / `Resources.openRawResource()` on non-media assets with high entropy +- `FileOutputStream` / `openFileOutput()` writing `*.dex`, `*.jar`, `*.apk` under app-private paths +- `DexClassLoader`, `PathClassLoader`, `InMemoryDexClassLoader`, or reflection touching `pathList` / `dexElements` +- `adb logcat` entries revealing generated payload paths or class-loading failures + +Quick triage: + +```bash +# Manifest vs DEX diff +apkanalyzer manifest print app.apk | rg 'service|activity|receiver' +unzip -l app.apk | rg 'classes.*\.dex|assets/|res/raw/' + +# Recover runtime payloads from the app sandbox +adb shell run-as sh -c 'find . -type f \( -name "*.dex" -o -name "*.jar" -o -name "*.apk" -o -name "*.json" -o -name "*.db" -o -name "*.xml" \) 2>/dev/null' +adb logcat | rg 'DexClassLoader|ClassNotFoundException|PackageInstaller|app_' +``` + +### Asset-to-`PackageInstaller` staging and nested child payloads + +Another useful evasion pattern is to hide stage 2 inside `assets/` and **stream it directly into a `PackageInstaller` session** instead of first dropping a plainly named APK in shared storage. After the child package is installed, that second package may generate another `DEX`/`JAR` under `/data/user/0//app_*` and dynamically load the final module. + +Hunting ideas: +- correlate `ACTION_MANAGE_UNKNOWN_APP_SOURCES` / `REQUEST_INSTALL_PACKAGES` with `PackageInstaller.createSession` -> `openWrite` -> `fsync` -> `commit` +- watch for the parent package stopping a temporary service (often VPN / overlay / lure UI) immediately after install, then launching the new package +- inspect `PACKAGE_ADDED` / `PACKAGE_REPLACED` receivers, private `app_*` directories, and follow-on `DexClassLoader` activity in the child app + +### `AccountManager` + Sync Adapter persistence + +A less common but very useful Android persistence primitive is to register a **fake account** and attach a **Sync Adapter** to it. The malware then uses `ContentResolver.setSyncAutomatically()`, `addPeriodicSync()`, or `requestSync()` so Android wakes it on a schedule even when no long-running service is visible. + +What to look for: +- authenticator XML/resources plus code calling `AccountManager.addAccountExplicitly` +- a sync adapter service with `android.content.SyncAdapter` metadata +- suspicious sync intervals (for example every 30 minutes) or forced immediate sync right after connectivity returns +- boot receivers / WorkManager jobs whose only purpose is to re-register the account or reschedule sync + +This is especially useful in samples that already store queue/state locally (SQLite + SharedPreferences): periodic sync becomes the exfil/reconnect trigger for offline-collected SMS, credential captures, contacts, or phishing results. + ### Anti-analysis kill-switch Packed loaders often **self-terminate** when emulator or analysis checks fail (e.g., `CPU_ABI` validation) by calling: @@ -862,6 +912,7 @@ struct Header { ## References +- [Octagon: Technical Analysis of a Fake Bahrain Civil Defense Application](https://labs.k7computing.com/index.php/octagon-technical-analysis-of-a-fake-bahrain-civil-defense-application/) - [Premium Deception: Uncovering a Global Android Carrier Billing Fraud Campaign](https://zimperium.com/blog/premium-deception-uncovering-a-global-android-carrier-billing-fraud-campaign) - [SmsRetrieverApi reference](https://developers.google.com/android/reference/com/google/android/gms/auth/api/phone/SmsRetrieverApi) - [Android `CookieManager` reference](https://developer.android.com/reference/android/webkit/CookieManager)