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

来源:互联网 发布:nginx反向代理socket 编辑:程序博客网 时间:2024/05/18 00:58

本文接 深入理解计算机系统(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,%ecxk = k-y;//8048b77:29 c1                sub    %eax,%ecxt = k;//8048b79:89 ce                mov    %ecx,%esit = t>>31;//8048b7b:c1 ee 1f             shr    $0x1f,%esik = k+t;//8048b7e:8d 0c 0e             lea    (%esi,%ecx,1),%ecxk = k/2;//8048b81:d1 f9                sar    %ecxk = k+y;//8048b83:01 c1                add    %eax,%ecxif(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,%eaxif(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,%ecxy = 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),%eaxreturn 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,%ecxy = 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,%eaxreturn 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

输入任意一个进行验证:


0 0
原创粉丝点击