Dexpler: A Dalvik to Soot Jimple Translator

Welcome to Dexpler's Webpage!

Welcome to Dexpler's webpage! Dexpler is a submodule for Soot (a framework for Java program analysis) which converts Dalvik bytecode to Jimple, Soot's internal representation. Following is a tutorial to help you start working with Dexpler.

If you use Dexpler in your research you can cite the following paper:

• A. Bartel, J. Klein, M. Monperrus, Y. Le Traon: Dexpler: Converting Android Dalvik Bytecode to Jimple for Static Analysis with Soot, in SOAP workshop, ACM Sigplan International Workshop on the State Of The Art in Java Program Analysis (2012), Beijing, June 14th 2012. [bib] [pdf]

Tutorial: Analyzing an Android Application With Soot / Dexpler

Read This First

Be sure to first read Soot's documentation available here to familiarize yourself with Soot. Browse Soot's mailing-list if you encounter difficulties: your problem has probably already a solution!

Have a look at Eric Bodden's blog post which describes how to instrument Android applications (Soot can also generate Dalvik bytecode).

Step 1: Download and Compile Soot

The easiest way to compile Soot is by executing a script available here. If you prefer to do it manually continue reading.
$ git clone https://github.com/Sable/soot.git
$ git branch -f develop origin/develop
$ git checkout develop
$ cp ant.settings.template ant.settings

At this point you have to install Soot dependencies hero, jasmin and polyglot and update the ant.settings file. For instance:

$ cat ant.settings
[...]
polyglot.jar=${user.home}/jar/soot/polyglotclasses-1.3.5.jar
jasmin.jar=${user.home}/src/jasmin-2.4.0/lib/jasminclasses-2.4.0.jar
heros.jar=../heros/heros-trunk.jar
[...]

Now you can compile Soot.

$ ant fulljar
[...]
BUILD SUCCESSFUL
Total time: 11 seconds
$

Step 2: Bash Script to Launch Soot

Soot has a lot of command line options. Thus, we create a small script to ease Soot's configuration and launching.
#!/bin/bash

ANDROID_JARS_PATH="/home/alex/jar/android/platforms/"
JAVA_CLASSPATH="\
/home/alex/src/soot.github/lib/soot-trunk.jar:\
/home/alex/src/soot.github/libs/AXMLPrinter2.jar:\
/home/alex/jar/baksmali-1.3.2.jar:\
"

APK_FILE=$1
SOOT_OUT_DIR=$2

PROCESS_THIS=" -process-dir $APK_FILE" 
SOOT_CLASSPATH="\
"${APK_FILE}":\
"
SOOT_CMD="soot.Main \
 -d $SOOT_OUT_DIR \
 -android-jars $ANDROID_JARS_PATH \
 -allow-phantom-refs \
 -src-prec apk \
 -ire \
 $PROCESS_THIS
"

java \
 -Xss50m \
 -Xmx1500m \
 -classpath  ${JAVA_CLASSPATH} \
 ${SOOT_CMD}\

You have to update ANDROID_JARS_PATH and JAVA_CLASSPATH with paths to jars on your system. Once you have done the update, save the script to runSootOnApk.sh and make it executable:

$ chmod u+x runSootOnApk.sh

Step 3: Convert Dalvik to Jimple using Soot

We use the snake.apk as the target Android application. Launch the script as follows:

$ mkdir ./out/
$ ./runSootOnApk.sh ./snake.apk ./out/

Soot should output something similar to the following:

Soot started on Mon Jan 28 10:37:39 CET 2013 
Could not find sdk version in Android manifest! Using default: 15
Using '/home/alex/jar/android/platforms//android-15/android.jar' as android.jar
[...]
Transforming com.example.android.snake.SnakeView... 
Transforming com.example.android.snake.SnakeView$RefreshHandler... 
[...]
Writing to ./out/com/example/android/snake/SnakeView.class
Writing to ./out/com/example/android/snake/SnakeView$RefreshHandler.class
[...]
Soot finished on Mon Jan 28 10:18:46 CET 2013
Soot has run for 0 min. 4 sec.

As you can see Java class files are generated. To generate Jimple files, update the script to force Soot to output Jimple files (-f J):

SOOT_CMD="soot.Main \
 -d $SOOT_OUT_DIR \
 -android-jars $ANDROID_JARS_PATH \
 -allow-phantom-refs \
 -src-prec apk \
 -ire \
 -f J \
 $PROCESS_THIS
"

Save the updated script, then launch it. Soot now writes Jimple files:

[...]
Writing to ./out/com.example.android.snake.SnakeView.jimple
Writing to ./out/com.example.android.snake.SnakeView$RefreshHandler.jimple
[...]

Open ./out/com.example.android.snake.Snake.jimple. It should look similar to the following code snippet:

public class com.example.android.snake.Snake extends android.app.Activity
{
[...]
    protected void onPause()
    {
        com.example.android.snake.Snake $r0;
        com.example.android.snake.SnakeView $r1;

        $r0 := @this: com.example.android.snake.Snake;
        specialinvoke $r0.<android.app.Activity: void onPause()>();
        $r1 = $r0.<com.example.android.snake.Snake: com.example.android.snake.SnakeView mSnakeView>;
        virtualinvoke $r1.<com.example.android.snake.SnakeView: void setMode(int)>(0);
        return;
    }
[...]
}

Soot outputs one Jimple file per class. Each Jimple file contains the class declaration and its methods with their Jimple statements.

Step 4: Generate a Jimple Control Flow Graph

In runSootOnApk.sh replace:

SOOT_CMD="soot.Main \
 -d $SOOT_OUT_DIR \
 -android-jars $ANDROID_JARS_PATH \
 -allow-phantom-refs \
 -src-prec apk \
 -ire \
 -f J \
 $PROCESS_THIS
"

by:

SOOT_CMD="soot.tools.CFGViewer \
 --graph=CompleteBlockGraph \
 -d $SOOT_OUT_DIR \
 -android-jars $ANDROID_JARS_PATH \
 -allow-phantom-refs \
 -src-prec apk \
 -ire \
 -f J \
 $PROCESS_THIS
"

Save and launch the script. Soot generates a dot file for every method, and outputs the following:

[...]
Transforming com.example.android.snake.Snake... 
Generate dot file in ./out//void ().dot
Generate dot file in ./out//void ().dot
Generate dot file in ./out//void onSaveInstanceState(android.os.Bundle).dot
Generate dot file in ./out//void onCreate(android.os.Bundle).dot
Generate dot file in ./out//void onPause().dot
[...]

One dot file is the graphical representation of a control flow graph for one method. Convert one dot file to pdf using Graphviz:

$ dot -Tpdf out/void\ updateWalls\(\).dot  > ./out/void\ updateWalls\(\).dot.pdf

The resulting pdf file should look like this:

Error Messages

Path to Android Jars Missing

Exception in thread "main" java.lang.RuntimeException: You are analyzing an Android application but did not define android.jar. Options -android-jars or -force-android-jar should be used.
  at soot.Scene.defaultClassPath(Scene.java:396)
  at soot.Scene.getSootClassPath(Scene.java:220)
  at soot.SootResolver.(SootResolver.java:79)
  at soot.Singletons.soot_SootResolver(Singletons.java:795)
  at soot.SootResolver.v(SootResolver.java:89)
  at soot.Scene.tryLoadClass(Scene.java:577)
  at soot.Scene.loadBasicClasses(Scene.java:1149)
  at soot.Scene.loadNecessaryClasses(Scene.java:1220)
  at soot.Main.run(Main.java:167)
  at soot.Main.main(Main.java:141)

If you are analyzing an Android application you must specify the directory containing the Android system jar files. You can download those files here.

Reserved Characters in .dex or .apk Path

Exception in thread "main" java.lang.RuntimeException: only one Android application can be analyzed when using option -android-jars.                                                                                               
  at soot.Scene.defaultClassPath(Scene.java:413)
  at soot.Scene.getSootClassPath(Scene.java:220)
  at soot.SootResolver.(SootResolver.java:79)
  at soot.Singletons.soot_SootResolver(Singletons.java:801)
  at soot.SootResolver.v(SootResolver.java:89)
  at soot.Scene.tryLoadClass(Scene.java:577)
  at soot.Scene.loadBasicClasses(Scene.java:1149)
  at soot.Scene.loadNecessaryClasses(Scene.java:1220)
  at soot.Main.run(Main.java:167)
  at soot.Main.main(Main.java:141)

The path to an .apk file must not contain the reserved character ':' (colon) since it is used to separate elements in the class path. For instance, path /a/b/c/d/v2:com.wAngryBirdsRio:1:1.apk is not accepted since in contains the reserved character. In that case the application must be renamed ,for example to /a/b/c/d/v2_com.wAngryBirdsRio_1_1.apk, before Soot can process it.