深入理解计算机系统(CSAPP)课程实验bomb程序炸弹实验日志(phase_4)

本文接 深入理解计算机系统(CSAPP)课程实验bomb程序炸弹实验日志(phase_3)继续写,phase_4部分在昨天已经完成了,日志在今天才开始写。个人认为这个部分是整个bomb程序炸弹最难破解的部分,在破解的过程中发现这是一个递归函数,体现在汇编语言中就显得特征不是那么明显,所以采用了一种将汇编转化成与之等价的C语言语句,这样有助于更好的看清程序的运作过程。下面是我的探索过程。

在Notepad++中查找到函数phase_4,代码如下:

08048e2e <phase_4>:
 8048e2e:	55                   	push   %ebp
 8048e2f:	89 e5                	mov    %esp,%ebp
 8048e31:	83 ec 28             	sub    $0x28,%esp
 8048e34:	8d 45 f0             	lea    -0x10(%ebp),%eax
 8048e37:	89 44 24 0c          	mov    %eax,0xc(%esp)
 8048e3b:	8d 45 f4             	lea    -0xc(%ebp),%eax
 8048e3e:	89 44 24 08          	mov    %eax,0x8(%esp)
 8048e42:	c7 44 24 04 3e a2 04 	movl   $0x804a23e,0x4(%esp)
 8048e49:	08 
 8048e4a:	8b 45 08             	mov    0x8(%ebp),%eax
 8048e4d:	89 04 24             	mov    %eax,(%esp)
 8048e50:	e8 eb f9 ff ff       	call   8048840 <__isoc99_sscanf@plt>
 8048e55:	83 f8 02             	cmp    $0x2,%eax
 8048e58:	75 0c                	jne    8048e66 <phase_4+0x38>
 8048e5a:	8b 45 f4             	mov    -0xc(%ebp),%eax
 8048e5d:	85 c0                	test   %eax,%eax
 8048e5f:	78 05                	js     8048e66 <phase_4+0x38>
 8048e61:	83 f8 0e             	cmp    $0xe,%eax
 8048e64:	7e 05                	jle    8048e6b <phase_4+0x3d>
 8048e66:	e8 66 02 00 00       	call   80490d1 <explode_bomb>
 8048e6b:	c7 44 24 08 0e 00 00 	movl   $0xe,0x8(%esp)
 8048e72:	00 
 8048e73:	c7 44 24 04 00 00 00 	movl   $0x0,0x4(%esp)
 8048e7a:	00 
 8048e7b:	8b 45 f4             	mov    -0xc(%ebp),%eax
 8048e7e:	89 04 24             	mov    %eax,(%esp)
 8048e81:	e8 da fc ff ff       	call   8048b60 <func4>
 8048e86:	83 f8 01             	cmp    $0x1,%eax
 8048e89:	75 06                	jne    8048e91 <phase_4+0x63>
 8048e8b:	83 7d f0 01          	cmpl   $0x1,-0x10(%ebp)
 8048e8f:	74 0c                	je     8048e9d <phase_4+0x6f>
 8048e91:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi
 8048e98:	e8 34 02 00 00       	call   80490d1 <explode_bomb>
 8048e9d:	c9                   	leave  
 8048e9e:	66 90                	xchg   %ax,%ax
 8048ea0:	c3                   	ret    

同样,从函数开始的部分到0x8048e4d位置都是在做新空间的开辟和参数的传递工作。依然设-0xc(%ebp)位置的参数为val1,-0x10(%ebp)位置的参数为val2,接着0x8048e50位置就是数据读入,0x8048e55位置eax中的数据应该是读入数据的个数,若eax中的值不等于2,跳转到0x8048e66位置,引爆炸弹。所以这一关的要求是输入两个数字,且两个参数之间必定会满足某种关系。

接下来是0x8048e5a位置的一条mov指令,将参数1放入寄存器eax中。0x8048e5d开始的test和js指令,将eax和eax自身进行与操作,当符号位位1时发生跳转,引爆炸弹。这说明eax中存的数必须满足符号位不为1,也就是必须是一个正数,这样我们获得了参数1的第一个范围限制。

继续往下读,0x8048e5a位置开始又是一个比较加跳转指令,将参数1的值和十六进制的e,也就是十进制的14进行比较,若eax<=14,则跳转到0x8048e6b位置,否则下一步就是引爆炸弹。所以,参数1必须小于等于14,这样得到了参数1的第二个范围限制。

然后将执行0x8048e6b位置和0x8048e73位置的两个movl指令,0x8048e7b开始再将eax中的值设为phase_4的返回值。

再往下看,0x8048e81位置调用了func4函数,这又是另外一个函数,也是phase_4这个部分最关键的地方,先跳过它继续往下获取信息。

0x8048e86位置开始是一个比较加跳转指令,在将func4函数执行后的返回值和1做比较,若不等则引爆炸弹。说明此函数的返回值必须为1。

0x8048e8b位置同样是一个比较加跳转,将参数2的值和1进行比较,若相等则函数执行结束,否则引爆炸弹。说明参数2的值必须为1。

接下来分析最关键的函数func4部分,它是一个递归结构,通过逐条将汇编指令转化成对应的C语言代码,将函数的功能清楚地显示出来。

在Notepad++中搜索函数func4,代码如下:

08048b60 <func4>:
 8048b60:	55                   	push   %ebp
 8048b61:	89 e5                	mov    %esp,%ebp
 8048b63:	83 ec 18             	sub    $0x18,%esp
 8048b66:	89 5d f8             	mov    %ebx,-0x8(%ebp)
 8048b69:	89 75 fc             	mov    %esi,-0x4(%ebp)
 8048b6c:	8b 55 08             	mov    0x8(%ebp),%edx
 8048b6f:	8b 45 0c             	mov    0xc(%ebp),%eax
 8048b72:	8b 5d 10             	mov    0x10(%ebp),%ebx
 8048b75:	89 d9                	mov    %ebx,%ecx
 8048b77:	29 c1                	sub    %eax,%ecx
 8048b79:	89 ce                	mov    %ecx,%esi
 8048b7b:	c1 ee 1f             	shr    $0x1f,%esi
 8048b7e:	8d 0c 0e             	lea    (%esi,%ecx,1),%ecx
 8048b81:	d1 f9                	sar    %ecx
 8048b83:	01 c1                	add    %eax,%ecx
 8048b85:	39 d1                	cmp    %edx,%ecx
 8048b87:	7e 17                	jle    8048ba0 <func4+0x40>
 8048b89:	83 e9 01             	sub    $0x1,%ecx
 8048b8c:	89 4c 24 08          	mov    %ecx,0x8(%esp)
 8048b90:	89 44 24 04          	mov    %eax,0x4(%esp)
 8048b94:	89 14 24             	mov    %edx,(%esp)
 8048b97:	e8 c4 ff ff ff       	call   8048b60 <func4>
 8048b9c:	01 c0                	add    %eax,%eax
 8048b9e:	eb 20                	jmp    8048bc0 <func4+0x60>
 8048ba0:	b8 00 00 00 00       	mov    $0x0,%eax
 8048ba5:	39 d1                	cmp    %edx,%ecx
 8048ba7:	7d 17                	jge    8048bc0 <func4+0x60>
 8048ba9:	89 5c 24 08          	mov    %ebx,0x8(%esp)
 8048bad:	83 c1 01             	add    $0x1,%ecx
 8048bb0:	89 4c 24 04          	mov    %ecx,0x4(%esp)
 8048bb4:	89 14 24             	mov    %edx,(%esp)
 8048bb7:	e8 a4 ff ff ff       	call   8048b60 <func4>
 8048bbc:	8d 44 00 01          	lea    0x1(%eax,%eax,1),%eax
 8048bc0:	8b 5d f8             	mov    -0x8(%ebp),%ebx
 8048bc3:	8b 75 fc             	mov    -0x4(%ebp),%esi
 8048bc6:	89 ec                	mov    %ebp,%esp
 8048bc8:	5d                   	pop    %ebp
 8048bc9:	c3                   	ret    

以下是在栈中模拟func4函数操作并将汇编指令转化为C语言代码的过程示意:




将转化的C语言代码整合成完整的func4在编译器中运行,注释为对应的汇编代码:

#include <stdio.h>
//val1:%edx,y:%eax,z:%ebx,k:%ecx,t:%esi;
int func4(int val1,int y,int z)
{
	int k,t;	//
	k = z;	//8048b75:	89 d9                	mov    %ebx,%ecx
	k = k-y;	//8048b77:	29 c1                	sub    %eax,%ecx
	t = k;	//8048b79:	89 ce                	mov    %ecx,%esi
	t = t>>31;	//8048b7b:	c1 ee 1f             	shr    $0x1f,%esi
	k = k+t;	//8048b7e:	8d 0c 0e             	lea    (%esi,%ecx,1),%ecx
	k = k/2;	//8048b81:	d1 f9                	sar    %ecx
	k = k+y;	//8048b83:	01 c1                	add    %eax,%ecx
	if(k<=val1)	//8048b85:	39 d1                	cmp    %edx,%ecx
 				//8048b87:	7e 17                	jle    8048ba0 <func4+0x40>
	{
		y = 0;	//8048ba0:	b8 00 00 00 00       	mov    $0x0,%eax
		if(k>=val1)	//8048ba5:	39 d1                	cmp    %edx,%ecx
 					//8048ba7:	7d 17                	jge    8048bc0 <func4+0x60>
		{
			return y;	//8048bc0:	8b 5d f8             	mov    -0x8(%ebp),%ebx
 						//8048bc3:	8b 75 fc             	mov    -0x4(%ebp),%esi
 						//8048bc6:	89 ec                	mov    %ebp,%esp
 						//8048bc8:	5d                   	pop    %ebp
 						//8048bc9:	c3                   	ret    
		}
		else
		{
			k = k+1;	//8048bad:	83 c1 01             	add    $0x1,%ecx
			y = func4(val1,k,z);	//8048ba9:	89 5c 24 08          	mov    %ebx,0x8(%esp)
									//8048bb0:	89 4c 24 04          	mov    %ecx,0x4(%esp)
									//8048bb4:	89 14 24             	mov    %edx,(%esp)
			y = y+y+1;	//8048bbc:	8d 44 00 01          	lea    0x1(%eax,%eax,1),%eax
			return y;	//8048bc0:	8b 5d f8             	mov    -0x8(%ebp),%ebx
 						//8048bc3:	8b 75 fc             	mov    -0x4(%ebp),%esi
 						//8048bc6:	89 ec                	mov    %ebp,%esp
 						//8048bc8:	5d                   	pop    %ebp
 						//8048bc9:	c3                   	ret    
		}
	}
	else
	{
		k = k-1;	//8048b89:	83 e9 01             	sub    $0x1,%ecx
		y = func4(val1,y,k);	//8048b8c:	89 4c 24 08          	mov    %ecx,0x8(%esp)
 								//8048b90:	89 44 24 04          	mov    %eax,0x4(%esp)
 								//8048b94:	89 14 24             	mov    %edx,(%esp)
		y = y+y;	//8048b9c:	01 c0                	add    %eax,%eax
		return y;	//8048b9e:	eb 20                	jmp    8048bc0 <func4+0x60>
	}
}

int main()
{
	int val1,val2;
	for(val1=0;val1<=14;val1++)
	{
		val2 = func4(val1,0,14);
		if(val2 == 1)
		{
			printf("%d\n",val1);
		}
	}
	return 0;
}

运行后的结果如下:



说明满足条件的答案有3个,分别是:

8,1

9,1

11,1

输入任意一个进行验证:


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值