• No results found

Preprocessing

9.4 Analysis Tool

9.4.1 Preprocessing

On analyzing one Android app, we must deal with some special issues due to the Android platform design.

Specific Characteristics of the Android Framework

The following Android framework characteristics influence the static analysis of Android apps [306]: onCr eate() Activity starts onStart()

onResume() onPause() onStop() onDestr

oy()

Activity is running

Process is killed

Figure 9.6 – Methods controlling the Android activity lifecycle [186].

Component lifecycle modeling In contrast to common Java programs, Android apps are not stand-alone applications and consist of components, such as activities and services, which have a distinct lifecycle (Figure 9.6). The

corresponding lifecycle methods (i.e., onCreate(), onPause, onStart()) are triggered indirectly by the Android framework to handle the app’s execution [183]. This is essential for creating cohesive control-flow graphs which are often needed by further static analyses.

Program entry points Android apps consist of several activities and other components. They have no single main() method which indicates the program starting point. However, some tools like Soot need a "main"-method as input, so an artificial main method considering the components of an app has to be created.

Inter-Component Communication (ICC) The components of an Android app (i.e., activities and services) can interact via Intents [185]. This interaction has to be modeled to connect the control-flow graph of single components to a system dependence graph (SDG). This enables further analyses to work across components. 1 public c l a s s M y A c t i v i t y extends A c t i v i t y { 2 . . . 3 I n t e n t s e r v i c e I n t e n t = new I n t e n t ( t h i s , M y S e r v i c e . c l a s s ) ; 4 s t a r t S e r v i c e ( s e r v i c e I n t e n t ) ; 5 I n t e n t i n t e n t = new I n t e n t ( t h i s , S e c o n d A c t i v i t y . c l a s s ) ; 6 s t a r t A c t i v i t y ( i n t e n t ) ; 7 . . . 8 } 9 public c l a s s S e c o n d A c t i v i t y extends A c t i v i t y { 10 public void o n C r e a t e ( . . . ) {} 11 } 12 public c l a s s M y S e r v i c e extends S e r v i c e { 13 public void o n C r e a t e ( . . . ) {} 14 }

Listing 9.5 – Android ICC example.

User Interface (UI) callbacks The Android framework provides specific UI call- backs, e.g., to react on a user’s button click via onClick()-Listener or system events such as onCellStateChanged() [26, 356]. Similar to the lifecycle methods (Figure 9.6), these callbacks are called by the framework. Modeling these actions enhances also a created control-flow graph for further analyses.

1 protected void o n C r e a t e ( . . . ) {

2 Button b u t t o n = ( Button ) f i n d V i e w B y I d (R . i d . myButton ) ; 3 b u t t o n . s e t O n C l i c k L i s t e n e r (new View . O n C l i c k L i s t e n e r ( ) {

4 @Override

5 public void o n C l i c k ( View v ) {

6 h a n d l e B u t t o n C l i c k ( v ) ;

7 } } ) ;

8 }

9 public void h a n d l e B u t t o n C l i c k ( . . . ) { . . . }

Listing 9.6 – Android UI callback example.

Handler Android also provides a specific message mechanism for communicating through threads within an app. This mechanism is called Handler and enables threads to communicate through a shared Handler object.

9.4 – Analysis Tool

AsyncTask Another Android extension to multi-threading is called AsyncTask. This extension, for example, provides a way to communicate with a user interface thread in an asynchronous fashion. Handler and AsyncTask are triggered by calling specific methods through the Android framework, e.g., when on an AsyncTask object the execute() method is called the framework invokes implicitly four methods of that object [184]. Listing 9.7 shows an example of the AsyncTask usage. The onPreExecute() method is invoked to prepare items like a progress bar. The method onPreExecute() in line seven is implicitly called through the method call execute() on the DownloadTask object in line 3. Then, the doInBackground() method of that object is called to perform the background computation. Thereby the publishProgress() method can be used to trigger the method onProgressUpdate() do display the computation progress. Finally, the method onPostExecute() is called to pass back the computation result.

1 public c l a s s M y A c t i v i t y extends A c t i v i t y { 2 public void o n C r e a t e ( . . . ) {

3 new DownloadTask ( ) . e x e c u t e ( u r l 1 , u r l 2 , u r l 3 ) ;

4 }

5 }

6 c l a s s DownloadTask extends AsyncTask<URL, I n t e g e r , Long> {

7 protected void o n P r e E x e c u t e ( ) { . . . }

8 protected Long doInBackground (URL . . . u r l s )

9 { . . .

10 p u b l i s h P r o c e s s ( . . . )

11 }

12 protected void o n P r o g r e s s U p d a t e ( I n t e g e r . . . p r o g r e s s ) { . . . } 13 protected void o n P o s t E x e c u t e ( Long r e s u l t ) { . . . }

14 }

Listing 9.7 – Android AsyncTask example.

XML-Layout The user interface of Android apps is structured by layouts. These layouts can be declared via XML configuration files or Java code. The XML configuration can define UI elements which are used via string reference within Android components. The Android framework instantiates the defined UI elements itself. These defined elements have to be considered and modeled to provide a more complete analysis scenario for an app.

1 <Button a n d r o i d : i d="@+i d / myButton "

2 a n d r o i d : l a y o u t _ w i d t h=" wrap_content " 3 a n d r o i d : l a y o u t _ h e i g h t=" wrap_content " 4 a n d r o i d : t e x t="My B u t t o n "

5 a n d r o i d : o n C l i c k=" h a n d l e B u t t o n C l i c k " />

Listing 9.8 – Android XML layout example.

1 protected void o n C r e a t e ( . . . ) {

2 Button b u t t o n = ( Button ) f i n d V i e w B y I d (R . i d . myButton ) ;

3 }

4 public void h a n d l e B u t t o n C l i c k ( . . . ) { . . . }

The basic Soot tool does not provide such a simulation of Android-app behavior to be able to generate viable callgraph and pointer information [26]. Some tools simulate the Android framework behavior to enable static analyses for special purposes such as tainted flow or privacy leak analyses [26, 305, 356]. These tools, however, cannot be easily adapted to other analyses. Their modifications to simulate the Android framework are firmly woven into the analysis process and linked to the analysis goal, e.g., to find tainted flows. Thus, it is difficult or even impossible to reuse the Android framework simulation extensions and append new analyses (transformers) to the tool.

Our Approach

Due to the reasons above, we developed our own pre-analysis steps to simulate the Android app behavior, which is normally performed by the Android system, based on the work by Arzt et al. [26]. First, we collect all Android components (e.g., activities, services) that belong to the app. Then, we extract user interface events, which are declared in specific configuration XML files describing user interfaces, and their corresponding callbacks in source code (Figure 9.5, step 1 ). Based on this information we generate for each Android component a call sequence for user interface interaction and other system events. This step can be compared with the iterative approach by Arzt et al. [26]. The generated call sequences are integrated into a main method, which simulates the overall app lifecycle triggered by the Android framework. Also, we simulate the lifecycle of fragments, which represent a part of the user interface in an activity. In addition, our tool considers and simulates the following aspects:

Application Configuration Android provides the possibility to maintaining the global application state by subclassing the Application class [182]. This class is instantiated before any other activity or service of an application. It is started by the framework on calling the onCreate() method and can be used by services and activities through the getApplication() method which returns the Application object.

Fragment Lifecycle Similar to activities, fragments have a lifecycle with specific methods which are called by the Android Framework (Figure 9.7). A fragment declared in XML is bound statically to the activity that inflated the view which contains the fragment (Listings 9.10, 9.11, and 9.12). This often happens in the onCreate() method of an activity and the onAttach(), onCreate(), and onCreateView() methods of the fragment are called. After the activity’s onCreate() is finished, the fragment’s onActivityCreated() method is called. Then, specific activity methods trigger the lifecycle methods of the fragment (Figure 9.7). The Android framework controls all these actions. Fragments can also be added, replaced, and removed during a running activity. Therefore, a placeholder within the layout XML is declared by using the <FrameLayout> tag (Listing 9.13). The explicit adding, replacing, and

9.4 – Analysis Tool onCreate() Fragment onStart() onResume() onPause() onStop() onDestroy() Fragment is active Fragment is destroyed onAttach() onCreateView() onDestroyView() onDetach() FragmentTransaction add() replace (A with B) detach() on B on A attach() remove() onActivityCreated() 1 2 3 4 5 1 2 3 1 2 3 4 1 2 3 4 5 6 Activity onStart() onResume() onPause() onStop() Activity is running Pr ocess is killed onCreate() onDestroy()

called after onCr

eate()

triggers

Figure 9.7 – Overview of Activity and FragmentTransaction methods controlling the Fragment’s lifecycle. Fragment methods controlled via the Activity methods are highlighted with dashed arrows and the methods controlled via the FragmentTransaction object have solid arrows with numbers highlighting the call order.

removing actions through the FragmentTransaction object can be found and used to trigger relevant fragment methods (Listing 9.14). Problematic are the calls on a removed fragment when another fragment replaces it and when fragments are moved to a so-called backstack and being reused in the running activity. Due to its indirect addressing through the placeholder it is difficult to determine the actual object by using static analysis. Thus, we do not support these two scenarios.

1 public M y A c t i v i t y extends F r a g m e n t A c t i v i t y {

2 public void o n C r e a t e ( Bundle s a v e d I n s t a n c e S t a t e ) { 3 s e t C o n t e n t V i e w (R . l a y o u t . main_layout ) ;

4 . . .

5 }

6 }

Listing 9.10 – Embedding a Fragment statically by inflating an XML layout file.

1 <?xml version=" 1 . 0 " e n c o d i n g=" u t f −8" ?>

2 <L i n e a r L a y o u t x m l n s : a n d r o i d=" h t t p : // schemas . a n d r o i d . com/ apk / r e s / a n d r o i d "

3 . . . 4 <f r a g m e n t 5 a n d r o i d : n a m e="com . e x a m p l e . a n d r o i d . MyFragment " 6 a n d r o i d : i d="@+i d /myFragment" 7 . . . /> 8 </ L i n e a r L a y o u t>

Listing 9.11 – XML layout file using a fragment.

1 public c l a s s MyFragment extends Fragment {

2 @Override

3 public void onAttach ( . . . ) { . . . }

4 }

5

Listing 9.12 – A Fragment example class.

We currently support programmed Fragments controlled via the Transaction- Manager and its FragmentTransaction object (Figure 9.7) as well as the calling of fragment methods bound to an activity. This allows us to model the usage of fragments within activities partially and thereby to enhance the callgraph and point-to analysis.

1 <?xml v e r s i o n=" 1 . 0 " e n c o d i n g=" u t f −8"?>

2 <L i n e a r L a y o u t xmlns : a n d r o i d=" h t t p : / / schemas . a n d r o i d . com/ apk / r e s / a n d r o i d "

3 . . . 4 <FrameLayout 5 a n d r o i d : i d="@+i d / m y _ p l a c e h o l d e r " 6 a n d r o i d : l a y o u t _ w i d t h=" match_parent " 7 a n d r o i d : l a y o u t _ h e i g h t=" match_parent "> 8 </FrameLayout> 9 . . . 10 </L i n e a r L a y o u t >

Listing 9.13 – XML layout file using a placeholder for dynamically processed Fragments.

1 . . .

2 FragmentManager fragmentManager = getSupportFragmentManager ( ) ;

3 F r a g m e n t T r a n s a c t i o n f r a g m e n t T r a n s a c t i o n = fragmentManager . b e g i n T r a n s a c t i o n ( ) ;

4 MyFragment f r a g m e n t = new MyFragment ( ) ;

5 f r a g m e n t T r a n s a c t i o n . add (R . i d . m y _ p l a c e h o l d e r , f r a g m e n t ) ; // a d d s t h e f r a g m e n t 6 f r a g m e n t T r a n s a c t i o n . commit ( ) ; // e x e c u t e s t h e t r a n s a c t i o n

7 f r a g m e n t T r a n s a c t i o n . r e p l a c e (R . i d . my_placeholder , new MySecondFragment ( ) ) ; //

˓→ r e p l a c e s t h e c u r r e n t f r a g m e n t i n t h e p l a c e h o l d e r l o c a t i o n w i t h a new

˓→ f r a g m e n t

8 f r a g m e n t T r a n s a c t i o n . commit ( ) ; // e x e c u t e s t h e t r a n s a c t i o n

9 . . .

9.4 – Analysis Tool

Use Simulator Extracted API We extracted the android.jar files of running Android simulators for API level 3 to 18 to have fully implemented API information instead of stubs, which are usually included in the android.jar distributed by the Android SDK. The extracted android.jar files enhance the generated points-to-analysis information for used API objects.

Java Concurrency Concepts We also simulate framework features related to Java concurrency concepts, such as Runnable, Thread, TimerTask, ForkJoin, Callable, and ExecutorService. For example, the missing simulation of Runnable objects within the Soot tool are also added by calling a Runnable object’s “run” method after locating its “start” method [460] (Listing 9.15). This information enhances the constructed callgraph and points- to information.

1 . . .

2 new Runnable (new CustomRunnable ( ) ) . s t a r t ( ) ;

3 . . .

4 c l a s s CustomRunnable implements Runnable {

5 public void run ( ) { . . . }

6 }

7

Listing 9.15 – Runnable example