bomb二进制炸弹拆除实验(MIPS)

上学期计算机系统基础课程的一个实验,在这里再简略整理一下:

实验要求:

仅给定一个MIPS二进制可执行文件bomb,要求运用GDB调试工具,通过分析反汇编代码来输入正确的参数以拆除炸弹。


辅助工具推荐:

静态反编译软件 IDA Pro


实验步骤:

由于前几个炸弹较为简单,故只重点叙述一下最后两个炸弹的拆弹过程

PHASE_1:

通过阅读phase_1的反汇编代码,在0x00400d90处设置断点,进行单步调试,查看$a0和$a1寄存器的状态,同时查看内存中存储的数据,可看到$a0里面保存着我们输入的字符串,$a1里面保存的字符串为”Let’s begin now!”,为了使两个字符串相匹配,故输入$a1里保存的字符串的内容,即可跳过第一个炸弹。


PHASE_2:

通过阅读phase_2的反汇编代码发现,在phase_2中存在两个引爆点,第一个引爆点是判断我们输入的数字个数是否为6,若不为6则爆炸,第二个引爆点则是比较$a0与$v0是否相等,循环比较六次,即逐个与我们输入的六个数字进行比较,若不相等则爆炸,故在0x00400e84处设置断点,查看$a0,$v0寄存器中的内容,不断调整我们的输入,使$a0与$v0相等,即可跳过引爆点,最后发现答案为我们输入ID后5位的累乘结果。


PHASE_3:

通过阅读phase_3的反汇编代码发现,phase_3要求的输入格式为”%d %c %d”,

并且发现phase_3首先是一个针对我们输入的第一个整数的switch-case结构,观察每一个对应switch-case结构,发现每一个跳转中都有一个引爆点,且引爆的条件为$v1与$v0不相等,由于除了case3对应的程序段以外,其余的程序段都会在比较操作之前将一个立即数加载至$v0,故$v1与$v0必定不相等,因此我们得到第一个输入应为3。然后继续阅读反汇编代码发现最后一个引爆点在0x0040120C,为了绕过这个引爆点必须保证在0x00401204处的判断中$v1与$v0相等,故我们在此处设置断点,通过查看$v1与$v0的内容知,$v0中存储的是我们输入的字符,$v1中存储的字符为k,故我们的输入应为k。


PHASE_4:

通过阅读phase_4的反汇编代码发现,phase_4首先判断我们输入的ID的最后一位是奇数还是偶数,若为奇数则将func4的返回值与8进行比较,若为偶数则将func4的返回值与13进行比较,因为我们输入ID的最后一位为奇数,所以要控制func4的返回值为8才能跳过炸弹,接着阅读func4的反汇编代码,发现其对传入参数分别进行减一减二操作后再次调用func4,故func4为一递归函数,且其表达式为f(n)=f(n-1)+f(n-2),故联想到斐波那契序列,要控制我们的返回值为8,只需控制输入的数字为5即可。



PHASE_5:

通过阅读phase_5的反汇编代码发现,phase_5存在两个引爆点,第一个引爆点是判断我们输入的字符串长度是否为6,若不为6则爆炸,第二个引爆点则是判断我们输入的字符串是否与相关内存中存储的字符串相等,若不等则爆炸。继续阅读phase_5反汇编代码,发现在0x0040144C处进行了$v1与0xF的与操作,即取$v1的后四位,然后在0x0040147C处将0x41的内容加载到 $v0中,通过查看内存中的存储内容发现,其中存储的为一串长度为16的字符串” isrveawhobpnutfg”,然后继续阅读发现,在0x004014CC处,将$v0与10160相加后的结果存储到$a1中,之后调用strings_not_equal函数判断字符串是否相等,我们查看内存中存储的内容发现,其中存储的是字符串”giants”,我们在0x004014CC处设置断点,查看$a1寄存器中的内容,发现一个规律,即我们输入字符的后四位与长度为16的字符串一一对应,控制输入,使得在” isrveawhobpnutfg”中依次取得”giants”,即可跳过炸弹,答案为opekma。


PHASE_6:

由read_six_number函数可得知,该题要求我们输入六个非负整数

bomb二进制炸弹拆除实验(MIPS)

控制循环六次,依次判断输入的六个数字是否合法

bomb二进制炸弹拆除实验(MIPS)

判断输入的数字是否小于7,大于等于7则爆炸

bomb二进制炸弹拆除实验(MIPS)

判断输入的数字是否大于0,小于等于0则爆炸

bomb二进制炸弹拆除实验(MIPS)

阅读代码发现又存在一个内嵌循环,其中Loc_4015A8将$v0+1其实是为了控制循环次数,

即是向后读取一位,进行判断,Loc_401618中$v0与6进行判断,是跳出循环的终止条件,

Loc_4015c0则是判断$v0与$v1是否相等,由$v0与$v1装载的内容可知,是判断前后输入的数字是否相等,

不相等则引爆炸弹,相等则跳回到Loc_401618,对下一个数字进行判断。

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

 

bomb二进制炸弹拆除实验(MIPS)

以上部分是对输入信息的基本判断:

(1)输入六个非负整数

(2)输入整数范围为1~6

(3)输入的整数各不相等

然后跳出该双重循环,接着往下看,发现又进入一个新的循环,通过阅读汇编代码,可以大致地看出这一循环实现的操作是将我们输入的六个整数压入栈中保存

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

 

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

 

bomb二进制炸弹拆除实验(MIPS)

将我们输入的六个整数压入栈中之后,通过观察程序的跳转,发现进入了下一段操作,汇编代码如下:

这一部分的主要功能是设置循环的起始条件,

bomb二进制炸弹拆除实验(MIPS)

这一部分的主要功能是作为循环的终止条件,

bomb二进制炸弹拆除实验(MIPS)

仔细思考这一部分的汇编代码,这是循环操作实现的主体部分,由上一阶段的操作可知,此时栈中已经保存了我们输入的六个整数的信息

bomb二进制炸弹拆除实验(MIPS)

通过gdb设置断点进行调试查看,观察每次循环中$v0内容结果如下:

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

 

bomb二进制炸弹拆除实验(MIPS)

 

bomb二进制炸弹拆除实验(MIPS)

 

bomb二进制炸弹拆除实验(MIPS)

 

bomb二进制炸弹拆除实验(MIPS)

由此可得,这一循环操作其实是将六个整数按照我们输入的顺序进行连接,并且我们得到了六个节点的地址

以及节点中存储的数据:

Node1->253

Node2->725

Node3->301

Node4->997

Node5->212

Node6->432

上一阶段的操作结束后,接着往下阅读反汇编代码,发现又进入一层循环,

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

我们在0x4017F4和0x40183C分别设置断点进行调试查看:

bomb二进制炸弹拆除实验(MIPS)

发现$v0与$v1寄存器中存的值为我们上一阶段node1到node6中存的内容,且必须保持降序才能跳过炸弹,故我们调整输入的六个整数,使其对应节点中的内容保持降序即可跳过炸弹。

为了研究phase_6采用的哪一种数据结构,在该断点处依次打印由上一步得到的6个节点地址中的内容:

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

由节点存储的内容可以看出该数据结构为链表。


SECRET_PHASE:

首先阅读phase_defused反汇编代码:

bomb二进制炸弹拆除实验(MIPS)

 

bomb二进制炸弹拆除实验(MIPS)

在gdb中设置断点 b phase_defused

发现每次炸弹输入后都会进入该函数,而只有输入格式为 %d %s,且%s为“austinpowers”时,才能跳转到secret_phase,通过尝试发现只有phase4符合输入条件。

在401a1c、4018c0、4018ec、401938、401988处设置断点进行观察调试,

首先在secret_phase中的4019f8处会对我们的输入进行判断,当$v0小于等于0x3e9(1001)时才能跳过炸弹,

bomb二进制炸弹拆除实验(MIPS)

然后继续阅读secret_phase反汇编代码

bomb二进制炸弹拆除实验(MIPS)

发现,只有fun7的返回值等于7时才能跳过炸弹,故我们接着进入fun7进行观察,可以看出fun7为一个递归函数,并且观察下列fun7的反汇编代码发现,每调用一次fun7,都会对$v0进行乘2并加1,因为跳过炸弹的要求为返回值为7,故我们应该控制fun7的调用次数为4次

bomb二进制炸弹拆除实验(MIPS)

故我们进入fun7函数继续观察

在4018ec处$v0与$v1进行比较,$v0大于等于$v1时,函数跳转至loc_401924,其实这里即为控制调用次数的关键语句,通过观察寄存器发现在几次经过该点时$v1里的值分别为36、50、107、1001、……、

bomb二进制炸弹拆除实验(MIPS)

因此我们要控制调用次数为4次,则输入1001即可。

为了研究secret_phase的数据结构:我们在0x401928处设置断点查看v0寄存器里的内容如下:

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

bomb二进制炸弹拆除实验(MIPS)

 

bomb二进制炸弹拆除实验(MIPS)

 

bomb二进制炸弹拆除实验(MIPS)

根据数据画出下图:

bomb二进制炸弹拆除实验(MIPS)