Valerio `sid` Costamagna bio photo

Valerio `sid` Costamagna

“It’s no use going back to yesterday, because I was a different person then.” ― Lewis Carroll, Alice in Wonderland

Email Twitter Github

Google has replaced (AOSP commit) the Dalvik (DVM) runtime with the ART runtime as default from Android 5.0. ART introduces Ahead-of-time (AOT) compilation at installation time by compiling applications using the on-device dex2oat tool.

ART uses two new file formats:

  • .ART: only one file, boot.art in “/system/framework/<arch>”. Image file with a heap of preinitialized classes and objects
  • .OAT: Master file boot.oat in “/system/framework/<arch>”. Compiled application will be saved as OAT file.

dex2oat compiles a DEX file in input to an OAT file, so the compiled application is device-dependent. The resulting OAT file will be generated inside the “/data/dalvik-cache/<arch>” folder, where <arch> is the target architecture of the compilation. (i.e. architecture of the device).

OAT file format is developed by Google, and it is embedded into an ELF. An OAT file contains DEX code, compiled native code and metadata. OAT files are loaded in application virtual memory like a shared object.

Android framework JARs are compiled at the first step of device booting (maybe OEM devices can act differently). The outputs of compiling are boot.art (the image file) and boot.oat. The boot.art is placed in memory right before the boot.oat, which links to it.

My helpful screenshot

Runtime flow is showed in the following figure:

asd

This journey into ART runtime is focused on discover how Java virtual methods are called and managed by the runtime.

ART Data Struct

The ART runtime is written in C++, and we are going to exploits ART’s data structures for hooking Java virtual methods by vtable tampering.

For our scope, some useful ART Data Structures (ADS) are:

  1. Class (androidxref)
  2. ArtMethod (androidxref)

The Class data structure define the Java classes memory-layout, the following two members are used to lookup virtual methods:

1
2
3
4
5
6
7
8
1220  // Virtual method table (vtable), for use by "invoke-virtual".  The vtable from the superclass is
1221  // copied in, and virtual methods from our class either replace those from the super or are
1222  // appended. For abstract classes, methods may be created in the vtable that aren't in
1223  // virtual_ methods_ for miranda methods.
1224  HeapReference<PointerArray> vtable_;

1246  // Virtual methods defined in this class; invoked through vtable. Pointer to an ArtMethod array.
1247  uint64_t virtual_methods_;

The vtable_ is a reference to an array of pointers. Each array element is a pointer to a virtual method defined inside that Java class or to a virtual method from the superclass. Instead, virtual_methods_ is a reference to an array of pointers to virtual methods defined inside that class, adn each element is a pointer to an ArtMethod object.

ArtMethod is the C++ class which defines the Java methods memory-layout. The interesting elements are:

1
2
3
4
5
6
7
544  GcRoot<mirror::Class> declaring_class_;
552  // Access flags; low 16 bits are defined by spec.
553  uint32_t access_flags_;
565  // Entry within a dispatch table for this method. For static/direct methods the index is into
566  // the declaringClass.directMethods, for virtual methods the vtable and for interface methods the
567  // ifTable.
568  uint32_t method_index_;

declaring_class_, line 544, is a reference to the class whithin method is defined. The access_flags_ is used for set the class visibility (public, static, native, interface, etc..) and method_index_ is the method’s index value inside vtable_.

Before starting the real fun, let me introduce my debugging envinronment.

Debugging tips

I suggest to you to use Ubuntu for building from AOSP ( or debian is likely as well). I used a Nexus6 with AOSP,my running version at the writing time is 5.1.1.

I’m going to use GDB as debugger, and radare is a very good alternative, with AOSP symbols. Create a directory with links to AOSP symbols, like the following:

1
2
3
4
5
6
7
8
9
10
lrwxrwxrwx 1 root root   72 gen 23 15:46 app_process32 -> symbols/system/bin/app_process32
lrwxrwxrwx 1 root root   76 gen 23 15:45 libandroidfw.so -> symbols/system/lib/libandroidfw.so
lrwxrwxrwx 1 root root   88 gen 23 15:45 libandroid_runtime.so -> symbols/system/lib/libandroid_runtime.so
lrwxrwxrwx 1 root root   64 gen 23 15:45 libart.so -> symbols/system/lib/libart.so
lrwxrwxrwx 1 root root   60 gen 23 15:44 libc.so -> symbols/system/lib/libc.so
lrwxrwxrwx 1 root root   70 gen 23 15:45 libcutils.so -> symbols/system/lib/libcutils.so
lrwxrwxrwx 1 root root   64 gen 23 15:45 liblog.so -> symbols/system/lib/liblog.so
lrwxrwxrwx 1 root root   70 gen 23 15:44 libstdc++.so -> symbols/system/lib/libstdc++.so
lrwxrwxrwx 1 root root   68 gen 23 15:45 libutils.so -> symbols/system/lib/libutils.so
lrwxrwxrwx 1 root root   58 gen 23 15:45 linker -> symbols/system/bin/linker

Create a file with the following GDB command:

1
2
target remote :1337
set solib-search-path .

Port 1337 will be used for connecting to the debugger instance running on the device. We have to forward this port by using adb with running the following command:

1
adb forward tcp:1337 tcp:1337

Hands on debugger

A Java class loaded in memory has a structure like the following one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(gdb) p/x *(art::mirror::Class*) 0x70377fc0
$48 = {
	[...]
  members of art::mirror::Class:  
  [...]
  direct_methods_ = {
    <art::mirror::ObjectReference<false, art::mirror::ObjectArray<art::mirror::ArtMethod> >> = {
      reference_ = 0x700ec788
    }, <No data fields>}, 
  [...]
  virtual_methods_ = {
    <art::mirror::ObjectReference<false, art::mirror::ObjectArray<art::mirror::ArtMethod> >> = {
      reference_ = 0x700ed158
    }, <No data fields>}, 
  vtable_ = {
    <art::mirror::ObjectReference<false, art::mirror::ObjectArray<art::mirror::ArtMethod> >> = {
      reference_ = 0x0
    }, <No data fields>},   
  access_flags_ = 0x80001, 
  class_size_ = 0x604,  
  object_size_ = 0x10, 
  status_ = 0xa, 
  [...]
}

virtual_methods_ is a reference to an “art::mirror::ObjectArray<art::mirror::ArtMethod> »”: an array of ArtMethod objects.

1
2
3
4
5
(gdb) p/x ((art::mirror::Class *)0x7110bf10)->virtual_methods_
$20 = {
  <art::mirror::ObjectReference<false, art::mirror::ObjectArray<art::mirror::ArtMethod> >> = {
    reference_ = 0x70e7b3c8
  }, <No data fields>}

The following code show its structure from memory:

1
2
3
4
5
6
7
8
(gdb) p/x *(art::mirror::ObjectArray<art::mirror::ArtMethod>*) 0x70e7b3c8
$23 = {
  <art::mirror::Array> = {
	[...]
    members of art::mirror::Array: 
    length_ = 0x280, 
    first_element_ = 0x70e7b3d4
  }, <No data fields>}

References