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

时间:2021-08-19 01:18:25

本文接 深入理解计算机系统(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语言代码的过程示意:

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

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


将转化的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;
}

运行后的结果如下:

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


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

8,1

9,1

11,1

输入任意一个进行验证:

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