You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/mobile-pentesting/android-app-pentesting/insecure-in-app-update-rce.md
+31-2Lines changed: 31 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -249,7 +249,34 @@ Also consider stubbing vendor methods such as `PluginVerifier.verifySignature()`
249
249
- Split APK / local-testing leftovers: official Play Core testing helpers obtain splits from a specified local directory, and `SplitCompat.install()` immediately exposes code/resources from installed splits. In production builds, any custom equivalent that trusts writable module directories, `split_id`-derived filenames, or leftover local-testing artefacts becomes a plugin-swap primitive. Historically this class of bug already led to Play Core code execution via path traversal (CVE-2020-8913); today you usually find the same idea as app-side misuse rather than the library bug itself.
250
250
- React Native / Web-based OTA content: if native bridges execute JS from OTA without strict signing, arbitrary code execution in the app context is possible (e.g., insecure CodePush-like flows). For Expo/EAS-style updaters, look for disabled or bypassable update signing before treating the JS bundle as trusted.
251
251
252
-
### 5.1 Platform changes that change exploitation
252
+
### 5.1 Trusted updater abuse: installing packages that do not exist yet
253
+
254
+
Do not test only replacement updates. A preinstalled or privileged updater may deserialize a remote Boolean/enum that decides whether the target package must already exist. If the backend can select an “install when absent” branch (for example, `installNotExists=true`), the update channel becomes an **arbitrary new-APK installation primitive**, even if the normal workflow appears limited to maintaining firmware packages. Trace the complete path from MQTT/push-message parsing through the package-existence check, download destination and `PackageInstaller`/PackageManager call.<sup>[[3]](#references)</sup>
255
+
256
+
Preserve the updater cache and correlate every newly introduced package with its recorded installer. Android's `pm list packages -i` option exposes the installer identity; on a rooted or forensic image, compare this with the APKs staged below the updater's external cache.<sup>[[3]](#references)[[4]](#references)</sup>
Treat the installer identity as provenance, not privilege inheritance: a downloaded APK normally executes under its **own UID and declared/granted permissions**. Do not report execution with the updater's system privileges unless shared UID, platform signing, an exported privileged bridge or another explicit escalation path proves it.<sup>[[3]](#references)</sup>
266
+
267
+
### 5.2 Recovering staged payload families
268
+
269
+
A downloaded file's extension is not a reliable type signal. Start from the loader's reads and deserializer: one observed staged format used a one-byte string key, a four-byte floating-point value reused as an XOR key, and then encrypted DEX bytes. Embedded droppers may also split ciphertext into blocks and derive each single-byte key linearly (`key_i = (key_0 + i * step) & 0xff`). Reimplement the exact loop, deserialize the recovered metadata, and validate output with DEX/ZIP magic before decompilation.<sup>[[3]](#references)</sup>
270
+
271
+
Predictable version strings in payload URLs are also an analysis surface. If a captured path contains a directly editable value such as `dex3.68.png`, enumerate nearby versions **only in an authorized sinkholed/lab copy**, then record HTTP status, hash, decoded magic and entry point. Diff recovered versions for header-layout, decoder, C2, class/method and capability changes; a decoder change in an older payload can reveal a previously unknown intermediate loader.<sup>[[3]](#references)</sup>
272
+
273
+
### 5.3 Configuration-driven reflective modules
274
+
275
+
Look beyond hard-coded command handlers. A compact implant can receive integer task IDs, fetch JSON definitions only for unknown or newer timestamped versions, and persist them in `SharedPreferences`; a field such as `tagName` then selects handlers for HTTP, WebView/JavaScript or module loading. During analysis, dump the preferences XML and correlate ID/version changes with descriptor-fetch requests and reflective calls.<sup>[[3]](#references)</sup>
276
+
277
+
For module loaders, trace attacker-controlled `url`, module name, entry class, factory/virtual method, typed arguments, cleanup list, thread and reload flags. An MD5/SHA value delivered in the **same attacker-controlled task object** as the payload URL detects corruption but does not authenticate code: the operator controls both values. Successful reflection gives replaceable code execution in the implant process and permission context.<sup>[[3]](#references)</sup>
278
+
279
+
### 5.4 Platform changes that change exploitation
253
280
254
281
- Apps targeting Android 14 (API 34+) must mark dynamically loaded DEX/JAR/APK files read-only as soon as they are opened and before content is written; otherwise the system throws an exception when the app later tries to load them.<sup>[[2]](#references)</sup>
255
282
- Apps targeting Android 17 (API 37+) extend the same Safer Dynamic Code Loading rule to native libraries loaded with `System.load()`; writable copied `.so` files now fail with `UnsatisfiedLinkError`.<sup>[[2]](#references)</sup>
@@ -279,5 +306,7 @@ Also consider stubbing vendor methods such as `PluginVerifier.verifySignature()`
279
306
280
307
-[1][NowSecure – Remote Code Execution Discovered in Xtool AnyScan App](https://www.nowsecure.com/blog/2025/07/16/remote-code-execution-discovered-in-xtool-anyscan-app-risks-to-phones-and-vehicles/)
281
308
-[2][Android Developers – Dynamic Code Loading (risks and mitigations)](https://developer.android.com/privacy-and-security/risks/dynamic-code-loading)
309
+
-[3][MoYu Malware Turns Android Car Head Units into Proxy-Botnet Nodes](https://securelist.com/android-head-unit-malware/121106/)
0 commit comments