The question has popped up on Stack Overflow a few times: how the heck does Parallel Space do what it is doing?
Parallel Space allows the user to have N copies of your app, each with its own portion of internal storage. The user could then register as Foo in one copy and Bar in another, and use each copy of the app independently. This does not require Android for Work, Samsung KNOX, or any other hardware-supplied partitioning system – Parallel Space is just an ordinary Android app.
LBE Tech, the firm behind Parallel Space, has not said much about how they do it, other than it involves “MultiDroid, the first application virtualization engine on Android”. And I have never used Parallel Space personally, let alone attempted to examine it (though others have).
My guess is that this is a commercialization of Boxify, or at least an implementation of the same concept.
If somebody asked us what our Android apps run on, our initial response might be “ummmm… Android?”, as the answer seems obvious.
However, most apps do not really interact much with Android, the OS, directly.
When you get past all the Java, most things in Android eventually hit one of two things:
an IPC call using Binder, which covers everything from system services to starting activities
a native call to a JNI-style C/C++ library linked into our app, including many such calls that come from framework code
Boxify, in effect, proxies both of those through its own app.
The details are in the Boxify paper. In a nutshell, Boxify:
Forks a process
Loads your APK into that process
Replaces a lot of system service implementations, like
PackageManager, with its own implementations that route the IPC through Boxify
Uses “syscall hooking” to replace necessary system calls with others that, again, route through Boxify
Runs your tweaked-in-memory app (notably, nothing Boxify does requires modifying the APK itself)
So, for example, let’s think about disk I/O. Usually, we find out where to write by
calling methods on
Environment. Those, in turn, wind up returning
paths supplied by Boxify. When you try to open a
FileInputStream or something,
the Linux syscalls triggered by that I/O also route through Boxify, as it
android:isolatedProcess to carefully manage what capabilities the
APK can actually perform, and so your app would not be able to write to
Boxify, itself, was written as a proof of concept for running apps in dedicated sandboxes, particularly for “untrusted apps”, to use the authors’ term.
However, this sort of virtualization technique – Android apps running inside other Android apps, for an Inception-style experience – requires that you trust the virtualization engine. After all, by definition, it can see all I/O between the app and Android, as it proxies all of that I/O. It is a MITM attack on the app.
I have little doubt that such virtualization can be put to plenty of positive uses. At the same time, I sincerely hope that Google and independent security researchers examine any such virtualization app, to “trust, but verify”, to use the Reagan-era maxim.
However, this illustrates yet another way – on top of custom ROMs, emulators, and related tricks – where a user can arrange to run your app in an environment that the user controls more than they do a standard Android environment. That, on top of standard rooting techniques, further emphasizes that you cannot defend yourself from the user. DRM solutions and related techniques are difficult to secure when the user controls the entire environment around your app. Treating the user as the enemy might work for a majority of users, but those who might really be your enemy may well be able to work around whatever DRM-style protections you add. These protections resemble the Maginot Line: strong defenses against predictable attacks that may prove useless with a nimble adversary. IMHO, you are better served finding a business model that does not require you to treat the user as the enemy.