This paper was converted on www.awesomepapers.org from LaTeX by an anonymous user.
Want to know more? Visit the Converter page.

NatiDroid: Cross-Language
Android Permission Specification

Chaoran Li, Xiao Chen, Ruoxi Sun, Jason Xue, Sheng Wen,
Muhammad Ejaz Ahmed, Seyit Camtepe, Yang Xiang
C. Li, S. Wen, and Y. Xiang are with School of Software and Electrical Engineering, Swinburne University of Technology, Hawthorn, VIC 3122, Australia;
E-mail: {chaoranli, swen, yxiang}@swin.edu.au; X. Chen is with the Department of Software Systems and Cybersecurity, Faculty of IT, Monash University, Clayton, VIC 3800. Australia; E-mail: xiao.chen@monash.edu; R. Sun, and J. Xue are with School of Computer Science, University of Adelaide, North Terrace, SA 5005, Australia;
E-mail: {ruoxi.sun, jason.xue}@adelaide.edu.au; M. E. Ahmed and S. Camtepe are with CSIRO Data61, Australia;
E-mail: {derek.wang, ejaz.ahmed, seyit.camtepe}@data61.csiro.au; Manuscript received April 19, 2005; revised August 26, 2015.
Abstract

The Android system manages access to sensitive APIs by permission enforcement. An application (app) must declare proper permissions before invoking specific Android APIs. However, there is no official documentation providing the complete list of permission-protected APIs and the corresponding permissions to date. Researchers have spent significant efforts extracting such API protection mapping from the Android API framework, which leverages static code analysis to determine if specific permissions are required before accessing an API. Nevertheless, none of them has attempted to analyze the protection mapping in the native library (i.e., code written in C and C++), an essential component of the Android framework that handles communication with the lower-level hardware, such as cameras and sensors. While the protection mapping can be utilized to detect various security vulnerabilities in Android apps, such as permission over-privilege and component hijacking, imprecise mapping will lead to false results in detecting such security vulnerabilities. To fill this gap, we thereby propose to construct the protection mapping involved in the native libraries of the Android framework to present a complete and accurate specification of Android API protection. We develop a prototype system, named NatiDroid, to facilitate the cross-language static analysis to benchmark against two state-of-the-art tools, termed Axplorer [1] and Arcade [2]. We evaluate NatiDroid on more than 11,000 Android apps, including system apps from custom Android ROMs and third-party apps from the Google Play. Our NatiDroid can identify up to 464 new API-permission mappings, in contrast to the worst-case results derived from both Axplorer and Arcade, where approximately 71% apps have at least one false positive in permission over-privilege and up to 3.6% apps have at least one false negative in component hijacking. Additionally, we identify that 24 components with at least one Native-triggered component hijacking vulnerability are misidentified by two benchmarks. We have disclosed all the potential vulnerabilities detected to the stakeholders.

Index Terms:
Computer Security, System Security, Mobile Security.

1 Introduction

Android protects access to restricted data (e.g., the device identifier) and actions (e.g., making phone calls) through permission enforcement [3]. Such an access control model can protect users against snooping and protect the stability and security of the operating system [4]. When an Android app attempts to access the restricted resources, a security check is triggered to inspect whether proper permissions are granted. Lack of permission request will prevent access to the resource and further cease the corresponding functionality or even crash the app. Therefore, it is essential for developers to know the permissions required of the invoked API. Unnecessary required permissions can pose three threats: i) Too many required permissions may confuse users. Users suspect that the app has unexpected behaviors, which leads to users uninstalling or unwilling to install the app. ii) The permissions required by an app is an important feature in detecting Android malware. Unnecessary permissions will fool the detector and cause a false alarm. iii) The app will incur security risks with unnecessary permissions. Once the app contains vulnerabilities that can be injected with tampered code, it is easy for an attacker to thwart user privacy or invoke sensitive APIs. Moreover, requesting unnecessary permissions may expand the attack surface and expose the Android operating system to a host of attacks, especially privilege escalation attacks [5]. Therefore, to safeguard users’ privacy and protect the Android ecosystem, Android app developers are suggested to follow the principle of least privilege, i.e., requesting a minimum set of permissions required to fulfill the apps’ functionality. Unfortunately, Android does not provide official documentation for the permission specifications (i.e., a mapping between APIs and the required permissions), making it difficult for app developers to follow the least privilege rule, and further lead to security vulnerabilities such as component hijacking [6, 7, 8].

To address this problem, researchers have been working on developing methods that generate an accurate list, called a protection map, that maps Android APIs to the required permissions. The previous works that provide such protection maps include Stowaway [5], PScout [3], Axplorer [1], and, most recently, Arcade [2]. Stowaway empirically determines the permissions required in Android APIs using feedback-directed testing. PScout and Axplorer leverage control-flow reachability analysis on the source code of the Android framework to generate the mapping between APIs and permissions. Arcade proposes a path-sensitive method based on graph abstraction techniques to generate a more precise mapping. Dynamic testing methods (e.g., Stowaway) can accurately map the required permissions to API invocations that they have tested; however, such dynamic approaches suffer from an intrinsic shortcoming of low coverage. The existing static analysis based approaches (e.g., PScout, Axplorer, and Arcade) have better coverage but may lead to imprecise results because of improper modeling of the complicated Android communication mechanisms.

Specifically, existing works only analyzed the Java API framework in the Android API Framework, but overlooked the C/C++ Native Library that consists of core Android system components and services (e.g., Camera service, Sensor service). For example, the public method openCamera() in CameraManager.java class implements its permission check (“android.permission.CAMERA”) in the native library CameraService.cpp. Missing native library analysis will mistakenly conclude that the API openCamera() does not require any permissions (one example is detailed in Section 2).

While the API-permission protection mapping contributes to identifying security vulnerabilities in Android apps, such as permission over-privilege [5] (i.e., an app requests additional permissions that are not required) and component hijacking [6] (i.e., an app inappropriately exposes a component with sensitive data), the imprecise mapping will lead to false results on detecting such vulnerabilities. Taking the aforementioned case as an example, an app invokes the API openCamera() will need to request the corresponding permission android.permission.CAMERA; however, existing works that do not analyze the native libraries will identify it as a permission over-privilege case, and henceforce, a false positive.

To address the shortcomings of the existing works, we leverage the cross-language analysis on the overall Android system, including both the Java API Framework and the C/C++ Native Libraries. To this end, we analyze the cross-language communication mechanisms on four Android Open Source Projects (AOSP) and summarize two communication models to facilitate the cross-language analysis. We develop a prototype system, NatiDroid, and generate Native-triggered (i.e., an Android API whose permission check is implemented in the native library) API-permission mappings in AOSP versions 7.0, 7.1, 8.0, and 8.1, which were chosen to benchmark against prior works [1, 2] (see detailed discussion in Section 5.1). In addition to the mappings generated by previous works, Axplorer and Arcade (2,115 and 1,585, respectively, in AOSP 7.0), NatiDroid can successfully discover 449 mappings that are not covered previously. Note that while most Android APIs are Java methods, fewer of them are C/C++ methods. Nevertheless, these native methods play indispensable roles in the Android system, such as interacting with the hardware layer. We further use the new mappings to detect permission over-privilege and component hijacking vulnerabilities on a large dataset containing more than 11,000 Android apps, including system apps from custom Android ROMs and third-party apps from the Google Play. We identify the worst-case scenario, where approximately 71% apps with permission over-privilege detected by Axplorer and Arcade are false positives, as well as both Axplorer and Arcade misidentify 3.6% apps (false negatives) which are vulnerable to hijacking attacks. Additionally, we identify that 24 components with at least one Native-triggered component hijacking vulnerability are misidentified by two benchmarks.

Refer to caption
Figure 1: Android software stack

In summary, we make the following contributions:

  • We design and implement a prototype system, NatiDroid, to facilitate cross-language control-flow analysis on the Android framework. To the best of our knowledge, this is the first work to enable cross-language analysis on the Android framework. By incorporating NatiDroid with existing Java-side permission mappings (e.g., Axplorer or Arcade), we obtain a complete permission mapping that covers the entire Android system. We make our system and results publicly available to benefit researchers and practitioners.111The source code is available at https://natidroid.github.io/.

  • We apply NatiDroid to extract the permission-API protection mappings from the native libraries on four AOSP versions (7.0, 7.1, 8.0, and 8.1). We show that 12 permissions, including 8 signature and 2 dangerous permissions, are determined to be enforced in native libraries, which are not covered by two state-of-the-art benchmarks, Axplorer and Arcade.

  • We analyze Android apps for permission over-privilege and component hijacking vulnerabilities at a large scale. Our results show that NatiDroid is effective in identifying vulnerable Android apps. We have identified approximately 71% false positives in terms of the number of the apps with at least one permission over-privileged and up to 3.6% false negatives in terms of the number of the apps with at least one component hijacking, a worst-case scenario reported by Axplorer and Arcade.

We hope that the proposed system, NatiDroid in this paper could bridge the gap between Java- and Native-sides analysis (see Figure 1), rendering the static analysis of the overall Android framework to be complete and accurate.

2 Background and Motivation

This section provides background information on how Android OS operates and explains the limitations of the existing static API protection mapping generation techniques that motivate our work.

Android framework.  Android framework consists of the Java API Framework layer and C/C++ Native Library layer (i.e., the second and the third layers from the top in Figure 1). The Java API Framework layer offers Application Programming Interfaces (APIs) written in the Java language for Android app developers to access Android features and functionalities. The Java framework access the device hardware capabilities, such as the camera and sensors, via the C/C++ Native Library layer. When a Java framework API (e.g., the Camera Manager in Figure 1) invokes a call to access device hardware, the Android system loads corresponding library module (e.g., the Camera Service) for that hardware component.

Android permission model.  When an app needs to use any of the protected features of an Android device (e.g., accessing the camera, sending an SMS, making a phone call), it must obtain the appropriate permission(s) from the user. When an Android API is called, the Android framework checks whether it is protected by any permission. Most of such permission checks are defined in the Java API Framework layer in the Android system, while there are yet a number of them defined in the C/C++ Native Library layer.

Existing works [3, 1, 2] leverage static analysis on the Java API Framework layer of the Android framework to extract the mapping between APIs and corresponding permission checks. Ignoring the invocation of native libraries miss the permission checks in the native libraries, leading to incomplete mapping results.

Refer to caption
Figure 2: Motivation example derived from a real-world Android app vStudio.Android.Camera360. The code is simplified for better illustration.

Motivating example.  We further elaborate on our motivation with a real-world example illustrated in Figure 2. The code from lines 1 to 10 is derived from a popular photography app vStudio.Android.Camera360 [9] on Google Play. The app initialises a CameraManager instance (line 4), and opens the camera instance by invoking openCamera() method (line 8). The invocation chain then traverses along the call path through an Android SDK class CameraManager.java (lines 11 to 18) and a native library CameraService.cpp (lines 19 to 32), and finally triggers a permission check in the native library (line 28). Note that the cameraService.connectDevice() (line 18) communicates with the CameraService::connectDevice() (line 20) in a cross-language way (marked as purple). The security check examines if the method is called by its own process (i.e., cameraservice, hence, no permission is required) or the corresponding permission android.permission.CAMERA is granted. If neither it is called from its own process, nor the android.permission.CAMERA permission is granted, a permission denied error is returned (line 30), which will further prevent openCamera() to be executed. This example implies a protection mapping from the Android API, CameraManager.openCamera(), to its permission protection check, {android.permission.CAMERA || callingPid == getpid()}.222Some if-then-else statements are omitted in line 27 of Figure 2 for better illustration; consequently, the protection mapping only reflects the simplified code as shown in Figure 2. The complete protection mapping for openCamera() can be found in our open source repository.

Unfortunately, as existing works only analyzed the Java source code in the Android framework, they miss the permission checks implemented in the native libraries. For instance, the mapping of the API CameraManager.openCamera() to the permission android.permission.CAMERA, as shown in the example, does not exist in the state-of-the-art works, such as PScout [3], Axplorer [1], or Arcade [2]. The incompleteness of the mapping results further introduces false results in detecting security vulnerabilities, such as permission over-privilege [5] and component hijacking [6] (detailed in Sections 4.2.1 and 4.2.2, respectively).

Refer to caption
Figure 3: An overview of NatiDroid system

3 Approach

We propose and implement a prototype system, NatiDroid, to address the cross-language protection mapping problem that has long been overlooked in previous works. Figure 3 illustrates the overall design of NatiDroid. As depicted, NatiDroid contains three modules. The Pre-processing module prepares the intermediate artifacts for analyzing the Android framework and native libraries, such as intermediate .jar files (for Java-side analysis) and Clang compile commands (for Native-side analysis). The Entry-points identification module summarizes two cross-language communication models used in the Android framework, and identifies the entry-points for both Java- and Native-sides analysis. The Cross-language Control Flow Graph (CFG) analysis module constructs the cross-language CFG and extracts the permission mapping.

We propose a complete solution for extracting Native-triggered permission mapping from the Android system. We leverage Soot [10] and Clang [11] static analysis frameworks, although our solution is also applicable to other static analysis frameworks. Soot is a popular Java optimization framework for analyzing and visualizing Java and Android apps, which has been widely used in various projects for static analysis [3, 12, 13]. Clang is a lightweight compiler for C language family. We use Clang to transform C/C++ code to the Abstract syntax tree (AST) [14]. Additional code for implementing NatiDroid consists of approximately 7kLOC. We detail the design and implementation of each module in the following subsections.

3.1 Pre-processing

Due to the complexity and cross-language nature of the Android framework, there is no off-the-shelf tool for static analysis of the Android framework (i.e., Java API Framework and Native Library) as a whole. NatiDroid leverages the divide-and-conquer strategy to facilitate the Java- and Native-sides analysis. However, there are still non-trivial tasks to prepare the AOSP codebase for the static analysis. Hence, in this module, we prepare the intermediate artifacts from the AOSP codebase, which are required to enable the Java- and Native-sides analysis. Note that the pre-processing module includes most engineering works, which is not considered our technical contribution. However, it is essential to facilitate the proposed cross-language analysis.

Java-side analysis preparation.  NatiDroid’s Java-side analysis takes compiled .jar file as input. However, to maintain the stability of the Android system, some non-SDK class and method bodies are hidden using the @hidden Javadoc tag (e.g., non-SDK Android APIs that may be changed in the future versions without noticing the app developer) during the building of android.jar from source code. The hidden classes and methods only expose the method name, parameters, return values, and minimum set of statements required to handle the invocation, which is not sufficient for constructing a complete CFG. We therefore retain the intermediate output during the compilation, i.e., the intermediate .jar files that have not been combined as android.jar. These intermediate .jar files, such as services.com.intermediates.jar, have the complete class and method information sufficient for facilitating static analysis.

Native-side analysis preparation.  Before we build the cross-language CFG (cf. Section 3.3), we leverage Clang to transform C/C++ source code to AST. A complete set of Clang compile command is required to enable the static analysis, however, is not provided in Android documentation. Android uses the ninja to build system [15]. During the compilation process, the .ninja files containing ninja build commands are generated by the compiler. However, the commands obtained from .ninja files consist of file operations and a mixture of GNU Compiler Collection (GCC) and Clang commands, which are not compatible with the off-the-shelf Clang-based analyzer. We then develop a system (to 500 LOC) to extract and pre-process the required commands from these files. The functions of the system include merging separated ninja commands and replacing the Clang++ commands with Clang commands (i.e., adding C++ headers in Clang command’s parameters).

Refer to caption
Figure 4: AIDL communication model. The Java-side caller invokes remote method from Native-side.

3.2 Entry-Points Identification

Recall that the overall idea of generating a protection mapping is to examine whether the invocation of an API will trigger a permission check in the Android framework (i.e., if there is a permission check node in the CFG starting from the API call). Due to the complexity of the Android framework, building a CFG of the overall framework is neither practical nor efficient. As NatiDroid’s goal is to complement the existing mappings, such as Axplorer and Arcade, by adding the protections whose permission checks are located in the native libraries, we only generate sub-CFGs for the Android APIs that involve cross-language communication. The first step to generate sub-CFGs is to identify the entry-points of the graphs (for both Java- and Native-sides). To this end, we first summarize two cross-language communication mechanisms used by Android.

Refer to caption
Figure 5: An example of AIDL-based cross-language communication model. The code snippets are simplified for better illustration.

AIDL-based communication model. The Android operating system (OS) is based on Linux but does not inherit the Inter-Process Communication (IPC) mechanism of Linux. In Android, resources between processes are not shared. Android Interface Definition Language (AIDL) is one of the IPC mechanisms that Android adopted to enable communication for remote invocation, providing cross-process or even cross-language communication. Figure 4 depicts the workflow of AIDL-based client-service model, where the Java framework works as a client requesting service from the native library. AIDL utilizes a pair of Stub/Proxy classes on Java-side to communicate with native libraries. The Proxy is responsible for sending requests to native service and implementing the remote method which invokes the transact() method and communicates with Native-side, while the Stub class, inheriting the Binder class, transforms service Binder and receives the reply from native service using the method onTransact(). The transact() and onTransact() are synchronous, such that a call to transact() does not return until the target has returned from onTransact().

On Native-side, it is unnecessary to generate Stub/Proxy pairs, but directly implements the remote method (using the name as same as the remote method on Java-side) to handle the request from Java-side, so that we can always find the receiver onTransact() and the same name remote method as the AIDL sender. Through using pairs of onTransact() and transact() methods as sender and receiver on both sides, the communication between Java- and Native-sides is established. Therefore, cross-language interaction can be detected via matching the use of AIDL on Java- and Native-sides (e.g., the Stub/Proxy pair, the onTransact() methods, and the implementation of the remote methods and the transact() methods). We can then determine the entry-points for static analysis accordingly.

An example of AIDL mechanism is shown in Figure 5, where the method getCameraInfo() uses AIDL to implement the communication between Java and C++. A pair of a sender and a receiver on each side of AIDL (i.e., the client and the service) handles the cross-language communication. The caller (line 3) invokes the method getCameraInfo() which is firstly defined as an interface in line 6 and then implemented in line 16 (the detailed implementation is omitted). In the corresponding native library (lines 21 to 34), the receiver onTransact() handles the request and further invokes the method getCameraInfo() (line 30). The getCameraInfo() method then executes the method implementation and sends the execution result back to the Java-side onTransact() method (line 10), which is further passed back to the caller (line 3). Note that the getCameraInfo() in line 6 and the getCameraInfo() in line 23 are the two interface methods that both invoke the transact() method (omitted) to establish the communication between Java- and Native-sides. The NatiDroid will match the pair of such remote methods and recognize them as a pair of Java entry-point and native entry-point. Note that, for the inner-language AIDL communication on both Java- and Native-sides, NatiDroid generates CFG with a similar approach, except for the identification of entry-points.

Refer to caption
Figure 6: JNI communication model. Java- and Native-sides communicate with JNI.

JNI-based communication model. Java Native Interface (JNI) provides a cross-language interface between Java and Native code (written in C/C++). This enables developers to write native methods to handle situations when an app cannot be written entirely in the Java programming language, e.g., when the standard Java class library does not support the platform-specific features or program library, such as communication with the underlying hardware. In the JNI framework, native functions are implemented in .c or .cpp files. When invoking the function, it passes a JNIEnv pointer, a jobject pointer, and any Java arguments declared by the Java method.

Figure 6 shows the JNI-based communication model adopted by Android. Android uses the JNI Dynamic Register to link native methods. Different from the AIDL model, the JNI-based communication starts from a registration process. When Android starts running, the AndroidRuntime class uses the startReg() method to start the registration of JNI methods, which will further invoke all JNI registration functions implemented in the native libraries. The registration functions will register native methods with the corresponding Java class specified by an array of JNINativeMethod structures that contains the Java method name, Java method signature, and pointers to the native function. After the registration process, all the JNINativeMethod (on Native-side) is registered and linked to the corresponding Java method in the Java Virtual Machine (JVM).

We further explain the JNI-based communication mechanism with an example given in Figure 7, which is derived from android_hardware_Radio.cpp in AOSP 8.0. The method register_android_hardware_Radio() (line 15) is called to register the JNI methods for Radio, with the JNI method information provided in line 16. Specifically, the kRadioModuleClassPathName variable (line 5) declares the containing class name of the Java method, and gModuleMethods (line 7) declares the correspondence between the Java method and the C++ function. The variable gModuleMethods is defined to contain groups of the Java method name (line 9), parameter and returned types (lines 10 to 11), and the pointer of C++ method (line 12). All the information will be dynamically registered in JVM during run-time. Finally, the C++ method involved in the cross-language communication is declared in line 14, while the involving Java method can be found in the java file RadioModule.java in package android.hardware.radio (lines 2 to 3).

Refer to caption
Figure 7: An example of JNI-based cross-language communication. The code snippets are simplified for better illustration.

According to the JNI-based communication mechanism, we extract pairs of entry-points from Java- and Native-sides. Specifically, the JNI methods and the corresponding native methods are vaguely identified by a linear sweep searching of keyword RegisterMethodsOrDie, registerNativeMethods and jniRegisterNativeMethods over the .cpp files at first. Then we extract the class path name (e.g., the kRadioModuleClassPathName in Figure 7) and the array of JNINativeMethod structures, from which a pair of entry-points can be located and recognized (e.g., the pair of native_setup() and android_hardware_Radio_setup()).

3.3 Cross-Language Protection Mapping Extraction

After the entry-points on both Java- and Native-sides are identified, we further extract the protection mappings from AOSPs. In this section, we first introduce how NatiDroid generates CFG from both sides. Based on the CFG, NatiDroid then traverses the cross-language Android API call paths and corresponding security checks (e.g., permission checks) to generate the API-permission protection mappings.

3.3.1 Cross-language CFG Generation

Algorithm 1 Constructing Cross-language CFG

Input: Android native code and intermediate jar cc.
Output: Cross-language CFG GG.

1:G=G=\emptyset
2:(Nepj,Nepc)scanEntryPoints(c)(N_{epj},N_{epc})\leftarrow scanEntryPoints(c)
3:for each(nepj,nepc)(Nepj,Nepc)each\ (n_{epj},n_{epc})\in(N_{epj},N_{epc}) do
4:     (Nc,Ec)NativeCFGGenerator(nepc)(N_{c},E_{c})\leftarrow NativeCFGGenerator(n_{epc})
5:     if hasSecurityCheck(Nc)hasSecurityCheck(N_{c}) then
6:         for each(nc,ec)(Nc,Ec)each\ (n_{c},e_{c})\in(N_{c},E_{c}) do
7:              GG(nc,ec)G\leftarrow G\cup(n_{c},e_{c})
8:         end for
9:         (Nj,Ej)JavaCFGGenerator(nepj)(N_{j},E_{j})\leftarrow JavaCFGGenerator(n_{epj})
10:         for each(nj,ej)(Nj,Ej)each\ (n_{j},e_{j})\in(N_{j},E_{j}) do
11:              GG(nj,ej)G\leftarrow G\cup(n_{j},e_{j})
12:         end for
13:         elink(nepj,nepc)e\leftarrow link(n_{epj},n_{epc})
14:         GG(nepj,e)G\leftarrow G\cup(n_{epj},e)
15:         GG(nepc,e)G\leftarrow G\cup(n_{epc},e)
16:     end if
17:end for

Algorithm 1 elaborates the detailed steps involved in generating cross-language CFGs. After obtaining the entry-point pairs from both Java- and Native-sides (line 2, as detailed in Section 3.2), NatiDroid first leverages a forward analysis to generate a CFG on the native side from each identified native entry-point (line 4). If the native-side CFG does not contain any security checkpoint (e.g., permission check, UID check, and PID check), we discard the CFG for computational efficiency (line 5). Otherwise, NatiDroid further utilizes a backward analysis to build a Java-side CFG starting from the paired Java-side entry-point to an Android API. If the reached Android API is further invoked by other Android APIs, we extend the CFG until the API is not called by any other APIs (lines 6 to 12). The CFGs generated from both sides are then connected with the communication models identified in Section 3.2 (lines 13 to 15).

We detail the mechanisms unique to Android that require additional work to handle as follows.

Handling the service identifier.  The aforementioned AIDL is often used to invoke remote methods in service. Before the invocation, the service is usually pointed by passing a string to the getService or checkService method, for example, the string ‘‘media.player’’ in line 22 of Figure 8. When building the call graph, we need to handle such remote invocation and identify which class is the identifier string actually pointed to. These services are registered to the system through an addService method (either on Java-side or Native-side). Therefore, we can automatically collect the correspondences between these identifiers and service classes from it. First, we scan the Java and C++ files looking for addService methods. Then the program confirms whether the method is ServiceManager.addService or defaultServiceManager->addService, separately. Once confirmed, the program extracts a pair of service class and the corresponding identifier from the parameters; for example, the string identifier ‘‘media.player’’ in Figure 8 will be paired with its service class MediaPlayerService.

Refer to caption
Figure 8: An example of using strong pointer in native library

Handling Android strong pointer.  Although the strong pointer defines the type variable, the type is not necessary to be restricted. Therefore, we need additional efforts to get what type the strong pointer actually points to from the context. In the case shown in Figure 8, the createMediaRecorder() method of the service object is invoked (line 13). Considering createMediaRecorder() is a member function and the object service is defined as a strong pointer, to determine which createMediaRecorder() method is actually invoked, we need to determine the type of service at first. By tracing the variables, we can find that, in line 25, the getMediaPlayerService() returns variable sMediaPlayerService to service, which is converted from the variable binder in line 24. Further, according to line 22, the binder is the result of getService() which returns a service object in the type of MediaPlayerService (as detailed in the previous paragraph). Therefore, we can determine that the createMediaRecorder() method invoked in line 13 is a method defined in MediaPlayerService class, rather than the IMediaPlayerService class as declared by the strong pointer in line 11. According to the strong pointer mechanism, when we find that a member function is called, if the object is declared as a strong pointer, the invocation of the member function will be determined automatically. The NatiDroid will first trace the statement where an object is assigned to the strong pointer. If it is assigned through mehtod getService(), the type of the object will be determined by the passed service identifier (as detailed in the previous paragraph); otherwise, NatiDroid will determine the type of strong pointer according to the variable type returned by the function.

Handling member variables.  A class member variable is also possibly assigned by a strong pointer. For example, in line 8 of Figure 8, the setAudioSource() method of the mMediaRecorder object is invoked, but from this line of code we cannot determine the type of variable mMediaRecorder so that we cannot determine which setAudioSource() method has been invoked. By looking up in the referenced header file (from line 27), we find that this variable is a member variable of class MediaRecorder. Therefore, to find out the type of this variable, we can search the entire class looking for the assignment or initialization statement. Note that the assignment should be ignored if the assignment releases the pointer, e.g., pointing the variable to a null pointer. In this case, the variable mMediaRecorder is initialized as the return value of createMediaRecorder in the class constructor (line 13). We have explained how to determine the return type of createMediaRecorder in the previous paragraph, handling Android strong pointers. To implement the process automatically, if a variable cannot be tracked in the local scope, NatiDroid will point to the header file to check whether it is a member variable, and thus the tracking scope will be expanded to the entire class.

3.3.2 Protection Mapping Extraction

Algorithm 2 shows the pseudo-code of extracting the protection mapping of Android APIs. After obtaining the cross-language CFG, we resort to a Depth-First Search (DFS) strategy (line 2) to check if there are call paths between Android APIs in the Java API Framework layer and security checks in the Native Library layer. For each node in the CFG, if it is a Java node, we will collect all its native children (lines 3 to 5) and obtain the security checks defined in its children nodes (lines 7 to 8). If there are more than one checkpoint on the call trace (e.g., an Android API is protected by multiple permissions), we concatenate them with AND operation. As inspired by Aafer et al. [2], we also include security checks other than permission enforcement, such as UID and PID checks. If there is more than one Android API along the track, we create a mapping entry for each of them (i.e., all Android APIs along the track have the same security check). Finally, each pair of Java API node and its corresponding security check(s) in Native-side will be added into the protection mapping (line 10).

Algorithm 2 Protection Maps Extraction

Input: The cross-language CFG generated in Algorithm 1 GG.
Output: The protection mapping MM.

1:M=map(Node,Condition)M=map(Node,\ Condition)
2:NDFS(G)N\leftarrow DFS(G)
3:for eachnNeach\ n\in N do
4:     if isJavaAPINode(n)isJavaAPINode(n) then
5:         KgetAllNativeChildren(n)K\leftarrow getAllNativeChildren(n)
6:         for eachkKeach\ k\in K do
7:              if hasSecurityCheck(k)hasSecurityCheck(k) then
8:                  CCgetSecurityChecks(k)C\leftarrow C\cup getSecurityChecks(k)
9:              end if
10:              MM(n,C)M\leftarrow M\cup(n,C)
11:         end for
12:     end if
13:end for
TABLE I: Permission-API protection mappings extracted by NatiDroid. The results of Axplorer and Arcade are generated from the Android Java Framework, while the results of NatiDroid are generated from Android Native Libraries.
Source Analysis Time (min) API Framework (Java) Native Library (C/C++)
Axplorer Arcade NatiDroid
# Permission # API Affected # Permission # API Affected # Permission # API Affected
# S 1 # D # N # Total # S # D # N # Total # S # D # N # Total
AOSP 7.0 43 145 12 27 184 2,115 152 11 30 193 1,585 5 2 2 9 449
AOSP 7.1 45 145 12 27 184 2,153 152 11 30 193 1,585 6 2 2 10 449
AOSP 8.0 49 / / / / / / / / / / 8 2 2 12 464
AOSP 8.1 51 / / / / / / / / / / 7 2 2 11 461
  • 1

    S: Signature permission; D: Dangerous permission; N: Normal permission.

4 Evaluation

The main contribution of this work, NatiDroid, is to enable the cross-language static analysis of the Android framework. Since there is a number of existing tools [16, 17] and works [1, 2] well handling the static analysis of the Java-side of Android framework, NatiDroid specifically focuses on the analysis of the cross-language part of the Android framework. We therefore incorporate existing works Axplorer [1] and Arcade [2] for the analysis that does not involve cross-language communication.

4.1 Protection Mapping in Android Native Libraries

We use NatiDroid to extract the API protection mapping for four AOSP versions – 7.0, 7.1, 8.0, and 8.1. We obtained the source code from the official AOSP repository [18]. The experiment was run on a Linux server with Intel (R) Core (TM) i9-9920X CPU @ 3.50GHz and 128 GB RAM.

TABLE II: Permission checks in native libraries
Permissions AOSP Protection Level
7.0 7.1 8.0 8.1
ACCESS_DRM_CERTIFICATES Signature
ACCESS_FM_RADIO Signature
ACCESS_SURFACE_FLINGER Signature
CAPTURE_AUDIO_HOTWORD Signature
CONTROL_WIFI_DISPLAY Signature
LOCATION_HARDWARE Signature
MODIFY_AUDIO_ROUTING Signature
READ_FRAME_BUFFER Signature
RECORD_AUDIO Dangerous
CAMERA Dangerous
INTERNET Normal
MODIFY_AUDIO_SETTINGS Normal
  • : The permission exists in AOSP; : The permission does not exist in AOSP.

Table I presents the statistics of permission-API protection mapping on the four AOSP versions. Since NatiDroid only focuses on the Native-triggered permission checks (i.e., on the Native-side), the results of the Java API framework (i.e., on the Java-side) are derived from previous works Axplorer and Arcade [1, 2].333Java-side mappings are derived from https://github.com/reddr/axplorer/ and https://arcade-android.github.io/arcade/. Since the authors of both works only released their mapping results (for AOSP version 7.1 and under) in lieu of the tools, we are unable to obtain the mappings on AOSP 8.0 and 8.1. As shown in the last two columns of Table I, the number of newly identified permissions that are missed in previous works ranges from 9 to 12 in the four AOSP versions. There are 449 to 464 Android APIs associated with these permissions (i.e., invoking these APIs requires the corresponding permissions to be granted), counting up to approximate 30% of the mappings reported in the previous study, which are overlooked in the previous work that only analyzed the Java-side of the Android framework.

Table I reports the breakdown of the mappings based on the permission protection levels. The mapping results contain the permissions in signature, dangerous, and normal levels. Signature permissions are only granted if the requesting app is signed with the same certificate as the app that declared the permission. The signature permissions declared in the AOSP will only be granted to apps developed by Android; hence, neither mobile phone vendors (e.g., Samsung, Huawei) nor third-party app developers have access to them. Normal permissions refer to the permissions with minimal risk to the system and the users’ private data. Dangerous permissions are those higher-risk permissions that would give access to private user data or control over the device that can negatively impact the users. Missing these mappings, especially the ones for the dangerous permissions, will lead to false results in detecting security issues of Android apps, such as permission over-privilege and component hijacking problems (detailed in Section 4.2). Given that signature permissions can only be accessed by system apps and normal permissions are usually associated with non-sensitive behaviours. Thus, the main security and privacy threats to the majority of Android apps (i.e., third-party apps downloaded from official or alternative app stores, which usually have no access to signature permissions) are caused by inaccurate mapping of dangerous permissions. It is therefore worth highlighting that NatiDroid is able to find approximately 17% dangerous level permission that previous works have missed. NatiDroid has identified the mappings for two additional dangerous permissions CAMERA and RECORD_AUDIO, which are closely related to user’s privacy. Table II details the new permissions protected by Native-triggered permission checks excluded in the previous works.

Due to the lack of ground truth for the permission protection mappings, it is difficult to evaluate the overall accuracy of our extracted mappings. We therefore resort to a manual process to examine the correctness of our mappings. To this end, we manually read the involved source code in the AOSP codebase to confirm if the APIs will go through the corresponding security check(s) and if the condition(s) in the security check(s) is(are) consistent with the condition(s) in the mappings. We randomly selected 10% of the total mappings (i.e., 182 mappings) for manual inspection and found no missing or redundant protection conditions in our mappings.

The column 2 in Table I reports the time consumed by NatiDroid to analyze the collected AOSP versions. As shown in the table, the average time taken for extracting the protection mapping from one AOSP version is 47 mins. Since the analysis has to be done only once per Android version, the time overhead is acceptable.

4.2 Applications of Protection Mappings

The protection mappings can be leveraged to detect security issues of Android apps, such as permission over-privilege and component hijacking. In this subsection, we evaluate the effectiveness of our extracted mappings in identifying these security vulnerabilities.

We include two categories of Android apps in our experiments: the custom ROM apps that are pre-installed on the devices, such as Camera and Calendar, as well as the third-party apps that users can download from official or alternative app stores (e.g., social networking apps, banking apps). The experimental dataset contains 1,035 custom ROM apps extracted from five Android custom ROMs of four vendors (i.e., Samsung, LG, Huawei, and Xiaomi) and 10,000 third-party apps randomly downloaded from the Google Play store. Table III shows an overview of the dataset in use.

We use the permission protection mappings extracted from AOSP to detect security vulnerabilities in both the custom ROM apps and third-party apps. The AOSP mapping may miss some vendor-customized permissions (e.g., huawei.permission.SET_SMSC_ADDRESS), which may be used in the custom ROM apps. Nevertheless, we argue that using the AOSP mapping may miss some vulnerabilities caused by the misuse of vendor-customized permissions but will not affect the results corresponding to the official permissions, serving as the main scope of our study.

TABLE III: Experimental dataset
Set Source # Apps
Custom ROM Apps Xiaomi (7.0) 398
LG (7.0) 220
Samsung (7.0) 302
Huawei (7.0) 115
Third-party Apps Google Play Store 10,000
Total 11,035
TABLE IV: Permission over-privilege detection results
Data Set Source Analyzable Apps Avg # Unneeded Permissions per App
# of False Positive
Permissions
% of Apps that
Have False Positives
Nati + Ar 1 Ar Nati + Ax Ax Nati + Ar Nati + Ax Nati + Ar Nati + Ax
Custom ROM Apps Xiaomi (7.0) 345 13.41 13.7 10.94 11.18 102 84 19.13% 17.97%
LG (7.0) 215 12.76 13.17 10.24 10.6 88 77 25.12% 24.19%
Samsung (7.0) 266 11.58 12.0 9.44 9.82 113 101 22.93% 21.8%
Huawei (7.0) 111 13.53 14.02 11.14 11.56 54 47 24.32% 22.52%
Total (7.0) 937 12.75 13.14 10.38 10.71 357 309 22.2% 21.02%
Third-party Apps Google Play Store 9,475 6.03 6.88 3.52 4.36 8,063 7,894 71.5% 71.38%
  • 1

    Nati: NatiDroid; Ar: Arcade; Ax: Axplorer; +: merge the two mappings.

4.2.1 Permission Over-privilege Detection

Android app developers access Android framework functionalities by invoking Android APIs. Some APIs have access to sensitive information, such as reading the contact list, are protected by permissions. Developers need to request such permissions from the Android system before accessing the sensitive resources. Specifically, a list of required permissions need to be declared in the AndroidManifest.xml file, and the corresponding permissions protected APIs are to be invoked in the app’s implementation. According to the Android developers’ documentation [19], app developers should request a minimum set of permissions required to complete the app’s functionality, as introducing additional permissions will increase the risk of privacy leak. However, developers usually (either intentionally or unintentionally) request permissions that are not related to the functionalities actually implemented in the app, and hence, not necessary [5].

To detect apps with the permission over-privilege issue, we extract the reachable APIs of the app (with a 30-min timeout), and retrieve its protection conditions (e.g., permission, UID, PID) according to the mappings. For instance, when invoking an Android API, it may check the UID (e.g., uid == AID_SYSTEM checks if the app has system privilege) and the PID (e.g., callingPid == getpid() examines if the method is called by its own process) along with permission enforcement. While the UID can be retrieved statically, the PID has to be determined at run-time, thereby cannot be obtained through static analysis. Nevertheless, the apps included in the experiment are custom ROM apps and third-party apps, which cannot possess PID of Android system services. Therefore, it is safe to assume that callingPid == getpid() will always return false in our tested apps. Finally, if the app declares permission (in the AndroidManifest.xml file) that is not required (i.e., no APIs associated with the permissions found in the app), we flag it as an over-privilege case.

Results.  Table IV presents the over-privilege detection results. To demonstrate the effectiveness of our mappings in pinpointing the permission over-privilege issue, we compare previous works’ results with our results. Note that, in our results (i.e., Nati + Ar and Nati + Ax), the Java-side mappings are derived from Arcade and Axplorer. We identify 95.8% and 95.5% apps with a permission over-privilege issue using Arcade’s and Axplorer’s mappings, respectively. Among their results, we identify that 66.6% and 54.2% apps (in Arcade’s and Axplorer’s results, respectively) contain false-positive results caused by missing Native-triggered permission mappings. Specifically, as shown in the last four columns of Table IV, there are 8,063 and 357 permissions that are erroneously identified as over-privilege by Axplorer in 71.5% third-party apps and 22.2% custom ROM apps, respectively; for Axplorer, 7,894 permissions in 71.38% third-party apps and 309 permissions in 21.02% custom ROM apps are found to be false-positive.

Interestingly, both Arcade and Axplorer report that a significantly high proportion of apps (approximately 96%) suffer from a permission over-privilege issue. We therefore take an in-depth look into their detection results and observe that the majority of their false positives are caused by missing native triggered INTERNET permission mappings. As illustrated in Figure 9, we further present the breakdown of permissions that cause the false positive results in the comparing methods. Specifically, missing INTERNET permission mappings leads to 6,661 and 6,660 false positives in Arcade’s and Axplorer’s results. Other missing permission mappings that contribute to the false positives include RECORD_AUDIO (623 false positives in both Arcade and Axplorer), MODIFY_AUDIO_SETTINGS (424 and 256 false positives in Arcade and Axplorer, respectively), and CAMERA (355 false positives in both Arcade and Axplorer).

Refer to caption
Figure 9: False-positive over-privileged permissions in previous works detected by NatiDroid.

Manual inspection. Due to the lack of ground truth, we manually inspect if the over-privileged permissions detected are indeed unneeded by the containing apps. The first two authors of this paper and three security researchers are involved in the manual inspection. The result is determined via majority voting. To this end, for each app, we decompile the APK file and locate the relevant APIs. Then, we manually check the app’s context and determine whether the invocation of the APIs meet the conditions in the protection mappings. As this process involves immense manual efforts, it cannot scale to cover a large number of apps. Hence, we manually verified 100 randomly selected apps. Our manual analysis indicates that most of the cases are true positives (95%). The remaining five apps contain implicit parameters passed to the APIs to be examined, which cannot be precisely inferred via static analysis. Nevertheless, we resort to a dynamic approach to verify the remaining five apps. Specifically, we remove the permissions in question from the AndroidManifest.xml file and repackage the app. Then, we manually test the app on an emulator to confirm if the app crashes or the corresponding functions are disabled. As a result, the removal of the permissions in question has no impact on the apps, suggesting that these permissions are indeed unneeded.

Case study.  In our study, we find that a large number of apps misidentified as over-privilege cases by previous works because of their imprecise mapping of the INTERNET permission. We show a typical false positive case by Axplorer and Arcade in Figure 10. Lines 1 to 8 in Figure 10 present the code snippet derived from the victim app Angel Numbers [20]. The app declares the INTERNET permission in its manifest (line 3), and invokes the API setDataSource() (line 8) to play online media (hence requiring accessing the Internet). NatiDroid traces the method back to its definition in the containing Java class MediaPlayer.java (line 10), and finds that no permission is required to access this method. Unfortunately, since the previous works Axplorer and Arcade only analyzed the Java framework but ignored the native libraries, they thereby concluded that there is no mapping between setDataSource() method and INTERNET permission. However, our approach further identify that setDataSource() method invokes a native method android_..._setDataSourceAndHeaders() in the native library android_media_MediaPlayer.cpp through JNI (lines 12 to 17), which eventually triggers a permission check for INTERNET (line 25). By analyzing the native libraries implemented in four AOSPs, NatiDroid has identified 20 mappings related to INTERNET permission, where the permission checks are implemented in native code.

Refer to caption
Figure 10: A case of over-privilege

4.2.2 Component Hijacking Detection

TABLE V: Component hijacking detection results
Data Set Source Analyzable Apps
# Hijacked Components
(in # Apps)
# Hijacked Sources
% of Apps Having
Native-triggered
Component Hijacking
Nati + Ar 1 Ar Nati + Ax Ax Nati + Ar Ar Nati + Ax Ax Nati + Ar Nati + Ax
Custom ROM Apps Xiaomi (7.0) 280 16 (10) 0 (0) 16 (10) 6 (4) 16 0 30 14 3.57% 3.57%
LG (7.0) 171 1 (1) 0 (0) 1 (1) 1 (1) 1 0 4 3 0.58% 0.58%
Samsung (7.0) 197 4 (2) 0 (0) 4 (2) 3 (1) 4 0 10 6 1.02% 1.02%
Huawei (7.0) 91 1 (1) 0 (0) 1 (1) 1 (1) 2 0 7 5 1.1% 1.1%
Total (7.0) 739 22 (14) 0 (0) 22 (14) 11 (7) 23 0 51 28 1.89% 1.89%
Third-party Apps Google Play Store 9,123 2 (2) 0 (0) 4 (4) 3 (3) 2 0 8 6 0.02% 0.02%
  • 1

    Nati: NatiDroid; Ar: Arcade; Ax: Axplorer; +: merge the two mappings.

Android apps are built upon basic blocks named components, such as Activities and Services. Each component fulfills a task and can respond to requests from the app’s other components and the Android framework. A component may also handle the requests from other apps if the component is publicly available (i.e., exported). For example, a restaurant review app may need to display a map to mark the location of a restaurant. Instead of implementing its own map, the app can incorporate an existing map component exported by a navigation app. However, suppose the component has access to sensitive information (e.g., location) but is not well-protected (e.g., through permission enforcement). In that case, it may be hijacked by other apps to gain unauthorized access to protected resources through exported components in vulnerable apps.

We identify if an app is vulnerable to component hijacking attack by comparing the set of dangerous level permissions it requires to access an exported component (declared in AndroidManifest.xml) with the actual permission protected APIs accessible by the component. If the former is weaker than the latter, we consider it vulnerable to a hijacking attack. To this end, we obtain a list of control flow reachable APIs accessible by each exported component. Based on our mapping results, we can therefore infer the permissions required to protect the component (denoted as PrP_{r}). On the other hand, we retrieve the permissions enforced in the manifest for accessing these exported components (denoted as PdP_{d}). For each exported component, if PrPd<PrP_{r}\cap P_{d}<P_{r}, the component is considered vulnerable to hijacking attacks.

It should be noted that in the Android system, if a component is designed to provide a privileged functionality exclusively to other apps signed by the same developer, a signature level permission could be declared, which may not match any of the permissions in PrP_{r}. Since these components are only accessible by the apps signed with the same developer, we therefore consider the components with signature level permissions well protected, even if it satisfies the condition PrPd<PrP_{r}\cap P_{d}<P_{r}.

Results. As presented in Table V, our mapping is capable of pinpointing additional components that are vulnerable to hijacking attacks in both custom ROM and third-party apps. For instance, we have identified 24 and 12 vulnerable components in 16 apps with hijacking vulnerabilities that are overlooked by Arcade and Axplorer (columns 4 to 7 of Table V). Among the vulnerable components, we have discovered 25 sources (i.e., sensitive resources or operations) that may be accessed by unauthorized apps (columns 8 to 11 of Table V). As observed, custom ROM apps suffer more from Native-triggered component hijacking vulnerabilities than third-party apps. For instance, the apps contain Native-triggered component hijacking vulnerabilities range from 3.57% to 0.58% across all vendors, while there are only 2 (0.02%) third-party apps having such a vulnerability.

Manual inspection. Similar to the manual inspection on the over-privilege detection results, two authors and three security researchers manually verified the component-hijacking results. Note that, due to the code obfuscation on 6 apps, we can only verify the 16 vulnerable components in the remaining 12 apps. For each app, we decompile the APK file and obtain the required permission in AndroidManifest.xml as PrP_{r}. To obtain the PdP_{d}, we start by tracing the entry-points from Java-side to their corresponding entry-points on native-side, and then verify all the Native-triggered security checks. The manual inspection finds no false positives in the component-hijacking results. However, there could be false negatives due to the incompleteness of CFGs, which is almost infeasible to be verified manually.

Case study. We have identified a system app com.android.mms in Huawei’s EMUI 5.0 ROM (based on Android 7.0) with component hijacking vulnerability. Figure 11 shows the code snippet of the app (lines 1 to 14) and the involving Java framework class (lines 15 to 17) and native library (lines 18 to 38). The app exported a service named NoConfirmationSendService. The service has a public method MmsVideoRecord() (line 8) that records the video and audio from the device’s camera and microphone. The method invokes setVideoSource() and setAudioSource() APIs, which are protected by permissions CAMERA (line 34) and RECORD_AUDIO (line 37), respectively. These permission checks are implemented in the native library MediaRecorderClient.cpp, and thus cannot be captured by Axplorer or Arcade. Exporting this service offers the third-party apps capability to access the video and audio recording functions and save the recorded media to an external directory which could be accessed by other apps. This leads to potential privacy leakage (lines 12 to 14). However, insufficient protection has been applied to this service, i.e., neither CAMERA nor RECORD_AUDIO permissions are required to access the resource (as declared in line 4, only SEND_RESPOND_VIA_MESSAGE permission is required). SEND_RESPOND_VIA_MESSAGE is a system protected permission, which allows the app to provide instant text messages to respond to the incoming phone calls, so it is unreasonable to request CAMERA and RECORD_AUDIO permissions. The best practice is to declare a customized permission to replace the permission group. We have disclosed 24 Native-triggered vulnerabilities to 4 vendors and 2 app developers through email on 1 June 2021, and are now in discussions with them about how severe the vulnerabilities are and the patching process.

Refer to caption
Figure 11: A case of component hijacking

5 Discussion and Limitations

5.1 Android Versions

In this paper, we propose a solution to facilitate cross-language static analysis of the Android framework and build a prototype system, NatiDroid, to extract API-permission mapping from the Android OS.

To compare with the state-of-the-art works Axplorer and Arcade, which are close sourced and only generated the mappings up to Android 7.1, in our experiment, we extract the mappings from the latest versions they have (i.e., 7.0 and 7.1) and two newer versions (i.e., 8.0 and 8.1). Nevertheless, the proposed solution can apply to any Android version, with further engineering works to be done in the pre-processing module. Specifically, different AOSP versions uses different compiler to compile their native libraries. Hence, additional engineering efforts are required to prepare the compiling commands as described in Section 3.1.

5.2 Custom ROMs

Android smartphones such as Samsung, Huawei and Xiaomi, are shipped with vendor-customized Android systems (i.e., custom ROMs) rather than the AOSP. Unfortunately, these custom ROMs are not open-source. The proposed solution takes the source code as input; therefore, it cannot extract permission mappings from these close sourced custom ROMs. However, smartphone vendors can use our solution to analyze their customized Android versions based on their source code. Nevertheless, to maintain the compatibility of running third-party apps, such custom ROMs are not likely to modify the normal and dangerous level permission specifications of AOSP that third-party apps can access, but rather add a few signature level permissions for their own system apps. Therefore, the results derived from AOSP will not affect the security analysis of third-party apps, which are the majority in the Android ecosystem. On the other hand, with NatiDroid, third-party vendors can perform an inner security analysis on custom ROM source code, determine whether there are errors in the implementation of permission mappings, and further detect permission over-privilege or component hijacking before releasing an app.

5.3 Static Analysis

When detecting over-privilege and component hijacking issues in Android apps, we may suffer from the intrinsic vulnerability of static code analysis when encountering code obfuscation, reflection, etc. These may lead to the unsoundness of our results. When building the apps’ call graph for component hijacking detection, our method may yield unsound results because it may miss the context and the parameters that can only be obtained at run-time. For example, the API android.media.MediaPlayer: void setDataSource requires the Internet permission when the data source is online media. The source is not always a static string so that it may be assigned at run-time. Nevertheless, these challenges are regarded as well known and non-trivial issues to overcome in the research community [21].

6 Related Work

Android API protection mapping.  Stowaway [5] initially explored and analyzed the Android permission specification. They extracted API mappings based on the feedback directed fuzz testing, and dynamically recorded the permission checks of APIs. The mappings they extracted are accurate, but the code coverage is limited. To address the limitations of low code coverage, PScout [3] uses static analysis to extract the API protection mapping. However, they did not consider the context of the API invocation, and thus may produce false positive mappings. Axplorer [1] leverages more accurate static analysis on the SDK and Android framework, and generates more precise permission specifications. Arcade [2] conducted a similar static analysis, with additional attention paid to extract other security mechanisms, such as UID and PID checks. While these works only analyzed the Java-side of the Android, none of the works has looked into the native libraries within the Android framework. Our work fills the research gap by analyzing the native libraries and their communications with the Java framework to produce more comprehensive permission protection mappings.

Cross-language analysis on Android.  A plethora of works have proposed to solve the analysis of cross-language code. George et al. [22] scanned the binary libraries and cross-referenced the information to search the call-backs from Native code to Java. Their work focuses on the JNI mechanism alone. However, the Android framework provides other IPC mechanisms, such as AIDL, which are not considered. Fengguo et al. [23] proposed a static analysis framework that focuses on performing cross-language modeling and generating call graphs for the analyzed apps. Nevertheless, these works are only applicable to Android apps, which are far less complicated than the Android framework we analyzed. In addition, our cross-language analysis handles various Android IPC mechanisms such as JNI and AIDL.

Static analysis on Android.  Static analysis is widely used in code analysis due to its fast speed and high coverage, especially in the field of Android security analysis. To date, there have been many works using static approaches to analyze the code of the Android apps. Static taint analysis can track the flow of information, detect privacy leaks and other issues, such as AndroidLeaks [24], FlowDroid [25], DroidSafe [26], BidText [27] and Amandroid [23]. There are also some works proposed to handle the analysis of Android inter-component communication (ICC), such as Epicc [28], DidFail [29] and IccTA [30]. Our static analysis extends existing static analysis tools to enable the cross-language analysis.

Android vulnerability detection.  There are also many works on vulnerability identification of Android operation systems, including the leakage of content provider [31], data encryption vulnerabilities [32, 33], cloud push-messaging services vulnerabilities [34] and others [35, 36, 37, 38]. Specially, AutoCog [39] analyzed and checked that if the app’s required permission conforms to the description of the permission. FANS [40] proposed to fuzz the Android Native system service for detecting vulnerabilities, while Yousra et al. [41] used fuzz to detect vulnerabilities in Android TVs. By leveraging the protection mapping our approach generated, we also identified vulnerabilities in Android apps, such as permission over-privilege and component hijacking.

7 Concluding Remarks

We proposed a novel approach, NatiDroid, to facilitate the cross-language analysis of the Android framework. NatiDroid identifies the entry-point pairs of both Java- and Native-sides of the Android framework, where both sides are communicated through JNI and AIDL based mechanisms, so NatiDroid builds the cross-language CFG on the overall Android framework (Java + Native code). Based on the cross-language CFG, we extracted Native-triggered permission specifications and created the protection mappings in the native code to complement existing Java-based mappings. We further applied our new mappings to detect permission over-privilege and component hijacking vulnerabilities in a large dataset consisting of more than 11,000 Android apps.

Our results show that using the mapping derived by NatiDroid can identify a significant number of false results existing in the state of the art, such as Axplorer and Arcade, notwithstanding the inevitable errors subject to the accuracy of generated CFGs.

References

  • [1] Michael Backes, Sven Bugiel, Erik Derr, Patrick McDaniel, Damien Octeau, and Sebastian Weisgerber. On demystifying the android application framework: Re-visiting android permission specification analysis. In 25th USENIX Security Symposium (USENIX Security 16), pages 1101–1118, Austin, TX, August 2016. USENIX Association.
  • [2] Yousra Aafer, Guanhong Tao, Jianjun Huang, Xiangyu Zhang, and Ninghui Li. Precise Android API protection mapping derivation and reasoning. In Proceedings of the 2018 ACM SIGSAC Conference on Computer and Communications Security, pages 1151–1164, 2018.
  • [3] Kathy Wain Yee Au, Yi Fan Zhou, Zhen Huang, and David Lie. Pscout: analyzing the Android permission specification. In Proceedings of the 2012 ACM conference on Computer and Communications Security, pages 217–228, 2012.
  • [4] Mohammad Nauman, Sohail Khan, and Xinwen Zhang. Apex: Extending Android permission model and enforcement with user-defined runtime constraints. In Proceedings of the 5th ACM symposium on Information, Computer and Communications Security, pages 328–332, 2010.
  • [5] Adrienne Porter Felt, Erika Chin, Steve Hanna, Dawn Song, and David Wagner. Android permissions demystified. In Proceedings of the 18th ACM conference on Computer and Communications Security, pages 627–638, 2011.
  • [6] Long Lu, Zhichun Li, Zhenyu Wu, Wenke Lee, and Guofei Jiang. Chex: statically vetting Android apps for component hijacking vulnerabilities. In Proceedings of the 2012 ACM conference on Computer and Communications Security, pages 229–240, 2012.
  • [7] Lei Wu, Michael Grace, Yajin Zhou, Chiachih Wu, and Xuxian Jiang. The impact of vendor customizations on Android security. In Proceedings of the 2013 ACM SIGSAC conference on Computer & Communications Security, pages 623–634, 2013.
  • [8] Yajin Zhou Xuxian Jiang and Zhou Xuxian. Detecting passive content leaks and pollution in Android applications. In Proceedings of the 20th Network and Distributed System Security Symposium (NDSS), 2013.
  • [9] Google Play - Camera360 photo editor + camera & beauty selfies. https://play.google.com/store/apps/details?id=vStudio.Android.Camera360, 2021.
  • [10] Soot - Java analysis framework. http://sable.github.io/soot/, 1999.
  • [11] Clang: A C language family frontend for LLVM. https://clang.llvm.org, 2000.
  • [12] Earlence Fernandes, Jaeyeon Jung, and Atul Prakash. Security analysis of emerging smart home applications. In 2016 IEEE symposium on security and privacy (SP), pages 636–654. IEEE, 2016.
  • [13] Yu Feng, Saswat Anand, Isil Dillig, and Alex Aiken. Apposcopy: Semantics-based detection of Android malware through static analysis. In Proceedings of the 22nd ACM SIGSOFT International Symposium on Foundations of Software Engineering, pages 576–587, 2014.
  • [14] Introduction to the clang ast. https://clang.llvm.org/docs/IntroductionToTheClangAST.html, 2000.
  • [15] Soong build system. https://source.android.com/setup/build, 2012.
  • [16] Raja Vallée-Rai, Phong Co, Etienne Gagnon, Laurie Hendren, Patrick Lam, and Vijay Sundaresan. Soot: A Java bytecode optimization framework. In CASCON First Decade High Impact Papers, pages 214–224. 2010.
  • [17] WALA: T.J. Watson libraries for analysis. https://github.com/wala/WALA, 2006.
  • [18] Android open source project. https://source.android.com, 2021.
  • [19] Developer guides — Android developers. https://developer.android.com/guide, 2008.
  • [20] Google Play - Angel numbers. https://play.google.com/store/apps/details?id=angel.numbers, 2021.
  • [21] Felix Pauck, Eric Bodden, and Heike Wehrheim. Do android taint analysis tools keep their promises? In Proceedings of the 2018 26th ACM Joint Meeting on European Software Engineering Conference and Symposium on the Foundations of Software Engineering, pages 331–341, 2018.
  • [22] George Fourtounis, Leonidas Triantafyllou, and Yannis Smaragdakis. Identifying java calls in native code via binary scanning. In Proceedings of the 29th ACM SIGSOFT International Symposium on Software Testing and Analysis, pages 388–400, 2020.
  • [23] Fengguo Wei, Sankardas Roy, and Xinming Ou. Amandroid: A precise and general inter-component data flow analysis framework for security vetting of Android apps. ACM Transactions on Privacy and Security (TOPS), 21(3):1–32, 2018.
  • [24] Clint Gibler, Jonathan Crussell, Jeremy Erickson, and Hao Chen. AndroidLeaks: automatically detecting potential privacy leaks in Android applications on a large scale. In International Conference on Trust and Trustworthy Computing, pages 291–307. Springer, 2012.
  • [25] Steven Arzt, Siegfried Rasthofer, Christian Fritz, Eric Bodden, Alexandre Bartel, Jacques Klein, Yves Le Traon, Damien Octeau, and Patrick McDaniel. Flowdroid: Precise context, flow, field, object-sensitive and lifecycle-aware taint analysis for Android apps. ACM SIGPLAN Notices, 49(6):259–269, 2014.
  • [26] Michael I Gordon, Deokhwan Kim, Jeff H Perkins, Limei Gilham, Nguyen Nguyen, and Martin C Rinard. Information flow analysis of Android applications in DroidSafe. In NDSS, volume 15, page 110, 2015.
  • [27] Jianjun Huang, Xiangyu Zhang, and Lin Tan. Detecting sensitive data disclosure via bi-directional text correlation analysis. In Proceedings of the 2016 24th ACM SIGSOFT International Symposium on Foundations of Software Engineering, pages 169–180, 2016.
  • [28] Damien Octeau, Patrick McDaniel, Somesh Jha, Alexandre Bartel, Eric Bodden, Jacques Klein, and Yves Le Traon. Effective inter-component communication mapping in Android: An essential step towards holistic security analysis. In 22nd USENIX Security Symposium (USENIX Security 13), pages 543–558, Washington, D.C., August 2013. USENIX Association.
  • [29] William Klieber, Lori Flynn, Amar Bhosale, Limin Jia, and Lujo Bauer. Android taint flow analysis for app sets. In Proceedings of the 3rd ACM SIGPLAN International Workshop on the State of the Art in Java Program Analysis, pages 1–6, 2014.
  • [30] Li Li, Alexandre Bartel, Jacques Klein, Yves Le Traon, Steven Arzt, Siegfried Rasthofer, Eric Bodden, Damien Octeau, and Patrick Mcdaniel. I know what leaked in your pocket: Uncovering privacy leaks on Android apps with static taint analysis. arXiv preprint arXiv:1404.7431, 2014.
  • [31] Michael C Grace, Yajin Zhou, Zhi Wang, and Xuxian Jiang. Systematic detection of capability leaks in stock Android smartphones. In NDSS, volume 14, page 19, 2012.
  • [32] Soo Hyeon Kim, Daewan Han, and Dong Hoon Lee. Predictability of android OpenSSL’s pseudo random number generator. In Proceedings of the 2013 ACM SIGSAC conference on Computer & Communications Security, pages 659–668, 2013.
  • [33] Manuel Egele, David Brumley, Yanick Fratantonio, and Christopher Kruegel. An empirical study of cryptographic misuse in android applications. In Proceedings of the 2013 ACM SIGSAC conference on Computer & communications security, pages 73–84, 2013.
  • [34] Tongxin Li, Xiaoyong Zhou, Luyi Xing, Yeonjoon Lee, Muhammad Naveed, XiaoFeng Wang, and Xinhui Han. Mayhem in the push clouds: Understanding and mitigating security hazards in mobile push-messaging services. In Proceedings of the 2014 ACM SIGSAC Conference on Computer and Communications Security, pages 978–989, 2014.
  • [35] Kangjie Lu, Zhichun Li, Vasileios P Kemerlis, Zhenyu Wu, Long Lu, Cong Zheng, Zhiyun Qian, Wenke Lee, and Guofei Jiang. Checking more and alerting less: Detecting privacy leakages via enhanced data-flow analysis and peer voting. In NDSS, 2015.
  • [36] Rahul Pandita, Xusheng Xiao, Wei Yang, William Enck, and Tao Xie. WHYPER: Towards automating risk assessment of mobile applications. In 22nd USENIX Security Symposium (USENIX Security 13), pages 527–542, Washington, D.C., August 2013. USENIX Association.
  • [37] Sascha Fahl, Marian Harbach, Marten Oltrogge, Thomas Muders, and Matthew Smith. Hey, you, get off of my clipboard. In International Conference on Financial Cryptography and Data Security, pages 144–161. Springer, 2013.
  • [38] Yousra Aafer, Nan Zhang, Zhongwen Zhang, Xiao Zhang, Kai Chen, XiaoFeng Wang, Xiaoyong Zhou, Wenliang Du, and Michael Grace. Hare hunting in the wild Android: A study on the threat of hanging attribute references. In Proceedings of the 22nd ACM SIGSAC Conference on Computer and Communications Security, pages 1248–1259, 2015.
  • [39] Zhengyang Qu, Vaibhav Rastogi, Xinyi Zhang, Yan Chen, Tiantian Zhu, and Zhong Chen. Autocog: Measuring the description-to-permission fidelity in Android applications. In Proceedings of the 2014 ACM SIGSAC Conference on Computer and Communications Security, pages 1354–1365, 2014.
  • [40] Baozheng Liu, Chao Zhang, Guang Gong, Yishun Zeng, Haifeng Ruan, and Jianwei Zhuge. FANS: Fuzzing Android native system services via automated interface analysis. In 29th USENIX Security Symposium (USENIX Security 20), pages 307–323. USENIX Association, August 2020.
  • [41] Yousra Aafer, Wei You, Yi Sun, Yu Shi, Xiangyu Zhang, and Heng Yin. Android SmartTVs vulnerability discovery via log-guided fuzzing. In 30th USENIX Security Symposium (USENIX Security 21). USENIX Association, August 2021.
[Uncaptioned image] Chaoran Li received the Bachelor of Information Technology degree from Deakin University Australia in 2018. He is currently working towards the Ph.D. degree at Swinburne University of Technology. His research interests include machine learning, especially in adversarial deep learning.
[Uncaptioned image] Xiao Chen is a research fellow with the Department of Software Systems and Cybersecurity, Faculty of IT, Monash University. He received Ph.D. degree from Swinburne University of Technology, Australia. His research interests include mobile software analysis, mobile security, and adversarial machine learning.
[Uncaptioned image] Ruoxi Sun received the Master of Computing and Innovation degree from the University of Adelaide in 2018. He is currently working towards the Ph.D. degree at the University of Adelaide. His research interests include mobile security and privacy, IoT security, and adversarial machine learning.
[Uncaptioned image] Jason Xue is a (continuing) Lecturer (a.k.a. Assistant Professor) of School of Computer Science at the University of Adelaide. He is also an Honorary Lecturer with Macquarie University. Previously, he was a Research Fellow with Macquarie University and a visiting research scientist at CSIRO-Data61 at Sydney, Australia. His current research interests are machine learning security and privacy, system and software security, and Internet measurement. He is the recipient of the ACM SIGSOFT distinguished paper award and IEEE best paper award, and his work has been featured in the mainstream press, including The New York Times, Science Daily, PR Newswire, Yahoo, The Australian Financial Review, and The Courier. He co-chaired the 1st IEEE AI4MOBILE workshop and the 1st IEEE MASS workshop on Smart City Security and Privacy. He currently serves on the Program Committee of IEEE Symposium on Security and Privacy (Oakland) 2021, ACM CCS 2021, USENIX Security 2021, 2022, NDSS 2021, 2022, IEEE/ACM ICSE 2021, 2022, PETS 2021, 2022, ESORICS 2021, and ACM ASIACCS 2021. He is a member of both ACM and IEEE.
[Uncaptioned image] Sheng Wen received his Ph.D. degree from Deakin University, Australia, in October 2014. Currently he is a senior lecturer in Swinburne University of Technology. He has received over 3 million Australia Dollars funding from both academia and industries since 2014. He is also leading a medium-size research team in cybersecurity area. He has published more than 50 high-quality papers in the last six years in the fields of information security, epidemic modelling and source identification. His representative research outcomes have been mainly published on top journals, such as IEEE Transactions on Computers (TC), IEEE Transactions on Parallel and Distributed Systems (TPDS), IEEE Transactions on Dependable and Secure Computing (TDSC), IEEE Transactions on Information Forensics and Security (TIFS), and IEEE Communication Survey and Tutorials (CST). His research interests include social network analysis and system security.
[Uncaptioned image] Muhammad Ejaz Ahmed received the M.S. degree in information technology from the National University of Sciences and Technology (NUST), Islamabad, Pakistan, in 2011, and the Ph.D. degree in wireless communication from the Kyung Hee University, South Korea, in 2014. From 2014 to 2015, he was a Post-Doctoral Researcher with the Pohang University of Science and Technology (POSTECH). From 2015 to 2018, he was a Research Professor with the Department of Electrical and Computer Engineering, Sungkyunkwan University (SKKU), South Korea. He is currently a Research Scientist with Data61, CSIRO, Australia. His current research interests include continuous authentication, data-driven security, malware analysis, applied machine learning, and network security.
[Uncaptioned image] Seyit Camtepe is a senior research scientist at CSIRO Data61. He received the Ph.D. degree in computer science from Rensselaer Polytechnic Institute, New York, USA, in 2007. From 2007 to 2013, he was with the Technische Universitaet Berlin, Germany, as a Senior Researcher and Research Group Leader in Security. From 2013 to 2017, he worked as a lecturer at the Queensland University of Technology, Australia. His research interests include Pervasive security covering the topics autonomous security, malware detection and prevention, attack modelling, applied and malicious cryptography, smartphone security, IoT security, industrial control systems security, wireless physical layer security.
[Uncaptioned image] Yang Xiang received his PhD in Computer Science from Deakin University, Australia. He is currently a full professor and the Dean of Digital Research & Innovation Capability Platform, Swinburne University of Technology, Australia. His research interests include cyber security, which covers network and system security, data analytics, distributed systems, and networking. He is also leading the Blockchain initiatives at Swinburne. In the past 20 years, he has been working in the broad area of cyber security, which covers network and system security, AI, data analytics, and networking. He has published more than 300 research papers in many international journals and conferences. He is the Editor-in-Chief of the SpringerBriefs on Cyber Security Systems and Networks. He serves as the Associate Editor of IEEE Transactions on Dependable and Secure Computing, IEEE Internet of Things Journal, and ACM Computing Surveys. He served as the Associate Editor of IEEE Transactions on Computers and IEEE Transactions on Parallel and Distributed Systems. He is the Coordinator, Asia for IEEE Computer Society Technical Committee on Distributed Processing (TCDP). He is a Fellow of the IEEE.