Androguard – Python tool to play with Android files

Androguard – Python tool to play with Android files

Androguard

Androguard is a full python tool to play with Android files. It is designed to work with Python 3 only.

  • DEX, ODEX
  • APK
  • Android’s binary XML
  • Android resources
  • Disassemble DEX/ODEX bytecodes
  • Decompiler for DEX/ODEX files

You can either use the CLI or graphical frontend for androguard, or use androguard purely as a library for your own tools and scripts.

Authors: Androguard Team

Androguard + tools: Anthony Desnos (desnos at t0t0.fr).

DAD (DAD is A Decompiler): Geoffroy Gueguen (geoffroy dot gueguen at gmail dot com)

Installation

There are several ways how to install androguard.

Before you start, make sure you are using a supported python version! For Windows, we recommend using the Anaconda python 3.6.x package.

Warning: The magic library might not work out of the box. If your magic library does not work, please refer to the installation instructions of python-magic.

PIP

The usual way to install python packages is by using pypi.python.org and it’s package installerpip. Just use:

$ pip install -U androguard[magic,GUI]

to install androguard including the GUI and magic file type detection. In order to use features that use dot, you need Graphviz installed. This is not a python dependency but a binary package! Please follow the installation instructions for GraphvizInstall.

You can also make use of anvirtualenv, to separate the installation from your system-wide packages:

$ virtualenv venv-androguard
$ source venv-androguard/bin/activate
$ pip install -U androguard[magic,GUI]

pip should install all required packages too.

Debian / Ubuntu

Debian has androguard in its repository. You can just install it using apt install androguard. All required dependencies are automatically installed.

Install from Source

Use git to fetch the sources, then install it. Please install git and python on your own. Androguard requires Python at least 3.4 to work. Pypy >= 5.9.0 should work as well but is not tested.

$ git clone --recursive https://github.com/androguard/androguard.git
$ cd androguard
$ virtualenv -p python3 venv-androguard
$ source venv-androguard/bin/activate
$ pip install .[magic,GUI]

The dependencies, defined in setup.py will be automatically installed.

For development purposes, you might want to install the extra dependencies fordocs andtests as well:

$ git clone --recursive https://github.com/androguard/androguard.git
$ cd androguard
$ virtualenv -p python3 venv-androguard
$ source venv-androguard/bin/activate
$ pip install -e .[magic,GUI,tests,docs]

You can then create a local copy of the documentation:

$ python3 setup.py build_sphinx

Which is generated in build/sphinx/html.

Getting Started

Using Androguard tools

There are already some tools for specific purposes.

To just decode the AndroidManifest.xml or resources.arsc, there areandroguard axml andandroguard arsc. To get information about the certificates useandroguard sign.

If you want to create call graphs, useandroguard cg, or if you want control flow graphs, you can useandroguard decompile.

Using Androlyze and the python API

The easiest way to analyze APK files is by using androguard analyze. It will start an iPython shell and has all modules loaded to get into action.

For analyzing and loading APK or DEX files, some wrapper functions exist. Use AnalyzeAPK(filename) or AnalyzeDEX(filename) to load a file and start analyzing it. There are already plenty of APKs in the androguard repo, you can either use one of those or start your own analysis.

$ androguard analyze
Androguard version 3.1.1 started
In [1]: a, d, dx = AnalyzeAPK("examples/android/abcore/app-prod-debug.apk")
# Depending on the size of the APK, this might take a while...

In [2]:

The three objects you get are a an APK object, d an array of DalvikVMFormat object and dx an Analysis object.

Inside the APK object, you can find all information about the APK, like the package name, permissions, the AndroidManifest.xml, or its resources.

The DalvikVMFormat corresponds to the DEX file found inside the APK file. You can get classes, methods, or strings from the DEX file. But when using multi-DEX APK’s it might be a better idea to get those from another place. The Analysis object should be used instead, as it contains special classes, which link information about the classes.dex and can even handle many DEX files at once.

Getting Information about an APK

If you have successfully loaded your APK using AnalyzeAPK, you can now start getting information about the APK.

For example, getting the permissions of the APK:

In [2]: a.get_permissions()
Out[2]:
['android.permission.INTERNET',
 'android.permission.WRITE_EXTERNAL_STORAGE',
 'android.permission.ACCESS_WIFI_STATE',
 'android.permission.ACCESS_NETWORK_STATE']

or getting a list of all activities, which are defined in the AndroidManifest.xml:

In [3]: a.get_activities()
Out[3]:
['com.greenaddress.abcore.MainActivity',
 'com.greenaddress.abcore.BitcoinConfEditActivity',
 'com.greenaddress.abcore.AboutActivity',
 'com.greenaddress.abcore.SettingsActivity',
 'com.greenaddress.abcore.DownloadSettingsActivity',
 'com.greenaddress.abcore.PeerActivity',
 'com.greenaddress.abcore.ProgressActivity',
 'com.greenaddress.abcore.LogActivity',
 'com.greenaddress.abcore.ConsoleActivity',
 'com.greenaddress.abcore.DownloadActivity']

Get the package name, app name, and path of the icon:

In [4]: a.get_package()
Out[4]: 'com.greenaddress.abcore'

In [5]: a.get_app_name()
Out[5]: u'ABCore'

In [6]: a.get_app_icon()
Out[6]: u'res/mipmap-xxxhdpi-v4/ic_launcher.png'

Get the numeric version and the version string, and the minimal, maximal, target and effective SDK version:

In [7]: a.get_androidversion_code()
Out[7]: '2162'

In [8]: a.get_androidversion_name()
Out[8]: '0.62'

In [9]: a.get_min_sdk_version()
Out[9]: '21'

In [10]: a.get_max_sdk_version()

In [11]: a.get_target_sdk_version()
Out[11]: '27'

In [12]: a.get_effective_target_sdk_version()
Out[12]: 27

You can even get the decoded XML for the AndroidManifest.xml:

In [15]: a.get_android_manifest_axml().get_xml()
Out[15]: '<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="2162" android:versionName="0.62" package="com.greenaddress.abcore">\n<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="27">\n</uses-sdk>\n<uses-permission android:name="android.permission.INTERNET">\n</uses-permission>\n<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">\n</uses-permission>\n<uses-permission android:name="android.permission.ACCESS_WIFI_STATE">\n</uses-permission>\n<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE">\n</uses-permission>\n<application android:theme="@7F0F0006" android:label="@7F0E001D" android:icon="@7F0D0000" android:debuggable="true" android:allowBackup="false" android:supportsRtl="true">\n<activity android:name="com.greenaddress.abcore.MainActivity">\n<intent-filter>\n<action android:name="android.intent.action.MAIN">\n</action>\n<category android:name="android.intent.category.LAUNCHER">\n</category>\n</intent-filter>\n</activity>\n<service android:name="com.greenaddress.abcore.DownloadInstallCoreIntentService" android:exported="false">\n</service>\n<service android:name="com.greenaddress.abcore.RPCIntentService" android:exported="false">\n</service>\n<service android:name="com.greenaddress.abcore.ABCoreService" android:exported="false">\n</service>\n<activity android:name="com.greenaddress.abcore.BitcoinConfEditActivity">\n<intent-filter>\n<category android:name="android.intent.category.DEFAULT">\n</category>\n<action android:name="com.greenaddress.abcore.BitcoinConfEditActivity">\n</action>\n</intent-filter>\n</activity>\n<activity android:name="com.greenaddress.abcore.AboutActivity">\n</activity>\n<activity android:label="@7F0E0038" android:name="com.greenaddress.abcore.SettingsActivity" android:noHistory="true">\n</activity>\n<activity android:label="@7F0E0035" android:name="com.greenaddress.abcore.DownloadSettingsActivity" android:noHistory="true">\n</activity>\n<activity android:theme="@7F0F0006" android:label="@7F0E0036" android:name="com.greenaddress.abcore.PeerActivity">\n</activity>\n<activity android:theme="@7F0F0006" android:label="@7F0E0037" android:name="com.greenaddress.abcore.ProgressActivity">\n</activity>\n<activity android:name="com.greenaddress.abcore.LogActivity">\n</activity>\n<activity android:name="com.greenaddress.abcore.ConsoleActivity">\n</activity>\n<activity android:name="com.greenaddress.abcore.DownloadActivity">\n</activity>\n<receiver android:name="com.greenaddress.abcore.PowerBroadcastReceiver">\n<intent-filter>\n<action android:name="android.intent.action.ACTION_POWER_CONNECTED">\n</action>\n<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED">\n</action>\n<action android:name="android.intent.action.ACTION_SHUTDOWN">\n</action>\n<action android:name="android.intent.action.ACTION_BATTERY_LOW">\n</action>\n<action android:name="android.net.wifi.STATE_CHANGE">\n</action>\n</intent-filter>\n</receiver>\n</application>\n</manifest>\n'

Or if you like to use the AndroidManifest.xml as an ElementTree object, use the following method:

In [13]: a.get_android_manifest_xml()
Out[13]: <Element manifest at 0x7f9d01587b00>

There are many more methods to explore, just take a look at the API for APK.

Using the Analysis object

The ~androguard.core.analysis.analysis.Analysis the object has all information about the classes, methods, fields and strings inside one or multiple DEX files.

Additionally, it enables you to get call graphs and crossreferences (XREFs) for each method, class, field and string.

This means you can investigate the application for certain API calls or create graphs to see the dependencies of different classes.

As a first example, we will get all classes from the Analysis:

In [2]: dx.get_classes()
Out[2]:
[<analysis.ClassAnalysis Ljava/io/FileNotFoundException; EXTERNAL>,
 <analysis.ClassAnalysis Landroid/content/SharedPreferences; EXTERNAL>,
 <analysis.ClassAnalysis Landroid/support/v4/widget/FocusStrategy$BoundsAdapter;>,
 <analysis.ClassAnalysis Landroid/support/v4/media/MediaBrowserCompat$MediaBrowserServiceCallbackImpl;>,
 <analysis.ClassAnalysis Landroid/support/transition/WindowIdImpl;>,
 <analysis.ClassAnalysis Landroid/media/MediaMetadataEditor; EXTERNAL>,
 <analysis.ClassAnalysis Landroid/support/v4/app/BundleCompat$BundleCompatBaseImpl;>,
 <analysis.ClassAnalysis Landroid/support/transition/MatrixUtils$1;>,
 <analysis.ClassAnalysis Landroid/support/v7/widget/ShareActionProvider;>,
 ...

As you can see, get_classes() returns a list of ClassAnalysis objects. Some of them are marked asEXTERNAL, which means that the source code of this class is not defined within the DEX files that are loaded inside the Analysis. For example the first class java.io.FileNotFoundException is an API class.

A ClassAnalysis does not contain the actual code but the ClassDefItem can be loaded using theget_vm_class():

In [5]: dx.get_classes()[2].get_vm_class()
Out[5]: <dvm.ClassDefItem Ljava/lang/Object;->Landroid/support/v4/widget/FocusStrategy$BoundsAdapter;>

If the class isEXTERNAL, a ExternalClass is returned instead.

The ClassAnalysis also contains all the information about XREFs, which are explained in more detail in the next section.

XREFs

Consider the following Java source code:

class Foobar {
    public int afield = 23;

    public void somemethod() {
        String astring = "hello world";
    }
}

class Barfoo {
    public void othermethod() {
        Foobar x = new Foobar();

        x.somemethod();

        System.out.println(x.afield);
    }
}

There are two classes and the class Barfoo instantiates the other class Foobar as well as calling methods and reading fields.

XREFs are generated for four things:

  • Classes
  • Methods
  • Fields
  • Strings

XREFs work in two directions:xref_from andxref_to.To means, that the current object is calling another object.From means, that the current object is called by another object.

All XREFs can be visualized as a directed graph and if some object A is contained in the xref_to, the called object will contain A in their xref_from.

In the case of our Java example, the string astring is called in Foobar.somethod, therefore it will be contained in the xref_to of Foobar.somethod.

The Field afield will be contained in the xref_to of Barfoo.othermethod as well as the call to Foobar.somethod.

More on XREFs can be found in xrefs.

Documentation

Find the documentation for master on ReadTheDocs.

There are some (probably broken/outdated) examples and demos in the folders demos and examples.

Projects using Androguard

In alphabetical order

You are using Androguard and are not listed here? Just create a ticket or send us a pull request with your project!