Foo-Manroot / apk-patcher

Takes an arbitrary Android app and injects a Frida Gadget. No third-party tools required
GNU General Public License v3.0
3 stars 4 forks source link
androguard android apk apkpatch baksmali frida jpype reverse-engineering smali

APK patcher

When trying to modify an android application, Frida comes really handy. However, on non-rooted devices it can sometimes be difficult to inject the gadget into the apk.

With single, fat, APKs, that's not much of an issue because there are already several tools that work really well, and it can also be done manually with apktool. This is in my experience less and less true, since I encounter every time more APKs that, one way or another, break something along the process. Since apktool decodes all resources, just a missing reference makes the whole process fail.

On the other hand, split APKs (those that come with not only a base.apk, but also other files like *_config.xxhdpi.apk et al.) are harder to recompile, because there are certain dependencies between those different files, and fixing all the resource IDs (which has to be done before apktool lets you merge all into a fat APK) is a pain that not always fully works.

This script aims to help with the injection task, by modifying the least amount of files possible so there are no issues later with the resources.

Install pre-requisites

It's advised to create a virtualenv to install the dependencies:

$ virtualenv venv
$ . venv/bin/activate
(venv) $ pip install -r requirements

Additionally, the following Java libraries must be present for the patcher to work end-to-end:

Usage

Just run the script and read the help message:

$ python apk-patcher.py -h
usage: APK patcher [-h] [-f FIX_MANIFEST] [-c GADGET_CONFIG] [-v] [-l frida_script] base_path

Script to automate the decompilation, patch and rebuild of any Android split applications (those apps that have base.apk, plus .config.<something>.apk) to inject the provided Frida script.

positional arguments:
  base_path             Common prefix for all the split apk files.
                        For example, if we have:
                          - com.example.1234.apk
                          - com.example.1234.config.armeabi_v7a.apk
                          - com.example.1234.config.en.apk
                          - com.example.1234.config.xxhdpi.apk

                        'base-name' must be "com.example.1234." (note the dot at the end)

options:
  -h, --help            show this help message and exit
  -f, --fix_manifest    If set, the script will attempt to modify AndroidManifest.xml to set extractNativeLibs=true.
                        ATTENTION: it may cause problems like 'INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION' on installation.
  -c GADGET_CONFIG, --config GADGET_CONFIG
                        Path to a custom Gadget config ( https://frida.re/docs/gadget/ )
  -v, --verbose         Increase the verbosity. Can be specified up to 3 times.
  -l frida_script, --load frida_script
                        The JS file to patch into the apk.

Comparison with other tools

There are other tools which aim to do the same thing. For example:

However, as far as my research goes, all of them rely on OS commands to execute the same tools in the background:

This poses two problems from my point of view:

  1. If one of those base tools fail (for example, zipalign on Kali has been giving me quite a lot of errors like undefined symbol), all tools will fail at the same step.
  2. Relying on executing OS commands poses the risk of something going wrong (for example, the output format changes slightly, and the parsing is off from there) without noticing, for example.

Therefore, I decided to implement all using those tools as libraries; or, when not possible, using alternative libraries which perform the same task.

Future work

If you want to contribute, you can take a look into the following open topics:

Aknowledgments

This tool wouldn't have been possible without the invaluable research and effort of the third-party libraries I'm relying on, besides the regular ones (Java and Python standard libs, requests, ...):