This repository contains code for an Android JVMTI agent that can be attached to an app in order to instrument it for AFL-style code coverage.
It consists of two portions, Java code in the runtime_java
folder that gets called at runtime
when a basic block is hit.
The code to add this call is generated in runtime_cpp
which is a JVMTI agent with a
ClassFileLoadHook
that transforms dex files when they are loaded. In particular it adds a call
to Instrumentation.reachedBlock(blockId)
. It also adds the java code to the classpath so it can
be loaded by the app at runtime.
Normally you can build by importing the project into Android Studio and building. On the command line:
(Replace ANDROID_SDK_ROOT
with your actual Android SDK folder)
set ANDROID_SDK_ROOT=%APPDATA%\Local\Android\Sdk
gradlew.bat assemble
ANDROID_SDK_ROOT=/path/to/sdk ./gradlew assemble
The deployer
folder in this project contains a convenience application to push the CoverageAgent
to an Android device using adb
.
gradle run --args="your.android.package.name"
It will locate the app's data directory and push the coverage agent into the
DATA_DIR/code_cache/startup_agents
directory.
It will also make all Android Runtimes on the phone debuggable by setting the
dalvik.vm.dex2oat-flags
property to --debuggable
. After this, you should be able to launch
the app while instrumenting coverage with:
am start-activity --attach-agent /path/to/libcoverage.so your.android.package.name/.app.MainActivity
Note: this is probably wrong and not needed
If you are trying to instrument apps that don't have the android:debuggable
attribute set and you
want to use the code_cache/startup_agents
to attach it on every launch. You must ensure
you have root access on the device and ro.debuggable
is set. The deployer can toggle the
debuggable bit in the system process. Firstly, ensure that
setprop persist.debug.dalvik.vm.jdwp.enabled 1
is set and restart the device after setting this property.
Next, invoke the deployer with the --force-debuggable
to have it deploy the coverage agent and
flip the debug bit for you.
gradle run --args="your.android.package.name --force-debuggable"