Prerequisites

Download and install the following:
Eclipse
Java
SCanDroid - Directions on how to set up the environment, libraries and running the code is located in the SCanDroid github readme.
Maven

Overview

SCanDroid is a static analysis tool for android applications. It uses IBM's WALA framework and does the static analysis directly with dalvik bytecode. Currently it is set up to do taint tracking analysis, though it can be easily modified to do other types of static analysis as well.

Traditional Android applications are installed and run on an Android OS. Traditional desktop applications are normally started with some type of main() function, however there is no traditional main() in Android applications. These applications interact with the Android framework and rely on it to invoke callback methods defined in the application. These callback methods are usually invoked in response to some type of event (like updated gps location, calls, or incoming text messages).


An android application registers callbacks with the android framework and sometimes may even transfer control to the framework to call an activity or callback method. If we wanted to track the complete controlflow of an Android application we would either a) need to use the main() method of the Android Framework as our entrypoint or b) somehow model how the framework handles an application. We found some viable candidates for option a which were subsequently able to enter the callbacks of an application that was added to the scope of our analysis, however we found that we needed some of WALA's reflection options turned on in order to do so. With these settings, just building the general call graph alone took at least a day with even the smallest of applications.


In this figure we use our model as a general entrypoint for our static analysis. The model is built by first scanning the android library/framework for all naming patterns that have classes that end with *Listener as well as all methods that start with the prefix on*. An Android Application which implement these* Listener interfaces or that define these on* methods have their callbacks registered in a general list in the android model. In this model we have a while loop which calls all the callback methods in our listin a giant switch table.

Setting up Sources and Sinks

A key file to look at in SCanDroid is the AndroidSpecs.java and the various source/sink spec classes located in the org.scandroid.spec package.

Sources
CallArgSourceSpec - A call to a method, where the arguments will be used as a source.
CallRetSourceSpec - A call to a method in which a return value will be used as the source.
EntryArgSourceSpec - Use the arguments of an entrypoint as a source.
StaticFieldSourceSpec - Mark static field as a source.

Sinks
CallArgSinkSpec - When a method is called, the arguments will be used as a sink.
EntryArgSinkSpec - Use the arguments of an entrypoint as a sink.
EntryExcSinkSpec - Exception thrown by an entrypoint as a sink.
EntryRetSinkSpec - Returned value of an entrypoint marked as a sink.
StaticFieldSinkSpec - Mark static field as a sink.

These various source and sink objects may be added to the AndroidSpecs.java file by modifying the sourceSpecs and sinkSpecs variables. For Example :


 1 static String lm = "Landroid/location/LocationManager";
 2 private static SourceSpec[]  sourceSpecs = {
 3    new CallRetSourceSpec(new MethodNamePattern(lm, "getLastKnownLocation"), null),
 4    new CallRetSourceSpec(new MethodNamePattern(lm, "getProvider"), null),
 5 };

  ...

10 static String sms = "Landroid/telephony/SmsManager";
11 private static SinkSpec[]  sinkSpecs = {
12    new CallArgSinkSpec(new MethodNamePattern(sms, "sendTextMessage"), null),
13    new CallArgSinkSpec(new MethodNamePattern(sms, "sendDataMessage"), null),
14 };


Notice in this example, we specify an array that contains a list of sources and a list of sinks. Here we are using the android.location.LocationManager class with the getLastKnownLocation and getProvider methods as possible sources. The 2nd argument to the CallRetSourceSpec is set to null to mark all the arguments as possible sources. If, on the otherhand, we would like to specify a specific argument like the first or second as a source then we may replace "null" with "new int[] {1}" or "new int[] {2}" respectively.

Example

Let's try running SCanDroid on an application found in Google Play. We will choose an open source application called Connectbot as our example because we can legally and easily look at the source code to verify our results.

First let's look through the source to see if we can find some potential sources and sinks to add to SCanDroid's source/sink specs. PubkeyListActivity.java seems to contain some interesting objects we can try to keep track of. A quick scan of the source leads me to believe that we can try tracking to see if the public keys are being stored in the public key database object properly. If we look at the code below, we can try to identify some potential sources for our public key objects.


297 @Override
298 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
299        // Create menu to handle deleting and editing pubkey
300        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
301        final PubkeyBean pubkey = (PubkeyBean) getListView().getItemAtPosition(info.position);
...

We then modify the AndroidSpecs.java file and add the following in our sourceSpecs variable to tag public key sources "new CallRetSourceSpec(new MethodNamePattern("Landroid/widget/ListView","getItemAtPosition"), null)". Next let's look for some proper sinks to see if the pubkey is flowing to the database call.


297 @Override
298 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
...
433        pubkeydb.savePubkey(pubkey);
...
463 }
...
501 private void readKeyFromFile(File file) {
...
550        pubkeydb.savePubkey(pubkey);

Modifying AndroidSpecs.java again, we add the following to sinkSpecs list, "new CallArgSinkSpec(new MethodNamePattern("Lorg/connectbot/util/PubkeyDatabase", "savePubkey"), new int[] { 1 })". Now we are tracking the pubkey object and seeing if it flows to the savePubkey method call for the PubkeyDatabase object.

Running SCanDroid with the following parameters produces some results showing that it was able to detect some initial taints specified by our specs, and that it also flowed into our specified sinks.

~> ant clean; ant build; ant jar; java -Xmx8g -jar sap.jar -a --summaries-file=data/MethodSummaries.xml --android-lib=data/android-2.3.7_r1.jar ConnectBot.apk