SideChannelMarvels / Tracer

Set of Dynamic Binary Instrumentation and visualization tools for execution traces.
GNU General Public License v3.0
297 stars 70 forks source link

Problems instrumenting Android applications #6

Open edermi opened 8 years ago

edermi commented 8 years ago

Currently I'm trying to trace Android applications on a real device (Nexus 6, rooted, Stock ROM Android 6). I'm running the valgrind build from the wiki page which works fine on preinstalled binaries and busybox, but when it comes to real android applications there are some problems.

Instrumenting an android application works roughly like described here: http://stackoverflow.com/questions/13531496/cant-run-a-java-android-program-with-valgrind/19235439#19235439

I've got this /data/local/start_valgrind.sh:

#!/system/bin/sh

PACKAGE="foo.bar.baz"

# TracerGrind
VGPARAMS='--kernel-variant=android-gpu-adreno3xx --trace-children=yes --tool=tracergrind --filter=foo.so --vex-iropt-register-updates=allregs-at-mem-access --output=/sdcard/foo.trace'

export TMPDIR=/data/data/$PACKAGE

exec /data/local/Inst/bin/valgrind $VGPARAMS $*

To actually run the application with valgrind attached to foo.so, it's required to disable SELinux via setenforce 0 because valgrind and SELinux do not seem to be best friends on Android 6. After that, setting PACKAGE="foo.bar.baz" and setprop wrap.$PACKAGE "logwrapper /data/local/start_valgrind.sh", starting the app on the phone brings up valgrind, too.

In logcat, I can see logs like those:

03-30 13:26:10.019 10502 10502 I start_valgrind.sh: disInstr(thumb): unhandled instruction: 0xDEFF 0x4620
03-30 13:26:10.027 10502 10502 I start_valgrind.sh: disInstr(thumb): unhandled instruction: 0xDEFF 0x461C
03-30 13:26:10.029 10502 10502 I start_valgrind.sh: disInstr(thumb): unhandled instruction: 0xDEFF 0x461D
03-30 13:26:10.054 10502 10502 I start_valgrind.sh: disInstr(thumb): unhandled instruction: 0xDEFF 0x48F8
03-30 13:26:10.058 10502 10502 I start_valgrind.sh: disInstr(thumb): unhandled instruction: 0xDEFF 0x686F
03-30 13:26:10.249 10502 10502 I start_valgrind.sh: disInstr(thumb): unhandled instruction: 0xDEFF 0x4B4C
03-30 13:26:10.342 10502 10502 I start_valgrind.sh: disInstr(thumb): unhandled instruction: 0xDEFF 0xF8DF

The recovered trace can not be decoded by text-/sqlitetrace, I'm getting errors like:

root@9bbb2997e81e ~ # Tracer/TracerGrind/sqlitetrace/sqlitetrace foo.trace foo.db
Invalid message of type 100 encountered.

The app I'm testing is proprietary from Google Play Store. I noticed this behaviour on different apps but if you require the name of this specific app I'm going to send you an E-Mail.

As I said, regular binaries work fine.

BTW, feel free to add the steps above to the wiki article's TODO-section :)

doegox commented 8 years ago

Thanks for your tests and reports @edermi ! Does it always fail or does it work for some apps and fails only when there are unhandled instructions?

edermi commented 8 years ago

So, I tried again today. I made a complete fresh build of Valgrind with latest NDK (r11b), this is the logcat when starting the app:

03-31 12:31:14.127 11357 11357 I start_valgrind.sh: ==11358== TracerGrind-1.4, TracerGrind tracing tool
03-31 12:31:14.127 11357 11357 I start_valgrind.sh: ==11358== Charles Hubain
03-31 12:31:14.127 11357 11357 I start_valgrind.sh: ==11358== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
03-31 12:31:14.128 11357 11357 I start_valgrind.sh: ==11358== Command: /system/bin/app_process32 /system/bin --application --nice-name=foo.bar.baz com.android.internal.os.WrapperInit 14 22 android.app.ActivityThread
03-31 12:31:14.128 11357 11357 I start_valgrind.sh: ==11358== 
03-31 12:31:14.401 11358 11358 W linker  : /data/local/Inst/lib/valgrind/vgpreload_core-arm-linux.so: unsupported flags DT_FLAGS_1=0x421
03-31 12:31:14.407 11357 11357 I start_valgrind.sh: WARNING: linker: /data/local/Inst/lib/valgrind/vgpreload_core-arm-linux.so: unsupported flags DT_FLAGS_1=0x421
03-31 12:31:19.629 11358 11358 D AndroidRuntime: >>>>>> START com.android.internal.os.RuntimeInit uid 10106 <<<<<<
03-31 12:31:19.773 11358 11358 D AndroidRuntime: CheckJNI is OFF
03-31 12:31:21.176 11357 11357 I start_valgrind.sh: disInstr(thumb): unhandled instruction: 0xDEFF 0x4A94
03-31 12:31:21.367 11357 11357 I start_valgrind.sh: disInstr(thumb): unhandled instruction: 0xDEFF 0x461C
03-31 12:31:21.484 11357 11357 I start_valgrind.sh: disInstr(thumb): unhandled instruction: 0xDEFF 0x4605
03-31 12:31:21.886 11357 11357 I start_valgrind.sh: disInstr(thumb): unhandled instruction: 0xDEFF 0x4ABA
03-31 12:31:21.906 11357 11357 I start_valgrind.sh: disInstr(thumb): unhandled instruction: 0xDEFF 0x6039
03-31 12:31:21.909 11357 11357 I start_valgrind.sh: disInstr(thumb): unhandled instruction: 0xDEFF 0xF8DF
03-31 12:31:22.064 11357 11357 I start_valgrind.sh: disInstr(thumb): unhandled instruction: 0xDEFF 0x4868

After that, those errors repeat but the app seems to work. The trace is still not usable.

I also tried with vim touch from F-Droid which throws the same errors when filtering on libvimtouch.so

edermi commented 8 years ago

Today I tried the native activity example, compiled with latest stable Android Studio (1.5.1) and NDK 11 using default settings (I shortened the package name in order to attach valgrind, but apart from that the code can be found 1:1 on github).

The example works but the same errors occur. I'm still on a Nexus 6 with rooted Stock Android 6. I attached the trace, maybe it's helpful foo.trace.zip

doegox commented 8 years ago

thanks! didn't have the time to follow up yet, sorry

edermi commented 8 years ago

No problem!

It seems that some binaries of the system are affected as well. The simplest way to reproduce it and get a clean output seems to be running dex2oat:

/data/local/Inst/bin/valgrind --trace-children=yes --tool=tracergrind --filter=0x000000-0x200000 --output=/sdcard/foo.trace dex2oat --dex-file=/sdcard/classes.dex --oat-file=/sdcard/classes.oat

classes.dex may be obtained by simply unzipping any Android apk and pushing it to the device. Filters may be set appropriate du get something in the trace.

This gives the following output:

==8939== TracerGrind-1.4, TracerGrind tracing tool
==8939== Charles Hubain
==8939== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==8939== Command: dex2oat --dex-file=/sdcard/classes.dex --oat-file=/sdcard/classes.oat
==8939== 
==8939== Filtering address range from 0x0000000000000000 to 0x0000000000020000
WARNING: linker: /data/local/Inst/lib/valgrind/vgpreload_core-arm-linux.so: unsupported flags DT_FLAGS_1=0x421
disInstr(thumb): unhandled instruction: 0xDEFF 0xF8DF
disInstr(thumb): unhandled instruction: 0xDEFF 0x461C
disInstr(thumb): unhandled instruction: 0xDEFF 0x461D
disInstr(thumb): unhandled instruction: 0xDEFF 0xF8DF
disInstr(thumb): unhandled instruction: 0xDEFF 0x460E
disInstr(thumb): unhandled instruction: 0xDEFF 0x9505
disInstr(thumb): unhandled instruction: 0xDEFF 0x4B15
disInstr(thumb): unhandled instruction: 0xDEFF 0x4915
disInstr(thumb): unhandled instruction: 0xDEFF 0x4B1F
disInstr(thumb): unhandled instruction: 0xDEFF 0x4A20
disInstr(thumb): unhandled instruction: 0xDEFF 0x4ACA
disInstr(thumb): unhandled instruction: 0xDEFF 0x4605
disInstr(thumb): unhandled instruction: 0xDEFF 0x4605
disInstr(thumb): unhandled instruction: 0xDEFF 0x930B
disInstr(thumb): unhandled instruction: 0xDEFF 0x4607
disInstr(thumb): unhandled instruction: 0xDEFF 0x48A9
disInstr(thumb): unhandled instruction: 0xDEFF 0x9309
disInstr(thumb): unhandled instruction: 0xDEFF 0x461D
disInstr(thumb): unhandled instruction: 0xDEFF 0xF8DF
disInstr(thumb): unhandled instruction: 0xDEFF 0x4605
disInstr(thumb): unhandled instruction: 0xDEFF 0x469A
disInstr(thumb): unhandled instruction: 0xDEFF 0x4605
disInstr(thumb): unhandled instruction: 0xDEFF 0xF8DF
disInstr(thumb): unhandled instruction: 0xDEFF 0x4699
disInstr(thumb): unhandled instruction: 0xDEFF 0xF8DF
disInstr(thumb): unhandled instruction: 0xDEFF 0x469A
disInstr(thumb): unhandled instruction: 0xDEFF 0x9306
disInstr(thumb): unhandled instruction: 0xDEFF 0xF8DF
disInstr(thumb): unhandled instruction: 0xDEFF 0x469A
disInstr(thumb): unhandled instruction: 0xDEFF 0x469A
disInstr(thumb): unhandled instruction: 0xDEFF 0x469A
disInstr(thumb): unhandled instruction: 0xDEFF 0x2000
disInstr(thumb): unhandled instruction: 0xDEFF 0xE9CD
disInstr(thumb): unhandled instruction: 0xDEFF 0x4605
==8939== 
edermi commented 8 years ago

I tested everything on different devices and older Android versions. On Nexus 4 with Stock Android 4.4.4 and on Galaxy Nexus with CyanogenMod 11 (based on 4.4.4), I get one single I/start_valgrind.sh( 2959): disInstr(thumb): unhandled instruction: 0x4771 0x5F43 when instrumenting an application. The app is starting fine but when converting the trace with sqlitetrace or texttrace, I still get Invalid message of type 100 encountered.

haxelion commented 7 years ago

There was recently an update of valgrind with the version 3.12. It might be interesting to retest the tracer with this version.