导航
BombLab Phase-3 & Phase-4 &Phase-5
Phase_6
- Phase_6栈帧图
- Read_six_numbers和sscanf栈帧
由于我们之前在第二次实验已经详细分析过了这两个函数的栈帧,这里我们就不多赘述了,我们知道他们俩的功能是为了读取我们输入的六个数字。
- 反汇编phase_6函数。
1.
常规的开栈操作,我们看到一共开了92个字节空间。
2.
我们看到这边又是调用了read_six_numbers这个函数,这个函数我们在之前的实验中遇到过,是读取六个数。而我们看到这里参数是ebp-0x30这个地址,和ebp+8这个我们输入的字符串首地址,那我们就知道了ebp-0x30是一个数组的首地址,保存了我们输入的六个数。
3.
我们可以用这几句来替代:
Esi = 0;
Edi = 数组首地址;
Eax = 数组首元素;
Eax = eax – 1;
If eax <=5 跳转+51
Else 爆炸
如此,我们看出,当前获得的元素必须要<=6,不然就爆炸了。
4.
Esi的值增加1,
然后和6比较,如果等于6,跳转到+93,我们先假设没有跳转,往下继续看;
5.
Ebx = 下标为esi的元素的地址;
//看到这里我们又恍然明白,前面esi=6时会跳转,正好六个数都被遍历完了循环结束的跳转,所以接下来肯定存在一个循环。
Ebp-0x4c保存esi的值;
Eax=下标为esi的后面一个元素值;
If(eax!=(ebx)) //其实就是数组中一个元素和他后面一个元素比较
跳转到 +78
Else
爆炸;
这个阶段就说明了前后相邻元素必定不能相等,相等就爆炸;
6.
我们看看跳到+78发生了什么
我们们说过 ebp-0x4c保存的当前元素的下标的一个临时变量;
临时变量+1; //其实也就是下标+1;
Ebx=ebx+4; //地址+4,ebx变成下一个元素地址
If(下标值<=5)
跳转到 +65; //说明比较没有结束,轮到下一个元素了
Else
跳转到 +35; //回到35,说明内层循环已经走完,开始下一轮外层循环
7.
当我们循环完毕后,会跳转到另一个地方
这一段,我们看到是在判断数组的元素有没有判断完,完毕之后,我们来到下一阶段+93
阶段一总结:
所以,综合起来看,这一阶段这其实是一个2层的for循环,目的是用来保证数组中的任意两个数都不相等,
且输入的每个元素都要<=6,
否则就会就爆炸。
分析完这个阶段我们来到下一个阶段。
我们看到下一个阶段会跳转到 +93,那么我们去+93看看;
(下一阶段我们称为阶段二)
8.
Ebx = 0;
Edi=数组首地址;
无条件跳转 +124的地方,那么我们可以看出这两句是初始化语句,我们再去看看+125。
9.
Esi = ebx;
Ecx = 数组中下表为 ebx 的元素值;
Edx = 内存为0x804c0c4中的值;
Eax = 1;
If( ecx > 1 )
跳转到+103 //可以看出,又是一个循环;
Else
跳转到+113 //eax=ecx会进入另一个分支
首先,我们还是看看 0x804c0c4 地址里放了什么东西:
从数据上,我们暂时看不出什么东西,但是我们可以注意到左边的尖括号里面的node1,这提示我们作者这个变量的取名为node1,我们可以猜测这是一个结点。
分析完有用信息,那我们先去看看到 +103是什么情况把;
10.
这里汇编我们可以看到终止条件是ecx=eax,如果ecx!=eax,则edx在循环里面每次改边一次并且edx=edx+8,这我们可以猜想很多,edx里面存放的是地址,edx+8里面存放的也是地址,联想到之前我们说的node1,很可能这是一个链表结构!
所以到这,我们知道最后的edx取值取决于你输入的ecx。
假设我们已经eax=ecx,我们来到下一步。
11.
这几句代码,是将我们edx里面存放的内容,放到栈中的一个位置保存,然后ebx加1,如果ebx!=6,我们发现又回到了+125的位置,又开始了对下一个元素的操作,这说明这也是一个两层循环,只有ebx=6之后才会来到之后一个阶段。
阶段二总结:
这个阶段仍然是一个两层循环,目的在于将我们从链表中取到的结点地址放入栈中保存,将六个都取完之后,到下一个阶段。
好,我们开始进入阶段三分析。
12
我们发现这边是一系列的赋值,但从阶段二中,我们知道这些位置保存的都是一些结点的地址值,我们先看看前几句: