CSAPP LAB buflab-handout实验报告

CSAPP LAB buflab-handout实验报告

更好的阅读体验

一、实验目的:

加深对IA-32函数调用规则和栈帧结构的理解

二、实验要求

对目标程序实施缓冲区溢出攻击(buffer overflow attacks)

通过造成缓冲区溢出来破坏目标程序的栈帧结构

继而执行一些原来程序中没有的行为

三、实验内容(所修改函数代码,功能以及重要代码的解释):

Smoke

要求通过栈溢出攻击,使之跳到smoke函数。

文档给已经出了getbuf()、test()、smoke()的高级语言代码

image.png

image.png

老规矩,先objdump d bufbomb > bufbomb.asm

08049342 <getbuf>:
 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  //buf 缓冲区的大小为 0x32,即50个字节
 804934e:	50                   	push   %eax             //eax里面就是缓冲区首地址
 804934f:	e8 ba fa ff ff       	call   8048e0e <Gets>
 8049354:	83 c4 10             	add    $0x10,%esp
 8049357:	b8 01 00 00 00       	mov    $0x1,%eax
 804935c:	c9                   	leave  
 804935d:	c3                   	ret    

从 804934b 行指令可以看到 buf 缓冲区的大小为 50 个字节

08048ba1 <smoke>:  //smoke 函数的地址为 0x08048ba1
 8048ba1:	55                   	push   %ebp
 8048ba2:	89 e5                	mov    %esp,%ebp
 8048ba4:	83 ec 08             	sub    $0x8,%esp
 8048ba7:	83 ec 0c             	sub    $0xc,%esp
 8048baa:	68 30 a3 04 08       	push   $0x804a330
 8048baf:	e8 5c fd ff ff       	call   8048910 <puts@plt>
 8048bb4:	83 c4  10             	add    $0x10,%esp
 8048bb7:	83 ec 0c             	sub    $0xc,%esp
 8048bba:	6a 00                	push   $0x0
 8048bbc:	e8 fe 08 00 00       	call   80494bf <validate>
 8048bc1:	83 c4 10             	add    $0x10,%esp
 8048bc4:	83 ec 0c             	sub    $0xc,%esp
 8048bc7:	6a 00                	push   $0x0
 8048bc9:	e8 52 fd ff ff       	call   8048920 <exit@plt>

smoke 函数的地址为 0x08048ba1

攻击字符串用来覆盖数组 buf,进而溢出并覆盖 ebp 和 ebp 上面的返回地址,攻击字符串的大小应该是 50+4+4=58 个字 节。攻击字符 串的最 后 4 字节 应是 smoke 函数 的地址0x08048ba1。

攻击字符串为:

image.png

成功

image.png


Fizz

image.png

Fizz传入了一个参数,文档告诉我们应该为cookie

08048bce <fizz>:  //fizz 函数的地址为 0x08048bce
 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 <fizz+0x34>
 8048be0:	83 ec 08             	sub    $0x8,%esp
 8048be3:	ff 75 08             	pushl  0x8(%ebp)
 8048be6:	68 4b a3 04 08       	push   $0x804a34b
 8048beb:	e8 50 fc ff ff       	call   8048840 <printf@plt>
 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 <validate>
 8048bfd:	83 c4 10             	add    $0x10,%esp
 8048c00:	eb 13                	jmp    8048c15 <fizz+0x47>
 8048c02:	83 ec 08             	sub    $0x8,%esp
 8048c05:	ff 75 08             	pushl  0x8(%ebp)
 8048c08:	68 6c a3 04 08       	push   $0x804a36c
 8048c0d:	e8 2e fc ff ff       	call   8048840 <printf@plt>
 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 <exit@plt>

所以可以这样构造攻击串:50(冲掉 buf)+4(冲掉 ebp 旧值)+4(用 fizz 函数地址08048bce替换,冲掉返回地址)+4(占位置)+4(这里到了ebp+8的位置,即需要的参数,把 cookie 值按照小端方式放到这里就行)

我的 cookie 是 0x25ed4761

image.png

成功

image.png


Bang

image.png

要求进入bang()函数,并且修改global_value的值为cookie

08048c1f <bang>: //返回地址0x08048c1f
 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  //比较0x804d138和0x804d140里面的内容,根据文档可知,要将global_value==cookie
 8048c31:	39 c2                	cmp    %eax,%edx   
 8048c33:	75 25                	jne    8048c5a <bang+0x3b>//要他们相同,gdb调试知804d140是global_value
 8048c35:	a1 40 d1 04 08       	mov    0x804d140,%eax
 8048c3a:	83 ec 08             	sub    $0x8,%esp                         //movl   $0x804d140,804d138//将cookie赋值给全局变量
 8048c3d:	50                   	push   %eax
 8048c3e:	68 8c a3 04 08       	push   $0x804a38c                        //push   $0x08048c1f //函数bang的地址压入栈
 8048c43:	e8 f8 fb ff ff       	call   8048840 <printf@plt>             //ret
 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 <validate>
 8048c55:	83 c4 10             	add    $0x10,%esp
 8048c58:	eb 16                	jmp    8048c70 <bang+0x51>
 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 <printf@plt>
 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 <exit@plt>

bang的地址08048c1f

gdb调试看看global_value的地址在哪里

屏幕截图 2021-12-22 005859.JPG

是0x804d140

编写攻击汇编代码(作用就是把 cookie 放到 0x804d1a0 处,然后调用 bang 函数),并进行反汇编得到机器码

屏幕截图 2021-12-22 012758.JPG

那么,怎么才能调用到这段函数呢?

可以把它写入 buf 数组中,buf 数组会被加载进入缓冲区,找到缓冲区的地址,用它覆盖掉返回地址就行了。

因为

 804934b:	8d 45 ce             	lea    -0x32(%ebp),%eax
 804934e:	50                   	push   %eax

屏幕截图 2021-12-22 011413.JPG

通过调试,可以找到 eax 为 0x5568317e,就是缓冲区首地址

image.png

成功

image.png


Bomb

image.png

前面的攻击都是使目标程序跳转到特定函数,进而利用exit函数结束目标程序运行,在这个过程中我们都把原来的恢复现场需要用的返回地址和原test的ebp给破坏了。Bomb这一关中,我们将修复这些被我们破坏的栈状态信息,让最后还是回到test中,让被攻击者不容易发现我们动了手脚,

另外,构造攻击字符串,使得getbuf都能将正确的cookie值返回给test函数,而不是返回值1。设置返回值也就是更改eax(eax中保存的就是函数的返回值)的值,可以用mov指令设置eax存的为cookie值。更改完要进入test函数继续执行下面的指令,也就是下图中这个位置,将这个地址压栈。

 8048c88:	e8 b5 06 00 00       	call   8049342 <getbuf>
 8048c8d:	89 45 f4             	mov    %eax,-0xc(%ebp)

我们需要构造一串攻击指令,ret之前push 的地址是返回地址,是 call getbuf 行的 pc,也就是 8048c8d。

把它写到缓冲区中,并用缓冲区地址替换返回地址,构造出下图所示的攻击串

屏幕截图 2021-12-22 014057.JPG

恶意代码准备好了,将返回地址更改为指向这个代码的位置,把恶意代码放到buf缓冲区内,返回地址和bang一样。

接下来要恢复ebp的值,先得到ebp旧值。

gdb调试:在getbuf第一行,push ebp 设置断点。查看ebp的值。用这个值覆盖ebp值。ebp值在返回地址的低方位,放在返回地址前。

屏幕截图 2021-12-22 014357.JPG

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KiMmgk2u-1654332656850)(C:\Users\26012\AppData\Roaming\Typora\typora-user-images\image-20211226111555640.png)]

ok

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6FY1avt6-1654332656850)(C:\Users\26012\AppData\Roaming\Typora\typora-user-images\image-20211226111651674.png)]


Nitro

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qazV3Khq-1654332656850)(C:\Users\26012\AppData\Roaming\Typora\typora-user-images\image-20211226111849067.png)]

这一关难度比前面都大。但也是承接上一关的,构造攻击字符串使getbufn函数,返回cookie值至testn函数,而不是返回值1,需要将cookie值设为函数返回值,复原被破坏的栈帧结构,并正确地返回到testn函数。但这一关与之前最大的不同在于地址空间随机化,每次攻击,被攻击函数的栈帧内存地址都不同,也就是函数的栈帧位置每次运行时都不一样,不能准确地跳转到栈空间的某个特定地址。因此,要想办法保证每次都能够正确复原原栈帧被破坏的状态,使程序每次都能够正确返回。

0804935e <getbufn>:
 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  //706
 8049370:	50                   	push   %eax
 8049371:	e8 98 fa ff ff       	call   8048e0e <Gets>
 8049376:	83 c4 10             	add    $0x10,%esp
 8049379:	b8 01 00 00 00       	mov    $0x1,%eax
 804937e:	c9                   	leave  
 804937f:	c3                   	ret  

在这一关buffersize也从50增大到了706,这个做法是有意义的。

大概的思路是,虽然栈的初始地址不同,但会在一些范围里浮动,所以我们需要把我们的代码填在706字节的最后几个字节里,并且前面全面的空间都填上nop(编码为0x90)。不管我们跳转到哪个nop,最后都会执行到我们的代码。

 8048cff:	89 45 f0             	mov    %eax,-0x10(%ebp)
 8048d02:	e8 57 06 00 00       	call   804935e <getbufn>  //ebp = esp + 0x18 
 8048d07:	89 45 f4             	mov    %eax,-0xc(%ebp)

ebp是随机的,但是ebp相对esp是绝对的,根据上面的图中结合栈结构得出

ebp = esp + 0x18

getbufn函数返回后要从8048d07开始执行,将这个地址压栈。

设置cookie给eax。

综合得出恶意代码为:

image.png

因为随机,不知道程序会跳到哪里,所以把恶意代码放到最后面,用nop滑行。

(nop不会执行任何操作,只有PC加一,机器码是90。)

所以,前面塞满90,最后面写上恶意代码程序,以及最后要跳的位置。

寻找要跳的地址:

由于随机化,buf首地址不确定。用gdb调试:在0x8049370设断点,看eax的值。(每执行一次,要用c命令继续,进而执行下一次)

如此这样五次,注意这次调试时运行r需要加入-n

屏幕截图 2021-12-22 021301.JPG

屏幕截图 2021-12-22 021335.JPG

屏幕截图 2021-12-22 021429.JPG

取最高地址0x55682eee作为返回地址,这样就会一路滑行到恶意代码,执行恶意代码。

image.png

完成!

屏幕截图 2021-12-22 023159.JPG

四、实验总结

下一次)

如此这样五次,注意这次调试时运行r需要加入-n

[外链图片转存中…(img-NeRtSnyl-1654332656851)]

[外链图片转存中…(img-hPoLbU3w-1654332656851)]

[外链图片转存中…(img-x5ivf2tj-1654332656851)]

取最高地址0x55682eee作为返回地址,这样就会一路滑行到恶意代码,执行恶意代码。

[外链图片转存中…(img-lwOXzTxo-1654332656851)]

完成!

[外链图片转存中…(img-km65ngQP-1654332656852)]

四、实验总结

学到了很多东西,加深了对栈溢出、函数调用、寻址的理解。

  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值