2. This talk is…
Very high level
Restricted to stack buffer overflows
Restricted to x86 architecture
3. 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
4. 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.
12. General Purpose Registers
Small 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.
13. EBP - The Base Pointer
Used to track the base of the current frame
(function).
Can be used for other purposes
14. 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
15. EIP - Instruction Pointer
Always points to the memory address of the next
instruction to be executed by the CPU
16. EIP - Instruction Pointer
Always points to the memory address of the next
instruction to be executed by the CPU
18. 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
19. 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
20. Stack - Program Initializes
main
High Mem Address
Low Mem Address
EBP
ESP
21. Stack - Foo Function Called
ret address
main
High Mem Address
Low Mem Address
EBP
ESP
22. Stack - Foo Function Called
ret address
main
High Mem Address
Low Mem Address
EBP
ESP
23. Stack - Foo Function Called
saved EBP
ret address
main
High Mem Address
Low Mem Address
EBP
ESP
24. Stack - Foo Function Called
saved EBP
ret address
main
High Mem Address
Low Mem Address
EBPESP
25. Stack - Foo Function Called
10 bytes
reserved for A
saved EBP
ret address
main
High Mem Address
Low Mem Address
EBP
ESP
26. Stack - strcopy() Assume we executed our program with an argument of “AAAAAAAAAA”
AAAA
AAAA
AA
saved EBP
ret address
main
High Mem Address
Low Mem Address
EBP
ESP
27. Stack - strcopy() Now let’s put our attacker hat on and execute our program with the argument
“AAAAAAAAAAAAAAAAAA”
AAAA
AAAA
AA
AAAA
AAAA
main
High Mem Address
Low Mem Address
EBP
ESP
28. Stack - strcopy() Now let’s put our attacker hat on and execute our program with the argument
“AAAAAAAAAAAAAAAAAA”
AAAA
AAAA
AA
AAAA
AAAA
main
High Mem Address
Low Mem Address
EBP
ESP
29. Stack - strcopy() Now let’s put our attacker hat on and execute our program with the argument
“AAAAAAAAAAAAAAAAAA”
AAAA
AAAA
AA
AAAA
AAAA
main
High Mem Address
Low Mem Address
EBP
ESP
30. Stack - strcopy() Now let’s put our attacker hat on and execute our program with the argument
“AAAAAAAAAAAAAAAAAA”
AAAA
AAAA
AA
AAAA
AAAA
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.
32. 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.
33. 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…?
35. Finding the offset
Using 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
39. 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!?”
40. 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!?”
41. Setting the RET address
You 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.
42. Putting it all together
Padding
NOP Sled
Shellcode
EIP = JMP ESP
Padding
Our Crafted
Buffer Overflow