security-criticality has already been targeted by offen-
sive security studies (Artenstein and Revivo, 2014).
3 ANDROID BINDER
All IPC constructs available to Android app devel-
opers (Gargenta, 2012) are implemented as Remote
Procedure Calls (RPC), with support from Android
Binder and shared memory (ashmem). At the high-
est level of abstraction developers are oblivious of
this detail, however this mechanism presents the focus
for forensics artifact exploration. Figure 1 illustrates
the main components involved in supporting inter-
app links across the framework (Java), middleware
(C/C++) and the (modified) Linux kernel (C) layers
of the Android architecture. A client app (App 1) ac-
cesses various system service (e.g. Telephony ser-
vice) using framework API calls. System service
code actually resides in separate OS processes, most
of which is lumped into system server. Therefore
in actual fact all such calls already constitute IPC.
Moreover, system services may just constitute a step-
ping stone so that App 1 can activate components in-
side another, App 2, and eventually communicating
directly using a Message Queue or an RPC type of
inter-app communication.
We resort to code comprehension in order to for-
mulate predictions about locating and parsing arti-
facts related to inter-app links. This is similar to aca-
demic work performing forensic analysis for on-disk
or in-network traffic artifacts (Anglano et al., 2016).
We made use of Android Open Source Project’s
(AOSP) master branch
1
for this purpose. The com-
prehension exercise mainly consisted of (statically)
tracing execution flow involving components commu-
nicating across app boundaries, and identifying those
data structures useful for forensic event reconstruc-
tion. In this section we summarize the primary bi-
naries involved and a representative cross-application
boundary flow, with specific detail concerning locat-
ing and parsing artifacts presented in the following
one. The primary source code files utilized during
comprehension are shown in parenthesis.
Let’s take the example when Activ-
ity1 inside App 1 sends a message to a
service component exposed by App 2 us-
ing the API Messenger.send(Message
aMsg) method. What happens here is that
aMsg is passed onto the middleware layer
through (android.os.Binder)’s transact()
method by android.os.Messenger stub code
1
https://source.android.com/source/index.html
(core/java/android/os/IMessenger.aidl).
Specifically, using the Android Runtime (ART)’s
(libart.so) Java-Native Interface (JNI) media-
tion, the proxy creates a serialized represen-
tation of aMsg inside the middleware layer
(libs/binder/Parcel.cpp), across a Java-
native link registered by libandroid runtime.so
(core/jni/android util Binder.cpp). Sub-
sequently it is passed onto the Binder frame-
work: libbinder.so (libs/binder/BpBinder.cpp),
that first packages it into a Binder transaction
that conforms to the Binder driver’s proto-
col
2
and then dispatches it to the Binder driver
(drivers/staging/android/binder.c) inside the
kernel using an ioctl() call on the /dev/binder
device file (libs/binder/IPCThreadState.cpp).
The role of the driver is to look up the location of the
requested remote service, the service inside App 2
in this example, and delivers aMsg to it where an
associated thread pool would be blocked awaiting
Binder transactions (in turn from a previous ioctl()
call from libs/binder/IPCThreadState.cpp).
Transaction delivery is completed using a ker-
nel memory region that is mapped to App 2’s user-
space (libs/binder/ProcessState.cpp). In case
of large messages, a faster alternative would be to
only serialize a file descriptor associated with a shared
memory region between App 1 and App 2 (acces-
sible through the /dev/ashmem device file through
libcutils.so). On message delivery completion it is
the Binder framework’s onTransact() method that
gets called first (libs/binder/JavaBBinder.cpp),
eventually calling into android.os.Messenger’s
proxy onTransact() method. The last phase of the
delivery involves in unserializing aMsg and passing
it to the messenger’s handling routine as argument.
In this example Binder’s RPC mechanism is used
to let App 1 and App 2 communicate using a mes-
sage queue abstraction, however it also possible to
use RPC directly, with service proxy/stub code gen-
erated from Android Interface Definition Language
(AIDL) files providing the necessary glue code. This
is the case for example when App 1 calls into sys-
tem server to start a service inside App 2 through a
bindService() API call for example.
The above flow relies on two very important reg-
istries. The first one is the Activity Manager service
that operates at the framework layer and resolves in-
tents based on a number of activity/service/broadcast
records that are registered with it, in turn based on
information derived from the various manifest files
of installed apps. The second registry is part of
2
http://www.angryredplanet.com/˜hackbod/openbinder/
docs/html/BinderIPCMechanism.html
Memory Forensics of Insecure Android Inter-app Communications
483