Memory Forensics of Insecure Android Inter-app Communications

Mark Vella and Rachel Cilia Department of , University of Malta, Msida, Malta mark.vella, rachel.cilia.13 @um.edu.mt { }

Keywords: Mobile Systems Security, Android Memory Forensics, Capability Leaks.

Abstract: Android is designed in a way to promote the implementation of user task flows among multiple applications inside mobile devices. Consequently, app permissions may be leaked to malicious apps without users noticing any compromise to their devices’ security. In this work we explore the possibility of detecting insecure inter- app communications inside memory dumps, with forensic analysis results indicating the possibility of doing so across the various layers of Android’s architecture. Yet, for the detailed evidence reconstruction that could be required during digital investigation, current capabilities have to be complemented with evidence collected through live forensics. We propose that this should still be based on carving forensic artifacts directly from memory.

1 INTRODUCTION live forensics approach would be necessary. There- fore we conclude this work (section 6) with a propo- sition that relies on collecting evidence directly from Android, the most popular mobile device operating live memory on-demand, using runtime patching. system, is designed in a way to both isolate poten- tially security-critical apps from each other as well as to have apps seamlessly delegate their functional- ity to third-parties (Elenkov, 2014). Clearly these two 2 ANDROID INTER-APP design objectives are at odds, leading to various in- COMMUNICATION secure inter-app communication links such as when vulnerable apps leak their legitimately granted privi- Android apps are composed of classes that extend leges to malicious ones, known as capability leaks. In framework components, namely: activities (app win- this work we begin to explore how to expose inter-app dows), services (long running, mostly background, links directly from physical memory; which is a tech- code), broadcast receivers (handlers of device-wide nique that does not have to rely on possibly tampered events) and content providers (shared data reposito- code, and which successfully executing malware can- ries); eventually fleshed out with application logic not evade. The value proposition is that of increased that makes use of Android system services, e.g. mes- systems security of Android-powered mobile devices. saging, telephony, Internet-access, location services Android’s Binder is the inter-process communica- and so on (Gargenta, 2012). The first three of these tion mechanism through which all inter-app links are components are activated through intents whilst the established (section 2). Code comprehension is uti- latter through content resolvers. lized to predict the relevant forensic artifacts across Intents are application framework constructs rep- Android’s architectural layers (section 3). Our pri- resenting the ‘intent’ion of an application component mary contribution lies in proposing a memory dump to provide some functionality. Intent-servicing com- parsing algorithm for each layer (section 4) and sub- ponents can even be exported for use by external ap- sequently used to verify artifact suitability through plications, thereby constituting a primary IPC con- forensic analysis (section 5). Results show that by struct. Explicit intents identify specifically the target combining artifacts identified within different sec- apps hosting the activities/services to be activated in tions of memory, all types of inter-app links can be correspondence to the specified intent action (listing disclosed from memory dumps despite varying de- 1). On the other hand, implicit intents only identify grees of reliability. However for the level of detail the action and possibly some other attributes (listing that may be required during digital investigation, a 2). In this case Android takes care of routing them to

481

Vella, M. and Cilia, R. Memory Forensics of Insecure Android Inter-app Communications. DOI: 10.5220/0006215504810486 In Proceedings of the 3rd International Conference on Information Systems Security and Privacy (ICISSP 2017), pages 481-486 ISBN: 978-989-758-209-7 Copyright c 2017 by SCITEPRESS – Science and Technology Publications, Lda. All rights reserved

ICISSP 2017 - 3rd International Conference on Information Systems Security and Privacy

those apps that would have declared interest in servic- missions, also have the sufficient privilege level ing them during install time, also possibly asking the to access the device’s contacts (e.g. by calling user to choose between multiple such candidate apps. Context.checkCallingPermission()). Otherwise On the other hand, content resolvers provide access to a capability leak is said to occur whenever an unpriv- external content providers. ileged app obtains contacts through it (Zhang et al., 2016). In this work we focus specifically on Intent- Listing 1: Explicit intents are used to launch activities or derived leaks, given that content resolvers should nor- services inside external applications. mally be used to directly access system/external data //Starting an external activity: repositories only, rather than potentially permission- PackageManager pm = t h i s .getPackageManager() ; leaking code. t r y { Listing 3: Vulnerable app’s AndroidMainfest.. Intent it = pm.getLaunchIntentForPackage(” com.example.mvella. eiserver”); 1 i f ( n u l l != i t ) t h i s .startActivity(it); .. 2 4 intent .setComponent( new ComponentName(”com. 5 ...SNIP... example.mvella. eiserver”, ”com.example. 6 7 startService(intent); − 8 9 various possible qualifiers. − 10 startActivity( Intent ( Intent .ACTION VIEW , Uri . new 11 parse(”http ://www.google.com”))); 12 . . . SNIP . . .

2.1 Capability Leaks 2.2 Related Work

Intents and content resolvers are core Android appli- While preventable both from secure coding and per- cation development constructs encouraging inter-app mission enforcement hardening stances (Zhang et al., functionality and data sharing, providing the required 2016), capability leaks are still bound to happen in support for user task flow implementation across mul- existing devices due to the difficulty concerned with tiple apps. A number of system intents are in fact complete eradication of vulnerabilities. We focus made available by the Android framework itself and on the provision of graceful recovery using memory are expected to be serviced by pre-installed/default forensics. Robust memory acquisition from Android apps e.g. picture viewers, instant messaging, and tele- devices has been explored extensively (Sylve et al., phony. The transition from one app to another can 2012). This body of knowledge underpins the LiME be so seamless that it may not be even noticed by acquisition tool utilized in this work. Memory ac- the device user. Since Android makes sure to iso- quisition differs from disk image acquisition since late Android apps from each other as well as from the address bus space in typical microprocessor ar- sensitive device services (e.g. telephony and net- chitectures is not exclusive to physical RAM, but is working), a permissions system is used to relax the rather shared with all memory-mapped hardware de- level of isolation in a controlled manner (Elenkov, vices. Erroneously reading from non-RAM addresses 2014). System permission requests are declared in- compromises system integrity. This same issue could side manifest files (app package meta-data) through however be leveraged by malware to evade memory the uses-permission tag. acquisition (Stuttgen¨ and Cohen, 2013). Mobile de- Listing 3 (lines 3-4), for example, requests vice forensics is challenging even at secondary stor- read/write access to the device’s contacts. Yet, it age level due to the variety of available custom hard- is the responsibility of the app developer to check ware (Kong, 2015). However, the wide-spread adop- that external apps activating the updateContacts tion of Android creates an opportunity for a common service (line 6) through the ACTION START in- source of in-memory forensic evidence. In this work tent (line 8) and that makes use of these per- we focus specifically on Android Binder and which

482 Memory Forensics of Insecure Android Inter-app Communications

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

483 ICISSP 2017 - 3rd International Conference on Information Systems Security and Privacy

App 1 system_server App 2 Access System Service Telephony/Sms svc., Activities Activity1 Start App/Service Activity Manager svc., BroadcastReceivers Android Location/Audio svc.,... Content Providers Framework Services Layer Send message/ remote call Service/Messenger proxies Service/Mes senger stubs android.os.Binder Android. os.Binder

libart.so JNI mediate JNI libandroid_runtime.so servicemanager Android handles service libbinder.so /dev/ashmem user Middleware libbinder.so, libcutils.so registration/lookup memory mapping Layer Shared mem. create Register as /dev/binder kernel Context Manager binder transaction memory mapping -lookup service, binder transaction - make RPC -register service -send ashmem fd ioctl()

shared memory map Linux (modified) (app1 + app2) Binder driver ashmem Kernel Binder transaction delivery Layer Kernel with kernel-to-user memory mapping

Figure 1: Android inter-app communication is implemented by Android’s Binder with support from Android shared memory. the Binder framework. The Binder driver needs to the Binder book-keeping structures perform sufficient book-keeping so that remote ob- (drivers/staging/android/binder.c) have jects can be registered with it, and then have client been identified as a linked list of binder proc and apps look them up to obtain a handle for them and associated structures, and which can be located through which perform remote calls. Given that both through the binder procs global variable. These these operations are sensitive a central process, ser- structures keep track of the processes hosting re- vicemanager, mediates between all processes and the motely accessible objects, binder objects, and the Binder driver. This process is called the Context Man- threads servicing the inter-process request/replies ager, and only one process can be registered as such. among others. Additionally, the well-known Linux Communication between processes and serviceman- linked list of task struct (Mauerer, 2010) and ager still occurs through Binder RPCs, and to which associated structures is required to recover the virtual a specially reserved handle (0) is utilized. Whenever memory sections of individual Linux processes enabled, Binder driver’s book-keeping structures are hosting app components. This linked list can be dumped to debugfs (/sys/kernel/debug/binder located using the init task global variable. file-system path). One layer upwards, the middleware, it is ex- pected that Parcels containing binder transaction (Android RPC calls) data intended for the Activ- ity Manager service can be identified through the 4 MEMORY DUMP PARSERS android.app.IActivityManager length-encoded wide character string. Specifically, serialized intents All three parsers take a dump of physical memory within such parcels include the package and com- as input along with an androidBinderProfile ob- ponent names of the targets in addition to target- ject. This is an abstract data object that contains: the intended data arguments. They are created on the virtual addresses of global variables; data structure client-side’s process heap and eventually get copied offsets; and an initial Directory Table Base (DTB) to a location inside kernel memory that in turn would (CR3 register value). This last value is the all- already have been mapped inside the target process as important offset inside the physical memory dump /dev/binder during the binder object’s creation. for the page table directory which is used for virtual- Target app component identifiers and arguments to-physical address translation of kernel memory. in turn would be stored inside ART’s own heap at the Specifically, androidBinderProfile is used by the framework layer during intent creation (for e.g. listing getKernelAddressSpace() function which recre- 1). ates the kernel’s virtual address space. Algorithm 2 shows the framework-layer parser. It At the kernel layer (Algorithm 1) takes the additional /data/system/packages.xml

484 Memory Forensics of Insecure Android Inter-app Communications

Algorithm 1: Kernel-layer parser. just the memory sections corresponding to ART’s heap, i.e. the ones corresponding to device file maps androidMemDump, androidBinderProfile input : /dev/ashmem/ output: Per-app binder object references prefixed with . The algorithm for the middleware layer is similar, with the main task struct aTaskStruct; difference being that this time it is the process heap hashmap procNameMap; binder proc aBinderProc; (delimited by task struct.mm->start brk binder node aBinderNode; and task struct.mm->brk start/end ad- binder ref aNodeRef; dresses) and the /dev/binder memory sec- kernel addsprace LinuxAS tions that are scanned for content tagged with getKernelAddressSpace(←androidMemDump, android.app.IActivityManager wide character androidBinderProfile); strings. aTaskStruct traverseLinkedList(LinuxAS, foreach Algorithm 2: Framework-layer parser. androidBinderProfile←, global addr=“init task”, datatype=“task struct”) do input : androidMemDump, androidBinderProfile, procNameMap packages.xml [aTaskStruct.pid] aTaskStruct.comm; output: Per-app intent/content provider-related strings ← end task struct aTaskStruct; foreach aBinderProc buffer heapBuffer; ← Array packageArray traverseBinaryTree(LinuxAS, androidBinderProfile, ← global addr=“binder procs”, getPackageList(packages.xml); datatype=“binder proc”) do String packageName; output(“process pid & name:”, aBinderProc.pid, String match; procNameMap [aBinderProc.pid]); kernel addsprace LinuxAS ← foreach aBinderNode getKernelAddressSpace(androidMemDump, traverseBinaryTree(← LinuxAS, androidBinderProfile); androidBinderProfile, addr=aBinderProc.nodes, foreach aTaskStruct traverseLinkedList(LinuxAS, datatype=“binder node”) do androidBinderProfile←, global addr=“init task”, output(“node id:”, aBinderNode.debug id); datatype=“task struct”) do output(“referenced by:”); output(“App: ”, aTaskStruct.comm, “pid: ”, foreach aNodeRef aTaskStruct.pid); traverseLinkedList(← LinuxAS, heapBuffer getAndroidRuntimeHeap(LinuxAS, aTaskStruct←.mm , aTaskStruct.mm pgd, androidBinderProfile, → → addr=“aBinderNode.refs”, mappingid=“/dev/ashmem/dalvik*”); datatype=“binder ref”) do foreach packageName (packageArray output(aNodeRef.proc.pid, procNameMap android,aTaskStruct←.comm ) do [aNodeRef.proc.pid]); \{ } foreach match end scanWideCharStr(← heapBuffer,packageName) end do end output(“Match: ”, match); end to assist searching for all wide character strings that end include an app package name. Effectively this is a end signature that takes advantage of the fact that package names are used as name-spaces for intent arguments. The framework’s android package and the package for the current app being analyzed are excluded given 5 PRELIMINARY RESULTS that no inter-app links are concerned. Directory table Experimentation was carried out on a system im- addresses for individual processes are obtained from age created using Android 6.0.0 (Marshmallow - API task struct.mm->pgd. This is the offset inside the level 23) and a kernel v3.4 image modified to support physical dump used by getAndroidRuntimeHeap() kernel modules. Prototype implementations of the to reconstruct ART’s heap. The memory sec- memory parsers were developed for the Volatility tions for each process are locatable through 2.5 memory forensics framework and utilize the the task struct.mm->mmap linked list of LiME memory extractor kernel module. vm area struct structures inside the kernel space. Table 1 shows the forensic analysis results ob- vm area struct.vm file->f path.dentry-> tained for the six IPC configurations, with debugfs d iname is the final memory lookup required to filter providing a live forensics baseline. As expected,

485 ICISSP 2017 - 3rd International Conference on Information Systems Security and Privacy

Table 1: Memory forensic analysis results.

IPC debugfs Kernel Middleware Framework Explicit intent - Start activity × × × X Explicit intent - Start service × × × X Explicit intent - Bind service (messaging) X X × X Explicit intent - Bind service (RPC) X X × X Implicit intent - Start activity × × × X Implicit intent - Send broadcast × × × X its effectiveness in uncovering IPC matches the ker- while at the same time verifying Binder’s integrity. nel layer dump parser and which corresponds to ap- This idea can extend to include adaptive permission plications communicating directly with each other. enforcement, whereas the user could be prompted to On the other hand, apps communicating indirectly consciously either patch the vulnerable app, or even through Activity Manager are fully detectable only at elevate the privilege level of the caller app in case of the framework layer. The middleware layer, Android false positives. Binder’s user-level code, misses out on all of them through a design that favors immediate transaction recycling. The memory parsing prototype was then REFERENCES extended into a full capability leak detector, with on- device app package dumping and reversal (using apk- Anglano, C., Canonico, M., and Guazzone, M. (2016). tool). This procedure enables disclosure of the apps’ Forensic analysis of the chatsecure instant messaging requested permissions and consequently the identifi- application on android smartphones. Digital Investi- cation of inter-app links that cross privilege bound- gation, 19:44–59. aries. Its detection capability was demonstrated using Artenstein, N. and Revivo, I. (2014). Man in the Binder: a case study app that leaks its contacts permissions He who controls IPC, controls the droid. In Europe BlackHat Conf (manifest shown in listing 3 ) by not performing any . privilege checks on the caller apps. Elenkov, N. (2014). Android Security Internals: An In- Depth Guide to Android’s Security Architecture. No Listing 4: Memory artifacts disclosing the suspicious inter- Starch Press. app link. Gargenta, A. (2012). Deep dive into Android IPC/Binder framework. In AnDevCon: The Android Developer App: com.example.mvella.malapp Conference. p i d : 822 ==> com.example. mvella .vulnapp. action .INSERT Kong, J. (2015). Data extraction on MTK-based Android ==> com.example. mvella .vulnapp# mobile phone forensics. Journal of Digital Forensics, ==> com.example.mvella.vulnapp. updateContacts Security and Law, 10(4):31–42. ==> com.example. mvella . vulnapp . extra .NAMEp# Mauerer, W. (2010). Professional architecture. ==> com.example.mvella.vulnapp. extra .TEL John Wiley & Sons. ...SNIP Stuttgen,¨ J. and Cohen, M. (2013). Anti-forensic resilient memory acquisition. Digital investigation, 10:S105– S115. Sylve, J., Case, A., Marziale, L., and Richard, G. G. (2012). 6 CONCLUSION Acquisition and analysis of volatile memory from An- droid devices. Digital Investigation, 8(3):175–184. While valuable, the current detector cannot identify Zhang, D., Wang, R., Lin, Z., Guo, D., and Cao, X. (2016). specific targets of implicit intents whenever multiple Iacdroid: Preventing inter-app communication capa- target apps are possible. It also lacks details of the ex- bility leaks in android. In ISCC, 2016 IEEE Sympo- act IPC sequences to support in-depth investigations sium on, pages 443–449. IEEE. since it is restricted to operate just upon instantaneous memory snapshots. This can be achieved through run- time patching of ARM/Intel atom machine instruc- tions by adding an Android middleware layer pro- cess that leverages ptrace to load runtime memory forensics patches supplied over network connections or removable flash memory. This security-critical process should be protected through an appropriate SELinux policy, with only vendor/approved foren- sic investigator-signed code patches being accepted

486