由于每个人拿到的bomblab不一样,我自己的输入可能不适用于其他同学的bomblab,也可以了解一下思路,思路都差不多。
一、Phase_1:
由图可知,在调用了strings_not_equal后,该函数的作用是判断两个字符串是否相等,将返回值%eax 进行test,我们可知必须要相等否则就会boom,再看前面的代码,再调用strings_not_equal之前进行了传参,第一个参数是0x20(%esp),推测有可能是自己输入的字符串,第二个参数是0x4(%esp),值为0x804a1a4,查看里面的内容:
这就是我们第一关应该输入的字符串了。
第一关完成。
二、Phase_2
在调用read_six_numbers前面又是传参构建栈,查看该函数的作用
可以看到,这个函数要求我们必须输入5个以上的数字否则就会bomb
回到上张图,在调用函数之后,将0x18(%esp)的值和0比较,结合上面我们知道0x1(%esp)放的是我们输入的第一个数字,这里必须等于0才能跳过爆炸,接下来又是0x1c(%esp)里面的值和1相比,也即是我们输入的第二个数字必须和1相等才能跳过爆炸。然后lea 0x20(%esp),%ebx,将0x20(%esp)保存在%ebx中,lea 0x30(%esp),%ebx,将0x30(%esp)保存在%esi中,mov -0x8(%ebx),%eax,实际是将0x28(%esp)保存在%eax中,然后在和-0x4(%ebx)相加,在判断和0x20(%esp)是否相等,这里必须相等否则就会boom,这几行代码实际上是将我们输入的第一个数和第二个数相加看是否等于我们输入的第三个数,相等继续否则爆炸,接下来的代码也是如此,实际phase_2对我们的输入要求是输入5个以上的数字,其中第一个数字是0,第二个数字是1,后续的数字是前两个数字之和即可。
正确,第二关完成。
三、Phase_3
第三关看上去很长实际很简单,实际就是一个跳转表,照例分析,前面还是老套路传参,直接看mov $0x804a3e3,%eax这里又给了东西,查看一下:
继续往下看,后面调用函数之后将返回值与1比较,大于1不爆炸,可推测这关应该要输入两个整数了,之后0x18(%esp)内的值和7比较,小于等于7不爆炸,所以这里得到一个初步的认识第一个数的范围要x<=7,然后根据*0x804a220( ,%eax,4)进行跳转,执行后续一系列计算就可以了。
按照上述分析,我们输入1,经过一系列加减算出来%eax值为109,cmp1 $0x5,0x18(%esp),这里说明我们输入的第一个数不仅仅要小于等于7,还必须小于等于5,cmp 0x1c(%esp),%eax,这里将我们刚刚算出来的值和我们输入的第二个数进行比较,不等就爆炸,所以根据我们刚才分析,如果我们输入的第一个数为1,则第二个数必为109,其他输入答案也类似,只是第一个输入必须小于等于5.
第三关完成!
四、Phase_4
Mov $0x804a3e3,0x4(%esp),查看发现和上一关一样也是输入两个整数。
mov 0x18(%esp),%eax
test %eax,%eax
js 0x8048d24 这里判断输入的第一个数是不是负数,是负数就爆炸
cmp $0xe,%eax
jle 0x8048d29 输入的第一个数必须大于0小于等于14,否则就爆炸
下面又是调用函数func了,并且我们看到它的返回值还必须和0x13相等,否则就爆炸。
进入func4查看功能:
func4是个递归函数,具体干什么没太懂,func4递归自身,初步可以推测func4是用来确定我们输入的第一个数的,回到phase_4,我们看到cmpl 0x13,0x1c(%esp),所以我们就知道了我们输入的第二个数必须是19,至于第一个数分析func4递归自身没找到太好的方法,只把从0-14作为第一个数都试了一遍。最后发现输入1 和19可通过此关。
第四关完成。
五、Phase_5
又调用string_length,照例查看功能:
该函数的返回值和6比较,不为6则爆炸,这题应该是要我们输入长度为6的字符串。
mov $0x0,%edx
mov $0x0,%eax
movsbl (%ebx,%eax,1),%ecx联系下面代码可知,这里是取出字符串的第i个字符做符号扩展
and $0xf,%ecx 取第i个字符的二进制的后4位
再根据 add 0x804a240( ,%ecx,4),%edx
,查找到0x804a240( ,%ecx,4)
的值加到%edx中
后面的add $0x1,%eax,
和 cmp $0x6,%eax
循环执行上述操作,把整个字符串的每个字符都做如上操作,最后%edx的值和0x30比较,只有0x30等于的%edx才不爆炸。也就是说,这道题要求我们输入的6个字符,每个字符取其二进制的后4位,然后计算出一个地址,跳转到那里去,把计算出来的地址里面的值放到累加器中,最后累加器的值必须到达0x30.
接下来我们需要知道计算出来的地址里面的值是什么,我们才能够判断我们怎么输入才能使一系列操作后的累加器的值必须到达0x30,先查看首地址0x804a240,新地址都是以它为根据算出来的,查看:
所以我们只要在这上面这些之中选取6个出来累加能够到达0x30,再反向推输入就可以了,方便计算我选了6个都是0x0000008,其地址为0x804a274,所以根据add 0x804a240( ,%ecx,4),%edx,我们可以算出%ecx值为13,因为我们查找的6个地址都相同,所以我们输入的六个字符都相同(在我这种选取地址的情况下),六个字符的二进制的后4位的十进制表示都为13,所以我们可推出一种输入可能为MMMMMM。输入查看。
第五关通过!
六、Phase_6
看到call 0x804921b<read_six_number>,和上述关口一样读入六个数
mov 0x10(%esp,%esi,4),%eax
sub $0x1,%eax
cmp $0x5,%eax
jbe 0x8048dd2 <phase_6+47> //无符号比较
call 0x80490e6 <explode_bomb>
add $0x1,%esi
cmp $0x6,%esi
je 0x8048e0d<phase_6+106>
由这几行代码我们可以知道读入的六个数字都不大于6并且由前面无符号比较跳转可知,我们输入的6个数都大于0小于等于6.
下面从0x08048dda到0x08048e27实际是确定输入的六个数互不相同,根据上述两个循环我们就初步得出要我们输入6个取值范围是从1到6的互不相同的整数。后续代码则是对0x804c13c为首地址的链表中的六个数进行升序排序,排序也就是说根据我们输入的值来对链表的值进行排序,而我们输入的值则是升序排序完成后每个元素在未排序之前在链表中相应的编号,查看这6个元素组成的链表:
可以得到这六个数依次为0x236、0x116、0x169、0x357、0x306、0x356,排序后0x116、0x169、0x236、0x306、0x356、0x357,所以此题我们需要输入的六个数字是2、3、1、5、6、4
第六关完成!
七、隐藏关
通过查看C代码,我们发现在每个阶段后面都有一个phase_defused(),查看
我们发现有一个secret_phase,查看发现它也会引起爆炸,其中cmpl $0x6,0x804c3cc,推测有可能只有当我们解决了前6关才会出现隐藏关,查看secret_phase:
在secret_phase中看见有调用函数read_line,应该是这里触发的隐藏关,反复查看secret_phase和phase_defused,找到0x0804929e movl $0x804a3e9,0x4(%esp)传递了一个东西,查看:
然后这个我们多于的字符和0x804a3f2里的内容发生strings_not_equal调用,查看0x804a3f2里的内容:
推测可能是在前面某个阶段输入两个整数时后面多输入了DrEvile才能触发隐藏关,不知道在哪次输入就都试一次:
现在开启了隐藏关。
回到phase_secret.调用fun7之后要求返回值必须为0x2,查看fun7功能:
这个函数会用来对一颗二叉树进行查询操作,最初传入函数的那个地址就是根节点的地址,当查询值大于当前节点的值的时候,递归查询右子树,否则递归查询左子树,直到查到所要的数为止。
演算值会查询三次,根据链表第一个地址0x804c088往后查找,查到0x16,输入值应该为22。
结束。