Buffer Overflows 101: Some Assembly Required

Post on 28-Jan-2018

99 views 0 download

Transcript of Buffer Overflows 101: Some Assembly Required

BUFFER OVERFLOWS 101SOME ASSEMBLY REQUIRED KORY KYZAR

This talk is…

Very high level

Restricted to stack buffer overflows

Restricted to x86 architecture

What’s a buffer?A buffer can be thought of as an allocated space in memory intended to hold a certain amount of data.

char A[10];

Allocate 10 bytes for the variable A

Ok, and overflow?Storing more data in the buffer than it is designed to hold.

t o o m u c h d a t a

strcopy(A, “toomuchdata”);

A

Data is written to memory outside the region allocated to A. We’ve overflowed the buffer.

So What Happens?

Crash

Score

So how do we score?

So how do we score?

Slow down there Romeo.

So how do we score?

Slow down there Romeo.

CPU REGISTERS

General Purpose RegistersSmall storage areas on the CPU that allow for very fast access.

x86 CPUs have 8 general purpose registers.

Basically, data from memory is loaded into a register, some form of processing is done, then the data is saved back to memory.

Main ones we are concerned with are EBP and ESP.

EIP is not considered a general purpose register, but we are interested in it as well.

EBP - The Base Pointer

Used to track the base of the current frame (function).

Can be used for other purposes

ESP - The Stack Pointer

Used to track the top of the stack.

As data is moved onto (PUSH) or off of (POP), the ESP register is incremented or decremented accordingly

EIP - Instruction PointerAlways points to the memory address of the next instruction to be executed by the CPU

EIP - Instruction PointerAlways points to the memory address of the next instruction to be executed by the CPU

THE STACK

What is the stack?

Data structure that store values contiguously in memory

Last In First Out structure

ESP register marks the top of the stack

Assume the below program#include <string.h> void foo (char *bar){ char A[10]; strcpy(A, bar); // no bounds checking} int main (int argc, char **argv){ foo(argv[1]);}

Program simply takes an argument on the

command line and copies it into a variable that is allocated 10 bytes (A)

https://en.wikipedia.org/wiki/Stack_buffer_overflow

Stack - Program Initializes

main

High Mem Address

Low Mem Address

EBP

ESP

Stack - Foo Function Called

ret address

main

High Mem Address

Low Mem Address

EBP

ESP

Stack - Foo Function Called

ret address

main

High Mem Address

Low Mem Address

EBP

ESP

Stack - Foo Function Called

saved EBPret address

main

High Mem Address

Low Mem Address

EBP

ESP

Stack - Foo Function Called

saved EBPret address

main

High Mem Address

Low Mem Address

EBPESP

Stack - Foo Function Called

10 bytes reserved for A

saved EBPret address

main

High Mem Address

Low Mem Address

EBP

ESP

Stack - strcopy()Assume we executed our program with an argument of “AAAAAAAAAA”

AAAAAAAA

AA

saved EBPret address

main

High Mem Address

Low Mem Address

EBP

ESP

Stack - strcopy()Now let’s put our attacker hat on and execute our program with the argument “AAAAAAAAAAAAAAAAAA”

AAAAAAAA

AAAAAAAAAA

main

High Mem Address

Low Mem Address

EBP

ESP

Stack - strcopy()Now let’s put our attacker hat on and execute our program with the argument “AAAAAAAAAAAAAAAAAA”

AAAAAAAA

AAAAAAAAAA

main

High Mem Address

Low Mem Address

EBP

ESP

Stack - strcopy()Now let’s put our attacker hat on and execute our program with the argument “AAAAAAAAAAAAAAAAAA”

AAAAAAAA

AAAAAAAAAA

main

High Mem Address

Low Mem Address

EBP

ESP

Stack - strcopy()Now let’s put our attacker hat on and execute our program with the argument “AAAAAAAAAAAAAAAAAA”

AAAAAAAA

AAAAAAAAAA

main

High Mem Address

Low Mem Address

EBP

ESP

We just overwrote the RET address,meaning we can tell the CPU

which instruction to execute next.

CONGRATULATIONS!YOU CRASHED.

Buffer Overflow Shopping List

We need…..

The offset in the buffer at which EIP is overwritten.

Code to perform the exploit.

A way to direct EIP to the code we want to run.

The buffer you were trying to overflow was larger than 10 bytes? Let’s say we have a large buffer of an unknown size.

We could write a fuzzer that submits an increasing number of “A”s and make note of the length that causes the crash.

But how do we know which of the “A”’s overwrote EIP?

What if…?

Finding the offset pattern_create.rb is a ruby script that creates a non repeating sequence of characters of a given length.

Finding the offsetUsing the string generated by pattern_create.rb as your input, you would analyze where the program crashed in a debugger. (i.e. Access violation when executing 30614239)

Then you would check where that series of characters was in string with pattern_offset.rb

Now you have the exact position in the buffer to place your return address

Shellcode

Assembly code generated to execute the payload of the attackers choice

Shellcode must be carefully crafted by hand…RIGHT?

Shellcode

Assembly code generated to execute the payload of the attackers choice

Shellcode must be carefully crafted by hand…RIGHT?

MSFVENOMMSFPAYLOAD AND MSFENCODE HAVE BEEN DEPRECATED IN FAVOR OF MSFVENOM

So where do we point EIP?

We need to get the CPU to execute our shellcode

“So just set EIP to the address at the beginning of your shellcode!?”

So where do we point EIP?

We need to get the CPU to execute our shellcode

“So just set EIP to the address at the beginning of your shellcode!?”

Setting the RET addressYou can’t hardcode the EIP address in since the program will be loaded into different places in memory at each execution.

JMP ESP - one of the most common methods of getting back to your shellcode is to point EIP to a JMP ESP command. This can be used since its relative.

This causes EIP to go to the address in the ESP register, which you should be able to use to access your shellcode.

Putting it all together

Padding

NOP Sled

Shellcode

EIP = JMP ESP

Padding

Our CraftedBuffer Overflow

DEMO?THIS WILL PROBABLY END IN FLAMES

@0XKTWO

K2@KORROSIVESECURITY.COM