前言:
早就听说csapp的大名,花了两个月的时间终于把它看完啦,不过看得比较赶,里面的实验没有做,抽空又把它翻出来,复习一遍,(当初的不认真,总归是要还的)。
这个实验唯一的材料就是一个叫bomb的可执行文件,和一份说明文档。
刚拿到bomb时发现不能执行,但是竟然没有想到是文件没有x权限,还折腾了一段时间。
1.phase_1的分析:
在call string_not_equal之前的两个push应该是将压入调用所需的参数,其中一个是用户输入的,另一个是本身硬编码的,猜测string_not_equal的作用是比较这两个字符串是否相等,然后地址0x8048b32处的语句测试保存返回值的%eax是否为0,所以只要用gdb输出地址0x8049678处的值即可。
所以第一个答案是"The future will be better tomorrow.”
2.phase_2的分析:
猜测read_six_numbers将用户输入的数字保存到%esp-0x20处。
来做个实验吧:
可以看到输入的第一个数字果然保存到了%esp-0x20处,第二个数字被保存在%esp-0x1c处,以此类推。。
接着用%esi保存%esp-0x20,即数组的基地址,%ebx保存循环变量,初始为1,然后就跟着循环就可一个推出密钥为:
1 2 6 24 120 720
phase_3的分析:
在调用sscanf前push三个数显然是参数啊,第一个为调用phase3的实參,第二个硬编码在0x8049968处,第三个则为phase3这个函数的第一个本地变量设为t。
打印处0x8049968处的值:
上网搜了下sscanf的原型:int sscanf ( const char * s, const char * format, ...);
结合0x8049968处的值得出,这段代码的含义为将phase3的字符串实參转化为两个整数保存在phase3的第一个本地变量中。
接下来看到:
联想到switch结构:
整个程序大致结构如下:
phase3(s):
{
int [2] t
ret = sscanf(s, ''%d,%d'', t)
if (ret > 1)
{if (t[0] < 5 && t[0] > 0)
tem = t[0]
switch(t[0]):
case 0:
.....
else:
bomb
}
else:
bomb
if tem == t[1]:
return tem
else:
bomb
}
最后结果为:
0 -179
1 -678
2 -199
3 -900
4 -169
5 -411