本文接深入理解计算机系统(CSAPP)课程实验bomb程序炸弹实验日志(phase_1)继续写,记录对bomb程序炸弹实验phase_2函数部分的探索过程。
首先在Notepad++中查找到函数phase_2,代码如下:
08048d6a <phase_2>:
8048d6a: 55 push %ebp
8048d6b: 89 e5 mov %esp,%ebp
8048d6d: 56 push %esi
8048d6e: 53 push %ebx
8048d6f: 83 ec 30 sub $0x30,%esp
8048d72: 8d 45 e0 lea -0x20(%ebp),%eax
8048d75: 89 44 24 04 mov %eax,0x4(%esp)
8048d79: 8b 45 08 mov 0x8(%ebp),%eax
8048d7c: 89 04 24 mov %eax,(%esp)
8048d7f: e8 87 03 00 00 call 804910b <read_six_numbers>
8048d84: 83 7d e0 00 cmpl $0x0,-0x20(%ebp)
8048d88: 75 06 jne 8048d90 <phase_2+0x26>
8048d8a: 83 7d e4 01 cmpl $0x1,-0x1c(%ebp)
8048d8e: 74 05 je 8048d95 <phase_2+0x2b>
8048d90: e8 3c 03 00 00 call 80490d1 <explode_bomb>
8048d95: 8d 5d e8 lea -0x18(%ebp),%ebx
8048d98: 8d 75 f8 lea -0x8(%ebp),%esi
8048d9b: 8b 43 fc mov -0x4(%ebx),%eax
8048d9e: 03 43 f8 add -0x8(%ebx),%eax
8048da1: 39 03 cmp %eax,(%ebx)
8048da3: 74 05 je 8048daa <phase_2+0x40>
8048da5: e8 27 03 00 00 call 80490d1 <explode_bomb>
8048daa: 83 c3 04 add $0x4,%ebx
8048dad: 39 f3 cmp %esi,%ebx
8048daf: 75 ea jne 8048d9b <phase_2+0x31>
8048db1: 83 c4 30 add $0x30,%esp
8048db4: 5b pop %ebx
8048db5: 5e pop %esi
8048db6: 5d pop %ebp
8048db7: c3 ret
从内存0x8048d7f位置的call指令看出,调用了一个名为<read_six_numbers>的函数,可以推断出这一关的基本要求是输入6个数字。从函数开始一直到0x8048d6f位置一样是帧的开辟和初始化部分。0x8048d72位置的lea指令用于地址传送,将%ebp-0x20位置的地址放入寄存器eax,接着0x8048d75将寄存器eax中的值(%ebp-0x20位置的地址)放入内存地址的0x4+%esp位置(通过寄存器作为中转在内存之间传递值)。
下面一步0x8048d79是将调用phase_2的函数的返回地址传入phase_2中,在内存的0x8+%ebp位置存放着上一级函数的返回地址,将返回地址存放在寄存器eax中。
接着0x8048d7c将eax中的返回地址放入栈顶位置的内存空间。
准备工作到这里已经基本完成。
接下来调用函数<read_six_numbers>读入数据(6个数字)。
紧接着是两个cmpl比较指令。cmpl $0x0,-0x20(%ebp)先将0和%ebp-0x20位置的值进行比较,若不相等则跳转至0x8048d90位置,往下看发现0x8048d90位置为<explode_bomb>函数,即炸弹爆炸,说明第一个参数存放在内存的%ebp-0x20位置且必须为0,同理,继续往下看,可以知道第二个参数放在内存的%ebp-0x1c位置且必须为1。到这里就已经推断出前两个参数的值为0和1。
0x8048d8e位置的je跳转至0x8048d95位置,接着是两个lea地址传送指令,分别将-0x18(%ebp)和-0x8(%ebp)位置的地址送入寄存器ebx和esi。
0x8048d9b位置开始是关键的运算部分,通过一个当前帧的模拟图来演示:
得出最终答案为0 1 1 2 3 5。
运行bomb程序测试一下: