// HackTricks · Mobile

Android Application-Level Virtualization (App Cloning)

Android Application-Level Virtualization (App Cloning)

Application-level virtualization (app cloning/container frameworks such as DroidPlugin-style loaders) can run one or more APKs inside a host that controls lifecycle, class loading, storage, and permission mediation. In frameworks where guests execute under the host UID, Android’s normal per-package UID isolation is collapsed; this behavior must be verified for the specific container rather than assumed for every cloning product.[1][2]

Baseline install/launch vs virtualized execution

  • Normal install: Package Manager installs an APK under an implementation-specific randomized /data/app/ path, assigns an application UID, and Zygote normally forks a process that loads the app’s classes.dex code. Historical layouts commonly resembled /data/app/<random>/com.pkg-<random>/base.apk; do not hardcode that shape on newer releases. Apps explicitly configured to share an identity are an exception to the one-package/one-UID simplification.[2]
  • Dex load primitive: DexFile.openDexFile() delegates to openDexFileNative() using absolute paths; virtualization layers commonly hook/redirect this to load guest dex from host-controlled paths.[1]
  • Virtualized launch: Host starts a process under its UID, loads the guest’s base.apk/dex with a custom loader, and exposes lifecycle callbacks via Java proxies. Guest storage API calls are remapped to host-controlled paths.[1]

Abuse patterns

  • Permission escalation via shared UID: Guests run under the host UID and can inherit all host-granted permissions even if not declared in the guest manifest. Over-permissioned hosts (massive AndroidManifest.xml) become “permission umbrellas”.
  • Stealthy code loading: Host hooks openDexFileNative/class loaders to inject, replace, or instrument guest dex at runtime, bypassing static analysis.
  • Malicious host vs malicious guest:
    • Evil host: acts as dropper/executor, instruments/filters guest behavior, tampers with crashes.
    • Evil guest: abuses shared UID to reach other guests’ data, ptrace them, or leverage host permissions.[1]

Fingerprinting & detection

  • Multiple base.apk in one process: A container often maps several APKs in the same PID.
    adb shell "cat /proc/<pid>/maps | grep base.apk"
    # Suspicious: host base.apk + unrelated packages mapped together
  • Hooking/instrumentation artifacts: Search for known libs (e.g., Frida) in maps and confirm on disk.
    adb shell "cat /proc/<pid>/maps | grep frida"
    adb shell "file /data/app/..../lib/arm64/libfrida-gadget.so"
  • Crash-tamper probe: Intentionally trigger an exception (e.g., NPE) and observe whether the process dies normally; hosts that intercept lifecycle/crash paths may swallow or rewrite crashes.[1]

Hardening notes

  • Server-side attestation: Use Play Integrity as one risk signal for sensitive operations, verify tokens on the server, and combine it with account and transaction controls; it is not proof that no runtime instrumentation exists.[3]
  • Use stronger isolation: For supported system components and specialized workloads, Android Virtualization Framework (AVF) provides VM isolation that is materially different from an app container sharing a UID.[4]

References