androiddexclassloader

How to execute APKs on a customized data directory?


I was wondering how Parallel Space app can duplicate and execute other apps without copying their APKs or running them under modified package names like other apps on Playstore do (e.g.: "com.whatever.name-of-duplicated-app").

After investigating their AndroidManifest.xml, the folders created on /data/data/, and the logs on the device, the only conclusion I could get is that somehow Parallel Space is capable of executing the code from other APKs but it maps the data directories of those apps into its own Data Directory.

Evidences:

  1. Directories are created like this: /data/data/com.lbe.parallel.intl/parallel_intl/0/whatever-package-name-you-cloned
  2. Every duplicated app execution begins with a new task of one of their Proxy activities and then somehow the duplicated app takes place of the newly created process.

Initially, I thought it was something with DexClassLoader/PathClassLoader APIs, but I couldn't progress any further with that investigation. I also saw some questions like this one, but it doesn't seem to be the case.


Solution

  • I was analysing the Xiaomi Redmi Note 3 which allows multi-instance apps for whatsapp. What it does is pretty straightforward, it creates another user profile from within the framework to differentiate the two.

    u0_a171   1832  631   1094576 91608 SyS_epoll_ 0000000000 S com.whatsapp
    u999_a171 8571  631   1037396 65024 SyS_epoll_ 0000000000 S com.whatsapp
    

    Parallel space was doing something even more interesting. Before getting into the details, lets analyse the output from ps

    u0_a45    2915  249   1120668 61264 SyS_epoll_ b6ca7010 S com.lbe.parallel.intl
    u0_a45    6876  249   1081464 40588 SyS_epoll_ b6ca7010 S com.google.android.gms.persistent
    u0_a45    6945  249   995016 19828 SyS_epoll_ b6ca7010 S com.google.process.gapps
    u0_a45    11296 1     1220488 22760 futex_wait b6c7a8b0 S com.google.android.gms
    u0_a45    12303 249   1064788 59680 SyS_epoll_ b6ca7010 S com.freecharge.android
    u0_a100   12786 249   699476 45096 jbd2_log_w b6ca6fe8 D com.freecharge.android
    

    Here, I have used Parallel Space to create another account for FreeCharge. So basically if we observe the last two processes, one of them is hosted in the parallel space process ID while the other app is in its own process ID.

    Reverse engineering Parallel Space using apktool and dex2jar the findings were as follows.

    Parallel Space declares 100 Proxy Activities, 100 Proxy Services and 100 Proxy Providers. These are used to host the application which is to be cloned. Hence the cloned app will be within the same process space as Parallel Space. Also it had Android framework stubs from ActivityManager, ServiceManager, AccountManager, LocationManager and many more. Basically when the app is compiled, it creates these classes which are the same as those in framework.jar that comes shipped in with Android devices. Using this Proxy stub and Java reflection, it creates and hosts the app in its own process space. For this it simply intercepts the Activity Manager calls and marshals new information which is then forwarded to the framework.

    It also creates a new directory structure for storing app information within its /data/data/ folder to host the cloned application data.

    The details are immense, the Parallel Space developer have used extensive knowledge from AOSP source code to leverage the behaviour and also leveraged how Java classes are used by using Reflection and Proxies.

    Update:

    Just found the open source version of Parallel space on GitHub. This works exactly on the same principles. Link below.

    https://github.com/asLody/VirtualApp