CSAPP LAB2:BOMB LAB 拆个炸弹玩玩
Contents
顾名思义,这个实验要求我们拆”炸弹”,炸弹是一个可执行程序,按照实验材料所给的提示,我们要利用反汇编工具来找出拆除炸弹的方法,最终拆掉所有的炸弹。这个实验还是十分有意思的,运用游戏化的方法让我们掌握反汇编的技能,提高阅读汇编码的能力,不得不佩服设计者。
下面我们来拆炸弹,老师给了我们一个炸弹大礼包,里头有好多个炸弹,我选择拆实验材料中的bomb1。按提示我们用objdump工具反汇编一下可执行文件,可以看到它的汇编代码,就像下图:
可以观察到程序中有phase1~6和secret_phase七个函数,从名字上看来它们就对应着我们要拆的炸弹,看来设计者也是个会玩的家伙,隐藏关卡都做了.. 为了方便,我将反汇编后得到的汇编代码输出到文本文件中,下面我们来一个个拆掉这些炸弹。
Phase1
下面我们来看看第一关的代码:
|
|
也就十几行,看起来就比较简单,观察一下,再由这里调用的函数名称分析可以得出,这关需要输入一个字符串与程序自带的某个字符串进行比较,如果两个字符串相等则过关,不相等就调用爆炸函数。然而我们要输入什么字符串呢?再观察一下,
movl $0x8049978,0x4(%esp)
这个地址看起来就很可疑,尝试使用gdb来打印一下这个地址里的内容:
于是找到了过关的密码,When I get angry, Mr. Bigglesworth gets upset. (感觉好像有哪里不太对😏)成功过关~
Phase2
下面是代码,比phase1要长了不少呢:
|
|
可以看出这关是调用了read_six_numbers函数读入六个数,放在内存的某块地方,然后比较一下是不是那六个数。再看看下面的代码,先读出输入的第一个数,比较一下它是否为1,不为1就爆炸。之后是个循环,认真分析一下代码(或者在纸上模拟执行一下)就能发现它就是个算阶乘的函数,所以过关密码为1 2 6 24 120 720
(网上这一关有的是算等比数列的,我差点就去找公比了_(:зゝ∠)_)
Phase3
比phase2 更长了,下面上代码:
|
|
具体分析我在代码旁也写了注释,这关看起来是个case句,先读入两个数,限制第一个数只能是2, 3, 4, 5, 6, 7中的一个,然后根据第一个数来确定第二个数,答案有好几组,不唯一,我这里得到的答案是2 138
Phase4
这关居然是递归函数!简直吓一跳
|
|
这关的本体不长,大概就是要求你输入一个正数,然后将这个数作为参数传递给fun4,然后判断fun4的返回值是否是117649.于是我们来看看fun4,模拟一下它的执行就能发现这就是个算7的n次方的函数,n为在phase4中传进去的参数。用计算器算一下就知道\(7^6=117649\),所以本关答案是6
Phase5
这关看起来很短,给人一种这关一定好简单的错觉
|
|
认为它好简单真的是一种错觉!这关卡了我将近2小时!这关先判断输入字符串的长度是否为6,不是就爆炸,之后坑爹的来了!大概说一下,这里先对输入的那个字符串做了个处理,把字符串中的字符一个个取出来,and $0xf,%eax
这句是取了每个字符的ASCII码的后一位(比如ASCII码为0x63,得到的结果为3),之后将这个数作为以某个地址为基址的偏移量,从中取出那个字符,组成一个新的字符串,再判断是否为特定的字符串。特定字符串放在0x80499d3
中,用gdb查看其中的内容为”ravens”。再看 0x804a5c0
中的内容,为”isrveawhobpnutfg\207\001”(后面那个\207\001我也不知道是什么鬼反正对这里没影响),所以我们的偏移量分别为2, 5, 3, 4, b, 1,故一组答案为becdka(答案不唯一)
Phase6
这关代码长得要死,实验说明也说the last phase will challenge even the best student. 那像我这种咸鱼肯定是要被challenge的嘛,那让我来看一看它。
|
|
看到这关首先是读入六个数,然后做出一个判断,是否为1~6间的整数,之后再判断他们是否两两相等,若有相等的数就爆炸。说穿了就是让你输个1~6的排列进去,至于是按什么顺序排列嘛,我们继续往下看。结果我发现它mov来mov去好像也看不懂它干了啥╰( ̄▽ ̄)╭只看出最后它要求某些地址的东西要按照从大到小来排序,顺序错了就爆炸。哎呀我实在没什么头绪了,然后发现movl $0x804a60c,-0x10(%ebp)
这里的地址看起来很可疑,其中必有蹊跷,于是用gdb查看了一下,发现它带了个<node>的标签_(:зゝ∠)_嗯这不就是个链表么?
于是我再用x/3w打印出连续3个字里的内容,果然是个链表,这里存了一个数,一个1~6之间的数,下一节点的地址。于是将这六个节点的内容都打印出来,再将数按照从大到小排序,得到的过关答案为1 5 3 4 6 2 至此,除隐藏关外的所有炸弹都拆完啦(╯‵□′)╯……*~●
Secret Phase
由于我比较好奇,而且现在考完试啦~\(≧▽≦)/~最后还是决定挑战一下隐藏关卡,下面是本关代码:
|
|
这又是一个递归函数,而且比phase4的递归长好多!看来这绝对不是盏省油的灯,我先从主体函数看起吧。好像本体也没什么东西,就是让你输个数进去然后把你输的数作为参数传进fun7里面看它是否返回2,不是就爆炸。那么我们来分析fun7,别看它是递归的函数,分析一下它就三种情况,用c语言写出来就是这样:
|
|
其实就是一个二叉树啊!要想要它返回2,就是要先有*a=b,之后*a < b,最后*a > b。由数据结构的知识,很快能确定出我们要查找的元素的位置,查出来应该输入22.(这里忘记截图了)
其实还有一个比较重要的问题,我们如何进入隐藏关啊?上面拆完6个炸弹就没有然后了啊,这时我们发现phase_defused这个神奇的函数,每拆完一个炸弹都会调用一次,下面是它的代码:
|
|
分析可知,这个函数会先判断你是否拆完6个炸弹,之后判断你是否在某个地方输入了某个字符串。字符串很好找,就在0x8049e7e
里面,用gdb可以得到该字符串为“austinpower”。问题就是在哪里输入,再看前面mov了一些地址,把那些地址里的东西都看一看发现,一个是6,一个是“%d %s”,后面那个是sscanf的参数,那么前面那个6是什么?可以发现6所在的这个地址是带有label的,用gdb看看它的前后是什么,就能发现这个就是第四关输入的东西。也就是说,在第四关过关密码输入的6后面再加个austinpower就能进入隐藏关了。
下面是过关截图:
啦啦啦至此炸弹都拆完了~请叫我拆弹小公举<(* ̄▽ ̄*)/
Author xymeow
LastMod 2015-06-03