MIPS反汇编拆炸弹
计算机系统原理的实验,参考了我的前舍友和不知道哪位同学的博客,不过写得也太简略了并且还有一些错误,更像是单纯的记录,对手头没代码的人大概没啥意义吧。所以就把我自己做时的带注释的代码贴住来吧,也不过是记录罢了。
两位同学的博客:
MIPS - 反汇编 - 拆炸弹 - bomb(如你所见直接把标题抄过来了)
bomb二进制炸弹拆除实验(MIPS)
如果有同校学弟做实验时看到这篇博客,还是希望可以先尽量尝试独立完成,实在没办法时再来参考。如有错误,欢迎指正。
前导知识
gdb操作请看:GDB汇编调试指令合集
MIPS相关知识请看:MIPS指令集及汇编完全解析
开拆前…
本实验含有六个炸弹(和一个隐藏炸弹 ),在运行程序开头,需要输入ID(学号),在之后的拆弹过程中会使用到。每个炸弹都需要输入一行数据,包括数字或字符串。需避开一个个引爆点来通关。
阅读反汇编代码时,最好能够前后联系,理解数行/一部分代码的功能。要逐渐熟练掌握MIPS指令集操作和寄存器含义,了解数据存储的位置和方式。
有???标记的是我暂时抱有疑惑的地方,可以忽视。
本文还未完成,随缘更新。
phase_1
第一个炸弹,主要是熟悉用。炸弹会调用函数strings_not_equal来比较输入字符串与存储的字符串是否相等,不需要理解该子函数的实现,只需要明白该函数的功能即可。读寄存器$a1中保存的字符串,为“Let’s begin now!”,即为我们要输入的内容。
00400900 <main>:...400ba4: 8fdc0010 lw gp,16(s8)400ba8: 0c1007fb jal 401fec <read_line> //读取输入400bac: 00000000 nop400bb0: 8fdc0010 lw gp,16(s8)400bb4: afc20020 sw v0,32(s8) //将读得的数据存入栈400bb8: 8fc40020 lw a0,32(s8) //并放入$a0中供函数phase_1使用400bbc: 0c10035b jal 400d6c <phase_1>...00400d6c <phase_1>:400d6c: 27bdffe0 addiu sp,sp,-32 //为当前函数开辟栈空间400d70: afbf001c sw ra,28(sp)400d74: afbe0018 sw s8,24(sp)400d78: 03a0f021 move s8,sp400d7c: afc40020 sw a0,32(s8) //将$a0的内容存入栈400d80: 8fc40020 lw a0,32(s8)400d84: 3c020040 lui v0,0x40400d88: 2445276c addiu a1,v0,10092 //加载参数到$a1400d8c: 0c10073e jal 401cf8 <strings_not_equal> //比较字符串$a0和$a1,不相等则$v0 = 1,否则$v0 = 1400d90: 00000000 nop400d94: 10400003 beqz v0,400da4 <phase_1+0x38> //若$v0 == 0则跳至0x00400da4处400d98: 00000000 nop400d9c: 0c10087c jal 4021f0 <explode_bomb> //否则若$v0 == 0则爆炸400da0: 00000000 nop400da4: 03c0e821 move sp,s8400da8: 8fbf001c lw ra,28(sp)400dac: 8fbe0018 lw s8,24(sp)400db0: 27bd0020 addiu sp,sp,32400db4: 03e00008 jr ra400db8: 00000000 nop
phase_2
该炸弹要求我们输入六个数字(看函数名称识功能,第1个数必须为1),之后进入循环中一个个对这些数字进行处理,将第i个数分别与学号倒数i位相乘结果与第i+1个数比较判断是否相等,意味着我们输入的六个数就是对ID后五位累乘的序列。为什么知道是ID后五位?读寄存器得到的。ID不够五位?那就相当于定义了一个变量却没有赋值,一样能解决这个炸弹。这个炸弹不理解代码强行在0x400e80处读$a0的值并反复尝试令其与$v0相等也能解决,当然不推荐就是了。
00400dbc <phase_2>:400dbc: 27bdffc0 addiu sp,sp,-64400dc0: afbf003c sw ra,60(sp)400dc4: afbe0038 sw s8,56(sp)400dc8: 03a0f021 move s8,sp400dcc: 3c1c0042 lui gp,0x42400dd0: 279cb190 addiu gp,gp,-20080400dd4: afbc0010 sw gp,16(sp)400dd8: afc40040 sw a0,64(s8)400ddc: 27c2001c addiu v0,s8,28400de0: 8fc40040 lw a0,64(s8)400de4: 00402821 move a1,v0400de8: 0c1006ea jal 401ba8 <read_six_numbers> //读入6个数字400dec: 00000000 nop400df0: 8fdc0010 lw gp,16(s8)400df4: 8fc3001c lw v1,28(s8) //m[$s8+28]存有读入的第一个数,将其存入$v1400df8: 24020001 li v0,1400dfc: 10620004 beq v1,v0,400e10 <phase_2+0x54> //判定$v1是否为1,不是则引爆400e00: 00000000 nop400e04: 0c10087c jal 4021f0 <explode_bomb>400e08: 00000000 nop400e0c: 8fdc0010 lw gp,16(s8)400e10: 24020001 li v0,1 //设定循环单次表达式$v0 = 1(i = 1)400e14: afc20018 sw v0,24(s8) //将$v0(i)存入栈400e18: 10000023 b 400ea8 <phase_2+0xec> //循环开始,跳至条件表达式400e1c: 00000000 nop400e20: 8fc20018 lw v0,24(s8) //将之前存在栈中的变量i取出400e24: 00000000 nop400e28: 2442ffff addiu v0,v0,-1 //$v0自减400e2c: 00021080 sll v0,v0,0x2 //$v0 = $v0 * 4(拓到1 int长度)400e30: 27c30018 addiu v1,s8,24 //第i个数的存放位置为m[$s8 + 24 + i * 4](一个int型变量占4个字节)400e34: 00621021 addu v0,v1,v0400e38: 8c440004 lw a0,4(v0) //将第i个数的值存入$a0(所以前面自减有意义吗)400e3c: 2403000c li v1,12400e40: 8fc20018 lw v0,24(s8) //将之前存在栈中的变量i取出400e44: 00000000 nop400e48: 00621023 subu v0,v1,v0 //$v0 = $v1(12) - $v0(i)400e4c: 8f83806c lw v1,-32660(gp) //读得输入的学号400e50: 00021080 sll v0,v0,0x2 //$v0 = $v0 * 4(拓到1 int长度)400e54: 00621021 addu v0,v1,v0 //$v0 = $v1 + $v0400e58: 8c420000 lw v0,0(v0) //将学号的倒数i位读入$v0中400e5c: 00000000 nop400e60: 00820018 mult a0,v0 //$a0与$v0相乘400e64: 00002012 mflo a0 //将结果存入$a0400e68: 8fc20018 lw v0,24(s8) //将之前存在栈中的变量i取出400e6c: 00000000 nop400e70: 00021080 sll v0,v0,0x2 //$v0 = $v0 * 4(拓到1 int长度)400e74: 27c30018 addiu v1,s8,24 //第i个数得存放位置为m[$s8 + 24 + i * 4](一个int型变量占4个字节)400e78: 00621021 addu v0,v1,v0 //得到第i个数的位置400e7c: 8c420004 lw v0,4(v0) //将第i + 1个数的值存入$v0400e80: 00000000 nop400e84: 10820004 beq a0,v0,400e98 <phase_2+0xdc> //比较$a0(第i个数与学号的倒数i位相乘的结果)与$v0(第i + 1个数),若不相等则引爆400e88: 00000000 nop400e8c: 0c10087c jal 4021f0 <explode_bomb>400e90: 00000000 nop400e94: 8fdc0010 lw gp,16(s8) //末尾循环体400e98: 8fc20018 lw v0,24(s8)400e9c: 00000000 nop400ea0: 24420001 addiu v0,v0,1 //i自加400ea4: afc20018 sw v0,24(s8) //将i存入栈中400ea8: 8fc20018 lw v0,24(s8)400eac: 00000000 nop400eb0: 28420006 slti v0,v0,6 //判断循环是否结束,相当于i != 6(i < 6)400eb4: 1440ffda bnez v0,400e20 <phase_2+0x64>400eb8: 00000000 nop400ebc: 03c0e821 move sp,s8400ec0: 8fbf003c lw ra,60(sp)400ec4: 8fbe0038 lw s8,56(sp)400ec8: 27bd0040 addiu sp,sp,64400ecc: 03e00008 jr ra400ed0: 00000000 nop
phase_3
考察分支结构(switch…case…结构)。要求输入格式为"%d %c %d"(看调用数据时的指令得到的,word/byte的区别),第一个数就是switch语句中的变量,跳至不同的case语句(0到7共八个,超出直接引爆)。除case 3外,其他数均是要求一个数与输入的第三个数相乘的结果为指定的立即数,而case 3要求相乘结果为0。读寄存器可知该数为输入ID的最后一位。另外在每个case结构的开头都将一个字符存入栈中,在switch…case…结束后与我们输入的字符比较,令两个字符相等即可。
00400ed4 <phase_3>:400ed4: 27bdffc8 addiu sp,sp,-56400ed8: afbf0034 sw ra,52(sp)400edc: afbe0030 sw s8,48(sp)400ee0: 03a0f021 move s8,sp400ee4: 3c1c0042 lui gp,0x42400ee8: 279cb190 addiu gp,gp,-20080400eec: afbc0018 sw gp,24(sp)400ef0: afc40038 sw a0,56(s8)400ef4: 8fc40038 lw a0,56(s8)400ef8: 3c020040 lui v0,0x40400efc: 24452780 addiu a1,v0,10112400f00: 27c3002c addiu v1,s8,44400f04: 27c20028 addiu v0,s8,40400f08: 27c60024 addiu a2,s8,36400f0c: afa60010 sw a2,16(sp)400f10: 00603021 move a2,v1400f14: 00403821 move a3,v0400f18: 8f828084 lw v0,-32636(gp)400f1c: 00000000 nop400f20: 0040c821 move t9,v0400f24: 0320f809 jalr t9400f28: 00000000 nop400f2c: 8fdc0018 lw gp,24(s8)400f30: 28420003 slti v0,v0,3 //判定输入的数据个数是否为3400f34: 10400004 beqz v0,400f48 <phase_3+0x74>400f38: 00000000 nop400f3c: 0c10087c jal 4021f0 <explode_bomb>400f40: 00000000 nop400f44: 8fdc0018 lw gp,24(s8)400f48: 8fc2002c lw v0,44(s8) //读入输入的第一个数至$v0400f4c: 00000000 nop400f50: 2c430008 sltiu v1,v0,8 //判断$v0是否小于8,是则继续,否则引爆400f54: 1060008e beqz v1,401190 <phase_3+0x2bc>400f58: 00000000 nop400f5c: 00021880 sll v1,v0,0x2 //$v1 = $v0 * 4,拓至1 int型变量长度400f60: 3c020040 lui v0,0x40400f64: 2442278c addiu v0,v0,10124400f68: 00621021 addu v0,v1,v0400f6c: 8c420000 lw v0,0(v0) //$v0对应case语句的地址,用x $v0查看400f70: 00000000 nop400f74: 00400008 jr v0 //switch语句,跳至相应的case语句400f78: 00000000 nop //case 0:400f7c: 24020071 li v0,113 //q的ASCII码400f80: a3c20020 sb v0,32(s8) //存入1byte的数据400f84: 8f82806c lw v0,-32660(gp)400f88: 00000000 nop400f8c: 8c43002c lw v1,44(v0) //读入学号的最后一位400f90: 8fc20024 lw v0,36(s8) //读入输入数据的第三个数400f94: 00000000 nop400f98: 00620018 mult v1,v0400f9c: 00001812 mflo v1 //$v1 = $v1 * $v0400fa0: 24020309 li v0,777 //判断是否为777(=3*=7*111),是则break,否则引爆400fa4: 10620081 beq v1,v0,4011ac <phase_3+0x2d8>400fa8: 00000000 nop400fac: 0c10087c jal 4021f0 <explode_bomb>400fb0: 00000000 nop400fb4: 8fdc0018 lw gp,24(s8)400fb8: 1000008f b 4011f8 <phase_3+0x324>400fbc: 00000000 nop //case 1:400fc0: 24020062 li v0,98 //b的ASCII码400fc4: a3c20020 sb v0,32(s8) //存入1byte的数据400fc8: 8f82806c lw v0,-32660(gp)400fcc: 00000000 nop400fd0: 8c43002c lw v1,44(v0) //读入学号的最后一位400fd4: 8fc20024 lw v0,36(s8) //读入输入数据的第三个数400fd8: 00000000 nop400fdc: 00620018 mult v1,v0400fe0: 00001812 mflo v1 //$v1 = $v1 * $v0400fe4: 240200d6 li v0,214 //判断是否为214(=2*107),是则break,否则引爆400fe8: 10620073 beq v1,v0,4011b8 <phase_3+0x2e4>400fec: 00000000 nop400ff0: 0c10087c jal 4021f0 <explode_bomb>400ff4: 00000000 nop400ff8: 8fdc0018 lw gp,24(s8)400ffc: 1000007e b 4011f8 <phase_3+0x324>401000: 00000000 nop //case 2:401004: 24020062 li v0,98 //b的ASCII码401008: a3c20020 sb v0,32(s8) //存入1byte的数据40100c: 8f82806c lw v0,-32660(gp)401010: 00000000 nop401014: 8c43002c lw v1,44(v0) //读入学号的最后一位401018: 8fc20024 lw v0,36(s8) //读入输入数据的第三个数40101c: 00000000 nop401020: 00620018 mult v1,v0401024: 00001812 mflo v1 //$v1 = $v1 * $v0401028: 240202f3 li v0,755 //判断是否为755(=5*151),是则break,否则引爆40102c: 10620065 beq v1,v0,4011c4 <phase_3+0x2f0>401030: 00000000 nop401034: 0c10087c jal 4021f0 <explode_bomb>401038: 00000000 nop40103c: 8fdc0018 lw gp,24(s8)401040: 1000006d b 4011f8 <phase_3+0x324>401044: 00000000 nop //case 3:401048: 2402006b li v0,107 //k的ASCII码40104c: a3c20020 sb v0,32(s8) //存入1byte的数据401050: 8f82806c lw v0,-32660(gp)401054: 00000000 nop401058: 8c43002c lw v1,44(v0) //读入学号的最后一位40105c: 8fc20024 lw v0,36(s8) //读入输入数据的第三个数401060: 00000000 nop401064: 00620018 mult v1,v0401068: 00001012 mflo v0 //$v0 = $v1 * $v040106c: 10400058 beqz v0,4011d0 <phase_3+0x2fc> //判断$v0是否等于0,是则break,否则引爆401070: 00000000 nop401074: 0c10087c jal 4021f0 <explode_bomb>401078: 00000000 nop40107c: 8fdc0018 lw gp,24(s8)401080: 1000005d b 4011f8 <phase_3+0x324>401084: 00000000 nop //case 4:401088: 2402006f li v0,111 //o的ASCII码40108c: a3c20020 sb v0,32(s8) //存入1byte的数据401090: 8f82806c lw v0,-32660(gp)401094: 00000000 nop401098: 8c43002c lw v1,44(v0) //读入学号的最后一位40109c: 8fc20024 lw v0,36(s8) //读入输入数据的第三个数4010a0: 00000000 nop4010a4: 00620018 mult v1,v04010a8: 00001812 mflo v1 //$v1 = $v1 * $v04010ac: 240200e4 li v0,228 //判断是否为228(=2*114=4*57),是则break,否则引爆 ???4010b0: 1062004a beq v1,v0,4011dc <phase_3+0x308>4010b4: 00000000 nop4010b8: 0c10087c jal 4021f0 <explode_bomb>4010bc: 00000000 nop4010c0: 8fdc0018 lw gp,24(s8)4010c4: 1000004c b 4011f8 <phase_3+0x324>4010c8: 00000000 nop //case 5:4010cc: 24020074 li v0,116 //t的ASCII码4010d0: a3c20020 sb v0,32(s8) //存入1byte的数据4010d4: 8f82806c lw v0,-32660(gp)4010d8: 00000000 nop4010dc: 8c43002c lw v1,44(v0) //读入学号的最后一位4010e0: 8fc20024 lw v0,36(s8) //读入输入数据的第三个数4010e4: 00000000 nop4010e8: 00620018 mult v1,v04010ec: 00001812 mflo v1 //$v1 = $v1 * $v04010f0: 24020201 li v0,513 //判断是否为513(=3*171=9*57),是则break,否则引爆4010f4: 1062003c beq v1,v0,4011e8 <phase_3+0x314>4010f8: 00000000 nop4010fc: 0c10087c jal 4021f0 <explode_bomb>401100: 00000000 nop401104: 8fdc0018 lw gp,24(s8)401108: 1000003b b 4011f8 <phase_3+0x324>40110c: 00000000 nop //case 6:401110: 24020076 li v0,118 //v的ASCII码401114: a3c20020 sb v0,32(s8) //存入1byte的数据401118: 8f82806c lw v0,-32660(gp)40111c: 00000000 nop401120: 8c43002c lw v1,44(v0) //读入学号的最后一位401124: 8fc20024 lw v0,36(s8) //读入输入数据的第三个数401128: 00000000 nop40112c: 00620018 mult v1,v0401130: 00001812 mflo v1 //$v1 = $v1 * $v0401134: 2402030c li v0,780 //判断是否为780(=2*390=3*260=4*195=5*156=6*130),是则break,否则引爆401138: 10620004 beq v1,v0,40114c <phase_3+0x278>40113c: 00000000 nop401140: 0c10087c jal 4021f0 <explode_bomb>401144: 00000000 nop //case 7:401148: 8fdc0018 lw gp,24(s8) ???40114c: 24020062 li v0,98 //b的ASCII码401150: a3c20020 sb v0,32(s8) //存入1byte的数据401154: 8f82806c lw v0,-32660(gp)401158: 00000000 nop40115c: 8c43002c lw v1,44(v0) //读入学号的最后一位401160: 8fc20024 lw v0,36(s8) //读入输入数据的第三个数401164: 00000000 nop401168: 00620018 mult v1,v040116c: 00001812 mflo v1 //$v1 = $v1 * $v0401170: 24020338 li v0,824 //判断是否为824(=2*412=4*206),是则break,否则引爆401174: 1062001f beq v1,v0,4011f4 <phase_3+0x320>401178: 00000000 nop40117c: 0c10087c jal 4021f0 <explode_bomb>401180: 00000000 nop401184: 8fdc0018 lw gp,24(s8)401188: 1000001b b 4011f8 <phase_3+0x324>40118c: 00000000 nop401190: 24020078 li v0,120401194: a3c20020 sb v0,32(s8)401198: 0c10087c jal 4021f0 <explode_bomb>40119c: 00000000 nop4011a0: 8fdc0018 lw gp,24(s8)4011a4: 10000014 b 4011f8 <phase_3+0x324>4011a8: 00000000 nop4011ac: 00000000 nop4011b0: 10000011 b 4011f8 <phase_3+0x324>4011b4: 00000000 nop4011b8: 00000000 nop4011bc: 1000000e b 4011f8 <phase_3+0x324>4011c0: 00000000 nop4011c4: 00000000 nop4011c8: 1000000b b 4011f8 <phase_3+0x324>4011cc: 00000000 nop4011d0: 00000000 nop4011d4: 10000008 b 4011f8 <phase_3+0x324>4011d8: 00000000 nop4011dc: 00000000 nop4011e0: 10000005 b 4011f8 <phase_3+0x324>4011e4: 00000000 nop4011e8: 00000000 nop4011ec: 10000002 b 4011f8 <phase_3+0x324>4011f0: 00000000 nop4011f4: 00000000 nop4011f8: 83c20028 lb v0,40(s8) //输入的第二个字符数据4011fc: 83c30020 lb v1,32(s8) //将case语句中存的字符取出401200: 00000000 nop401204: 10620004 beq v1,v0,401218 <phase_3+0x344> //比较,不相等则引爆401208: 00000000 nop40120c: 0c10087c jal 4021f0 <explode_bomb>401210: 00000000 nop401214: 8fdc0018 lw gp,24(s8)401218: 03c0e821 move sp,s840121c: 8fbf0034 lw ra,52(sp)401220: 8fbe0030 lw s8,48(sp)401224: 27bd0038 addiu sp,sp,56401228: 03e00008 jr ra40122c: 00000000 nop
phase_4
该炸弹使用了if…else…语句和递归结构,学号最后一位的奇偶分别进入判断fun4(x)是否与8和13相等,很容易联想到斐波那契数列。而调用的fun4也是计算f(x)=f(x-1)+f(x-2),正是斐波那契数列的递归解法。那么输入的数字x就是函数fun4的参数。注意fun4定义f(0)=f(1)=1,与通常的斐波那契数列不同,所以答案为5或6。
00401230 <func4>:401230: 27bdffd8 addiu sp,sp,-40401234: afbf0024 sw ra,36(sp)401238: afbe0020 sw s8,32(sp)40123c: afb0001c sw s0,28(sp)401240: 03a0f021 move s8,sp401244: afc40028 sw a0,40(s8)401248: 8fc20028 lw v0,40(s8)40124c: 00000000 nop401250: 28420002 slti v0,v0,2 //判断$v0是否小于2,是则$v0 = 1401254: 14400011 bnez v0,40129c <func4+0x6c> //$v0 != 0则return 1401258: 00000000 nop40125c: 8fc20028 lw v0,40(s8)401260: 00000000 nop401264: 2442ffff addiu v0,v0,-1401268: 00402021 move a0,v040126c: 0c10048c jal 401230 <func4> //递归引用自身f(x - 1)401270: 00000000 nop401274: 00408021 move s0,v0 //将f(x - 1)的结果存入$s0401278: 8fc20028 lw v0,40(s8)40127c: 00000000 nop401280: 2442fffe addiu v0,v0,-2401284: 00402021 move a0,v0401288: 0c10048c jal 401230 <func4> //递归引用自身f(x - 2)40128c: 00000000 nop401290: 02021021 addu v0,s0,v0 //$v0 = f(x - 1) + f(x - 2),返回$v0401294: 10000002 b 4012a0 <func4+0x70>401298: 00000000 nop40129c: 24020001 li v0,1 //return 14012a0: 03c0e821 move sp,s84012a4: 8fbf0024 lw ra,36(sp)4012a8: 8fbe0020 lw s8,32(sp)4012ac: 8fb0001c lw s0,28(sp)4012b0: 27bd0028 addiu sp,sp,404012b4: 03e00008 jr ra4012b8: 00000000 nop004012bc <phase_4>:4012bc: 27bdffd8 addiu sp,sp,-404012c0: afbf0024 sw ra,36(sp)4012c4: afbe0020 sw s8,32(sp)4012c8: 03a0f021 move s8,sp4012cc: 3c1c0042 lui gp,0x424012d0: 279cb190 addiu gp,gp,-200804012d4: afbc0010 sw gp,16(sp)4012d8: afc40028 sw a0,40(s8)4012dc: 8fc30028 lw v1,40(s8)4012e0: 3c020040 lui v0,0x404012e4: 244227ac addiu v0,v0,101564012e8: 00602021 move a0,v14012ec: 00402821 move a1,v04012f0: 27c20018 addiu v0,s8,244012f4: 00403021 move a2,v04012f8: 8f828084 lw v0,-32636(gp)4012fc: 00000000 nop401300: 0040c821 move t9,v0401304: 0320f809 jalr t9401308: 00000000 nop40130c: 8fdc0010 lw gp,16(s8)401310: 00401821 move v1,v0401314: 24020001 li v0,1401318: 14620005 bne v1,v0,401330 <phase_4+0x74> //$v0 != 1则引爆40131c: 00000000 nop401320: 8fc20018 lw v0,24(s8)401324: 00000000 nop401328: 1c400005 bgtz v0,401340 <phase_4+0x84>40132c: 00000000 nop401330: 0c10087c jal 4021f0 <explode_bomb>401334: 00000000 nop401338: 8fdc0010 lw gp,16(s8)40133c: 00000000 nop401340: 8f82806c lw v0,-32660(gp)401344: 00000000 nop401348: 8c42002c lw v0,44(v0) //令$v0等于学号的最后一位40134c: 00000000 nop401350: 30420001 andi v0,v0,0x1 //判定奇偶401354: 304200ff andi v0,v0,0xff401358: 10400010 beqz v0,40139c <phase_4+0xe0> //if...else...结构,奇数(1)继续,偶数(0)跳转40135c: 00000000 nop401360: 8fc20018 lw v0,24(s8) //令$v0等于输入的第一个数401364: 00000000 nop401368: 00402021 move a0,v0 //传入参数40136c: 0c10048c jal 401230 <func4> //计算f(x)401370: 00000000 nop401374: 8fdc0010 lw gp,16(s8)401378: 00401821 move v1,v040137c: 24020008 li v0,8401380: 10620013 beq v1,v0,4013d0 <phase_4+0x114> //f(x) = $v1 != 8则引爆,则x = 5401384: 00000000 nop401388: 0c10087c jal 4021f0 <explode_bomb>40138c: 00000000 nop401390: 8fdc0010 lw gp,16(s8)401394: 1000000e b 4013d0 <phase_4+0x114>401398: 00000000 nop40139c: 8fc20018 lw v0,24(s8)4013a0: 00000000 nop4013a4: 00402021 move a0,v0 //传入参数4013a8: 0c10048c jal 401230 <func4> //计算f(x)4013ac: 00000000 nop4013b0: 8fdc0010 lw gp,16(s8)4013b4: 00401821 move v1,v04013b8: 2402000d li v0,134013bc: 10620004 beq v1,v0,4013d0 <phase_4+0x114> //f(x) = $v1 != 13则引爆,则x = 64013c0: 00000000 nop4013c4: 0c10087c jal 4021f0 <explode_bomb>4013c8: 00000000 nop4013cc: 8fdc0010 lw gp,16(s8)4013d0: 03c0e821 move sp,s84013d4: 8fbf0024 lw ra,36(sp)4013d8: 8fbe0020 lw s8,32(sp)4013dc: 27bd0028 addiu sp,sp,404013e0: 03e00008 jr ra4013e4: 00000000 nop
phase_5
输入字符串,要求其长度为6。进入循环中对每个字符进行处理,获取其二进制数的后四位(即ASCII码的b3b2b1b0),一一对应程序存储的长度为16的字符串S=“isrveawhobpnutfg”,即S[b3b2b1b0],炸弹要求这个映射获得的字符串为"giants",那么输入的字符串就可以是opekma,应当也可以是其他可以映射的字符串(大概没有限制?上机验证一下就知道了)
004013e8 <phase_5>:4013e8: 27bdffb8 addiu sp,sp,-724013ec: afbf0044 sw ra,68(sp)4013f0: afbe0040 sw s8,64(sp)4013f4: 03a0f021 move s8,sp4013f8: afc40048 sw a0,72(s8) //$a0为输入的字符串,将其存入栈中4013fc: 8fc40048 lw a0,72(s8)401400: 0c10071e jal 401c78 <string_length>401404: 00000000 nop401408: 00401821 move v1,v040140c: 24020006 li v0,6401410: 10620003 beq v1,v0,401420 <phase_5+0x38> //输入字符串长度$v1 != 6则引爆401414: 00000000 nop401418: 0c10087c jal 4021f0 <explode_bomb>40141c: 00000000 nop401420: afc00018 sw zero,24(s8) //i = 0401424: 10000020 b 4014a8 <phase_5+0xc0>401428: 00000000 nop40142c: 8fc20018 lw v0,24(s8) //读得i401430: 8fc30018 lw v1,24(s8) //读得i401434: 8fc40048 lw a0,72(s8) //从栈中取出输入的字符串(从0开始编号)401438: 00000000 nop40143c: 00831821 addu v1,a0,v1401440: 80630000 lb v1,0(v1) //读取输入字符串的第i个字符401444: 00000000 nop401448: 306300ff andi v1,v1,0xff40144c: 3063000f andi v1,v1,0xf //取字符转化为二进制数(1byte=8bit)的后四位401450: 00021080 sll v0,v0,0x2 //将i拓至1 int型变量长度401454: 27c40018 addiu a0,s8,24 //读得i的地址401458: 00821021 addu v0,a0,v040145c: ac43000c sw v1,12(v0) //将字符后四位存入m[$s8 + 36 + i * 4]401460: 8fc40018 lw a0,24(s8) //读得i401464: 8fc20018 lw v0,24(s8) //读得i401468: 00000000 nop40146c: 00021080 sll v0,v0,0x2 //将i拓至1 int型变量长度401470: 27c30018 addiu v1,s8,24 //读得i的地址401474: 00621021 addu v0,v1,v0401478: 8c43000c lw v1,12(v0) //读得字符后四位,存入$v1中40147c: 3c020041 lui v0,0x41401480: 244230ec addiu v0,v0,12524 //获取存储的字符串S(从0开始编号)的位置 $v0 = isrveawhobpnutfg401484: 00621021 addu v0,v1,v0 //得到第$v1个字符的内存地址401488: 80430000 lb v1,0(v0) //得到第$v1(输入字符串的第i个字符的后四位,即ASCII码的b3b2b1b0)个字符40148c: 27c20018 addiu v0,s8,24401490: 00441021 addu v0,v0,a0401494: a0430004 sb v1,4(v0) //将获得的字符存入m[$s8 + 28 + i]401498: 8fc20018 lw v0,24(s8) //读得i40149c: 00000000 nop4014a0: 24420001 addiu v0,v0,1 //i++4014a4: afc20018 sw v0,24(s8)4014a8: 8fc20018 lw v0,24(s8)4014ac: 00000000 nop4014b0: 28420006 slti v0,v0,6 //$v0 = ($v0 < 6 ? 1 : 0),为1再循环一次,即i < 64014b4: 1440ffdd bnez v0,40142c <phase_5+0x44>4014b8: 00000000 nop4014bc: a3c00022 sb zero,34(s8) //将字符串尾设为'\0'4014c0: 27c2001c addiu v0,s8,284014c4: 00402021 move a0,v0 //从内存中获取依靠映射从存储的字符串S中得到的字符串4014c8: 3c020040 lui v0,0x404014cc: 244527b0 addiu a1,v0,10160 //从内存中获取用来比较的字符串4014d0: 0c10073e jal 401cf8 <strings_not_equal> //比较$a0,$a14014d4: 00000000 nop4014d8: 10400003 beqz v0,4014e8 <phase_5+0x100>4014dc: 00000000 nop4014e0: 0c10087c jal 4021f0 <explode_bomb>4014e4: 00000000 nop4014e8: 03c0e821 move sp,s84014ec: 8fbf0044 lw ra,68(sp)4014f0: 8fbe0040 lw s8,64(sp)4014f4: 27bd0048 addiu sp,sp,724014f8: 03e00008 jr ra4014fc: 00000000 nop
phase_6
b* 0x4016e0
r
//node[] = {0fd, 2d5, 12d, 3e5, 0d4, 1b0}
x $v1 //node[i]
c
x $v1
c
x $v1
c
x $v1
c
x $v1
c
x $v1
c00401500 <phase_6>:401500: 27bdffa0 addiu sp,sp,-96401504: afbf005c sw ra,92(sp)401508: afbe0058 sw s8,88(sp)40150c: 03a0f021 move s8,sp401510: 3c1c0042 lui gp,0x42401514: 279cb190 addiu gp,gp,-20080401518: afbc0010 sw gp,16(sp)40151c: afc40060 sw a0,96(s8)401520: 3c020041 lui v0,0x41401524: 24423130 addiu v0,v0,12592401528: afc20020 sw v0,32(s8)40152c: 27c20024 addiu v0,s8,36401530: 8fc40060 lw a0,96(s8)401534: 00402821 move a1,v0401538: 0c1006ea jal 401ba8 <read_six_numbers> # 输入六个数字40153c: 00000000 nop # 第一层循环的初始条件设定401540: 8fdc0010 lw gp,16(s8)401544: afc0001c sw zero,28(s8) # i = 0401548: 1000003c b 40163c <phase_6+0x13c> # 跳至0x40163c处条件判断处40154c: 00000000 nop # 第一层循环中间循环体开始401550: 8fc2001c lw v0,28(s8) # 获取i401554: 00000000 nop401558: 00021080 sll v0,v0,0x2 #拓至1int长度40155c: 27c30018 addiu v1,s8,24401560: 00621021 addu v0,v1,v0401564: 8c42000c lw v0,12(v0) # 得到输入的第i个数401568: 00000000 nop40156c: 28420007 slti v0,v0,7 # 判断第i个数是否小于7401570: 1040000a beqz v0,40159c <phase_6+0x9c> # 否则引爆401574: 00000000 nop401578: 8fc2001c lw v0,28(s8)40157c: 00000000 nop401580: 00021080 sll v0,v0,0x2401584: 27c30018 addiu v1,s8,24401588: 00621021 addu v0,v1,v040158c: 8c42000c lw v0,12(v0)401590: 00000000 nop401594: 1c400004 bgtz v0,4015a8 <phase_6+0xa8> # 判断第i个数是否大于0,否则引爆401598: 00000000 nop40159c: 0c10087c jal 4021f0 <explode_bomb>4015a0: 00000000 nop4015a4: 8fdc0010 lw gp,16(s8)4015a8: 8fc2001c lw v0,28(s8)4015ac: 00000000 nop # 第二层循环的初始条件设定4015b0: 24420001 addiu v0,v0,1 # j = i + 14015b4: afc20018 sw v0,24(s8) # 将j存至m[$s8 + 24]处4015b8: 10000017 b 401618 <phase_6+0x118> # 跳至0x401618条件判断处4015bc: 00000000 nop # 第二层循环中间循环体开始4015c0: 8fc2001c lw v0,28(s8) # 获取i4015c4: 00000000 nop4015c8: 00021080 sll v0,v0,0x24015cc: 27c30018 addiu v1,s8,244015d0: 00621021 addu v0,v1,v04015d4: 8c43000c lw v1,12(v0) # 获取第i个数4015d8: 8fc20018 lw v0,24(s8) # 获取j4015dc: 00000000 nop4015e0: 00021080 sll v0,v0,0x24015e4: 27c40018 addiu a0,s8,244015e8: 00821021 addu v0,a0,v04015ec: 8c42000c lw v0,12(v0) # 获取第j个数4015f0: 00000000 nop4015f4: 14620004 bne v1,v0,401608 <phase_6+0x108> #判断第i个数和第j个数是否不相等,否则爆炸4015f8: 00000000 nop4015fc: 0c10087c jal 4021f0 <explode_bomb>401600: 00000000 nop401604: 8fdc0010 lw gp,16(s8)401608: 8fc20018 lw v0,24(s8)40160c: 00000000 nop # 第二层循环末尾循环体401610: 24420001 addiu v0,v0,1 # j++401614: afc20018 sw v0,24(s8)401618: 8fc20018 lw v0,24(s8) # 第二层循环条件判断处40161c: 00000000 nop401620: 28420006 slti v0,v0,6 # 当j < 6时,继续循环401624: 1440ffe6 bnez v0,4015c0 <phase_6+0xc0>401628: 00000000 nop40162c: 8fc2001c lw v0,28(s8) # 获取i401630: 00000000 nop # 第一层循环末尾循环体401634: 24420001 addiu v0,v0,1 # i++401638: afc2001c sw v0,28(s8)40163c: 8fc2001c lw v0,28(s8) # 第一层循环条件判断处401640: 00000000 nop401644: 28420006 slti v0,v0,6 # 当i < 6 时,继续循环401648: 1440ffc1 bnez v0,401550 <phase_6+0x50>40164c: 00000000 nop # 第一层循环的初始条件 401650: afc0001c sw zero,28(s8) # i = 0401654: 10000028 b 4016f8 <phase_6+0x1f8> # 跳至条件判断处401658: 00000000 nop # 第二层循环的初始条件40165c: 3c020041 lui v0,0x41401660: 24423130 addiu v0,v0,12592 # 令$v0等于&firstnode = 0x413130401664: afc20020 sw v0,32(s8) # m[$s8 + 32] = &firstnode401668: 24020001 li v0,1 # j = 140166c: afc20018 sw v0,24(s8)401670: 1000000a b 40169c <phase_6+0x19c> # 跳至条件判断处401674: 00000000 nop401678: 8fc20020 lw v0,32(s8) # 取得&node40167c: 00000000 nop401680: 8c420008 lw v0,8(v0) # $v0 = m[$v0 + 8]401684: 00000000 nop401688: afc20020 sw v0,32(s8) # node = node->next40168c: 8fc20018 lw v0,24(s8) # 取得j401690: 00000000 nop401694: 24420001 addiu v0,v0,1 # j++401698: afc20018 sw v0,24(s8)40169c: 8fc2001c lw v0,28(s8) # 取得i4016a0: 00000000 nop4016a4: 00021080 sll v0,v0,0x24016a8: 27c30018 addiu v1,s8,244016ac: 00621021 addu v0,v1,v04016b0: 8c43000c lw v1,12(v0) # 取得输入的第i个数4016b4: 8fc20018 lw v0,24(s8)4016b8: 00000000 nop4016bc: 0043102a slt v0,v0,v1 # 判断j是否小于输入的第i个数,是则循环继续4016c0: 1440ffed bnez v0,401678 <phase_6+0x178>4016c4: 00000000 nop4016c8: 8fc2001c lw v0,28(s8) # 取得i4016cc: 00000000 nop4016d0: 00021080 sll v0,v0,0x24016d4: 27c30018 addiu v1,s8,244016d8: 00621021 addu v0,v1,v04016dc: 8fc30020 lw v1,32(s8) # 将node = [链表的第j/【输入的第i个数】个取出4016e0: 00000000 nop4016e4: ac430024 sw v1,36(v0) # 存入数组res的res[i]中4016e8: 8fc2001c lw v0,28(s8)4016ec: 00000000 nop4016f0: 24420001 addiu v0,v0,14016f4: afc2001c sw v0,28(s8)4016f8: 8fc2001c lw v0,28(s8) # 条件判断处4016fc: 00000000 nop401700: 28420006 slti v0,v0,6 # i < 6 则循环继续401704: 1440ffd5 bnez v0,40165c <phase_6+0x15c>401708: 00000000 nop40170c: 8fc2003c lw v0,60(s8)401710: 00000000 nop401714: afc20020 sw v0,32(s8) # node = firstnode ???401718: 24020001 li v0,140171c: afc2001c sw v0,28(s8) # i = 1401720: 10000016 b 40177c <phase_6+0x27c>401724: 00000000 nop # 循环开始401728: 8fc2001c lw v0,28(s8) # 取得i40172c: 00000000 nop401730: 00021080 sll v0,v0,0x2401734: 27c30018 addiu v1,s8,24401738: 00621021 addu v0,v1,v040173c: 8c430024 lw v1,36(v0) # 取得res[i]401740: 8fc20020 lw v0,32(s8) # 取得node401744: 00000000 nop401748: ac430008 sw v1,8(v0) # node->next = res[i]40174c: 8fc2001c lw v0,28(s8) # 取得i401750: 00000000 nop401754: 00021080 sll v0,v0,0x2401758: 27c30018 addiu v1,s8,2440175c: 00621021 addu v0,v1,v0401760: 8c420024 lw v0,36(v0) # 取得res[i]401764: 00000000 nop401768: afc20020 sw v0,32(s8) # node = res[i]40176c: 8fc2001c lw v0,28(s8) # 末尾循环体起始,取得i401770: 00000000 nop401774: 24420001 addiu v0,v0,1 # i++401778: afc2001c sw v0,28(s8) # 存入内存中40177c: 8fc2001c lw v0,28(s8) # 条件判断起始401780: 00000000 nop401784: 28420006 slti v0,v0,6 # 判断i < 6,是则循环继续401788: 1440ffe7 bnez v0,401728 <phase_6+0x228>40178c: 00000000 nop401790: 8fc20020 lw v0,32(s8)401794: 00000000 nop401798: ac400008 sw zero,8(v0) # node->next = null40179c: 8fc2003c lw v0,60(s8)4017a0: 00000000 nop4017a4: afc20020 sw v0,32(s8) # node = firstnode4017a8: afc0001c sw zero,28(s8) # i = 04017ac: 10000032 b 401878 <phase_6+0x378>4017b0: 00000000 nop4017b4: 8f82806c lw v0,-32660(gp)4017b8: 00000000 nop4017bc: 8c42002c lw v0,44(v0)4017c0: 00000000 nop4017c4: 30420001 andi v0,v0,0x14017c8: 304200ff andi v0,v0,0xff4017cc: 10400012 beqz v0,401818 <phase_6+0x318> # if...else语句,判断奇偶4017d0: 00000000 nop4017d4: 8fc20020 lw v0,32(s8)4017d8: 00000000 nop4017dc: 8c430000 lw v1,0(v0)4017e0: 8fc20020 lw v0,32(s8)4017e4: 00000000 nop4017e8: 8c420008 lw v0,8(v0)4017ec: 00000000 nop4017f0: 8c420000 lw v0,0(v0)4017f4: 00000000 nop4017f8: 0062102a slt v0,v1,v0 # 比较重排后链表前后两个数的大小,升序则爆炸4017fc: 10400015 beqz v0,401854 <phase_6+0x354>401800: 00000000 nop401804: 0c10087c jal 4021f0 <explode_bomb>401808: 00000000 nop40180c: 8fdc0010 lw gp,16(s8)401810: 10000010 b 401854 <phase_6+0x354>401814: 00000000 nop401818: 8fc20020 lw v0,32(s8)40181c: 00000000 nop401820: 8c430000 lw v1,0(v0)401824: 8fc20020 lw v0,32(s8)401828: 00000000 nop40182c: 8c420008 lw v0,8(v0)401830: 00000000 nop401834: 8c420000 lw v0,0(v0)401838: 00000000 nop40183c: 0043102a slt v0,v0,v1 # 比较重排后链表前后两个数的大小,降序则爆炸401840: 10400004 beqz v0,401854 <phase_6+0x354>401844: 00000000 nop401848: 0c10087c jal 4021f0 <explode_bomb>40184c: 00000000 nop401850: 8fdc0010 lw gp,16(s8)401854: 8fc20020 lw v0,32(s8)401858: 00000000 nop40185c: 8c420008 lw v0,8(v0)401860: 00000000 nop401864: afc20020 sw v0,32(s8)401868: 8fc2001c lw v0,28(s8)40186c: 00000000 nop401870: 24420001 addiu v0,v0,1 # i++401874: afc2001c sw v0,28(s8)401878: 8fc2001c lw v0,28(s8)40187c: 00000000 nop401880: 28420005 slti v0,v0,5 # i < 5401884: 1440ffcb bnez v0,4017b4 <phase_6+0x2b4>401888: 00000000 nop40188c: 03c0e821 move sp,s8401890: 8fbf005c lw ra,92(sp)401894: 8fbe0058 lw s8,88(sp)401898: 27bd0060 addiu sp,sp,9640189c: 03e00008 jr ra4018a0: 00000000 nop
phase_secret
在炸弹四输入5 austinpowers即可进入隐藏炸弹。这个炸弹就是一个普通的二叉搜索树,输入数值x,执行find(x),返回得到根节点到值为x的节点的路径。炸弹要求返回值为7=111B,即根节点的右儿子节点的右儿子节点的右儿子节点,该节点值为1001。因此输入1001即可。
00402264 <phase_defused>:402264: 27bdff88 addiu sp,sp,-120402268: afbf0074 sw ra,116(sp)40226c: afbe0070 sw s8,112(sp)402270: 03a0f021 move s8,sp402274: 3c1c0042 lui gp,0x42402278: 279cb190 addiu gp,gp,-2008040227c: afbc0010 sw gp,16(sp)402280: 3c020041 lui v0,0x41402284: 8c433240 lw v1,12864(v0)402288: 24020006 li v0,640228c: 14620039 bne v1,v0,402374 <phase_defused+0x110>402290: 00000000 nop402294: 8f828058 lw v0,-32680(gp)402298: 00000000 nop40229c: 244400f0 addiu a0,v0,2404022a0: 3c020040 lui v0,0x404022a4: 244328a8 addiu v1,v0,10408 # "%d %s" !!!4022a8: 27c20068 addiu v0,s8,1044022ac: 00602821 move a1,v14022b0: 00403021 move a2,v04022b4: 27c20018 addiu v0,s8,244022b8: 00403821 move a3,v04022bc: 8f828084 lw v0,-32636(gp)4022c0: 00000000 nop4022c4: 0040c821 move t9,v04022c8: 0320f809 jalr t9 # 调用库中函数sscanf !!!4022cc: 00000000 nop4022d0: 8fdc0010 lw gp,16(s8)4022d4: 00401821 move v1,v04022d8: 24020002 li v0,2 # 判断sscanf读得的有效数据个数是否为24022dc: 1462001d bne v1,v0,402354 <phase_defused+0xf0>4022e0: 00000000 nop4022e4: 27c20018 addiu v0,s8,244022e8: 00402021 move a0,v0 # $a0中存储着输入的字符4022ec: 3c020040 lui v0,0x404022f0: 244528b0 addiu a1,v0,10416 # $a1中存储着"austinpowers"4022f4: 0c10073e jal 401cf8 <strings_not_equal> # 判断是否相等4022f8: 00000000 nop4022fc: 8fdc0010 lw gp,16(s8)402300: 14400014 bnez v0,402354 <phase_defused+0xf0>402304: 00000000 nop402308: 3c020040 lui v0,0x4040230c: 244428c0 addiu a0,v0,10432402310: 8f828038 lw v0,-32712(gp)402314: 00000000 nop402318: 0040c821 move t9,v040231c: 0320f809 jalr t9402320: 00000000 nop402324: 8fdc0010 lw gp,16(s8)402328: 3c020040 lui v0,0x4040232c: 244428e8 addiu a0,v0,10472402330: 8f828038 lw v0,-32712(gp)402334: 00000000 nop402338: 0040c821 move t9,v040233c: 0320f809 jalr t9402340: 00000000 nop402344: 8fdc0010 lw gp,16(s8)402348: 0c100664 jal 401990 <secret_phase> # 跳转至secret_phase40234c: 00000000 nop402350: 8fdc0010 lw gp,16(s8)402354: 3c020040 lui v0,0x40402358: 24442920 addiu a0,v0,1052840235c: 8f828038 lw v0,-32712(gp)402360: 00000000 nop402364: 0040c821 move t9,v0402368: 0320f809 jalr t940236c: 00000000 nop402370: 8fdc0010 lw gp,16(s8)402374: 03c0e821 move sp,s8402378: 8fbf0074 lw ra,116(sp)40237c: 8fbe0070 lw s8,112(sp)402380: 27bd0078 addiu sp,sp,120402384: 03e00008 jr ra402388: 00000000 nop40238c: 00000000 nop004018a4 <fun7>:4018a4: 27bdffe0 addiu sp,sp,-324018a8: afbf001c sw ra,28(sp)4018ac: afbe0018 sw s8,24(sp)4018b0: 03a0f021 move s8,sp4018b4: afc40020 sw a0,32(s8)4018b8: afc50024 sw a1,36(s8)4018bc: 8fc20020 lw v0,32(s8)4018c0: 00000000 nop4018c4: 14400004 bnez v0,4018d8 <fun7+0x34> # $v0($a0)不为0则继续,为0则函数结束4018c8: 00000000 nop4018cc: 2402ffff li v0,-1 # 设返回值为-1,即没有找到该值4018d0: 10000029 b 401978 <fun7+0xd4>4018d4: 00000000 nop4018d8: 8fc20020 lw v0,32(s8) # 取出$a0中的值4018dc: 00000000 nop4018e0: 8c430000 lw v1,0(v0) # $v1 = m[$a0]4018e4: 8fc20024 lw v0,36(s8) # $v0 = $a14018e8: 00000000 nop4018ec: 0043102a slt v0,v0,v1 # $v0 >= $v1时函数跳转4018f0: 1040000c beqz v0,401924 <fun7+0x80>4018f4: 00000000 nop4018f8: 8fc20020 lw v0,32(s8)4018fc: 00000000 nop401900: 8c420004 lw v0,4(v0) # 令fun7第一个参数为节点的左儿子的地址401904: 00000000 nop401908: 00402021 move a0,v040190c: 8fc50024 lw a1,36(s8) #第二个参数不变401910: 0c100629 jal 4018a4 <fun7>401914: 00000000 nop401918: 00021040 sll v0,v0,0x1 # $v0左移一位40191c: 10000016 b 401978 <fun7+0xd4>401920: 00000000 nop401924: 8fc20020 lw v0,32(s8)401928: 00000000 nop40192c: 8c430000 lw v1,0(v0)401930: 8fc20024 lw v0,36(s8)401934: 00000000 nop401938: 0062102a slt v0,v1,v0 # $v1 >= $v0时函数跳转,即$v0 == $v1时找到节点,函数返回040193c: 1040000d beqz v0,401974 <fun7+0xd0>401940: 00000000 nop401944: 8fc20020 lw v0,32(s8)401948: 00000000 nop40194c: 8c420008 lw v0,8(v0) # 令fun7第一个参数为节点的右儿子的地址401950: 00000000 nop401954: 00402021 move a0,v0401958: 8fc50024 lw a1,36(s8) # 第二个参数不变40195c: 0c100629 jal 4018a4 <fun7>401960: 00000000 nop401964: 00021040 sll v0,v0,0x1 # $v0左移一位401968: 24420001 addiu v0,v0,1 # $v0末位补140196c: 10000002 b 401978 <fun7+0xd4>401970: 00000000 nop401974: 00001021 move v0,zero401978: 03c0e821 move sp,s840197c: 8fbf001c lw ra,28(sp)401980: 8fbe0018 lw s8,24(sp)401984: 27bd0020 addiu sp,sp,32401988: 03e00008 jr ra40198c: 00000000 nop00401990 <secret_phase>:401990: 27bdffd8 addiu sp,sp,-40401994: afbf0024 sw ra,36(sp)401998: afbe0020 sw s8,32(sp)40199c: 03a0f021 move s8,sp4019a0: 3c1c0042 lui gp,0x424019a4: 279cb190 addiu gp,gp,-200804019a8: afbc0010 sw gp,16(sp)4019ac: 0c1007fb jal 401fec <read_line> # 输入4019b0: 00000000 nop4019b4: 8fdc0010 lw gp,16(s8)4019b8: afc2001c sw v0,28(s8)4019bc: 8fc2001c lw v0,28(s8)4019c0: 00000000 nop4019c4: 00402021 move a0,v04019c8: 00002821 move a1,zero4019cc: 2406000a li a2,104019d0: 8f828070 lw v0,-32656(gp)4019d4: 00000000 nop4019d8: 0040c821 move t9,v04019dc: 0320f809 jalr t94019e0: 00000000 nop4019e4: 8fdc0010 lw gp,16(s8)4019e8: afc20018 sw v0,24(s8)4019ec: 8fc20018 lw v0,24(s8)4019f0: 00000000 nop4019f4: 2442ffff addiu v0,v0,-1 # $v0--4019f8: 2c4203e9 sltiu v0,v0,1001 # 判断[输入的值-1]($v0)是否小于1001,是则继续,否则引爆4019fc: 14400004 bnez v0,401a10 <secret_phase+0x80>401a00: 00000000 nop401a04: 0c10087c jal 4021f0 <explode_bomb>401a08: 00000000 nop401a0c: 8fdc0010 lw gp,16(s8)401a10: 3c020041 lui v0,0x41401a14: 24443184 addiu a0,v0,12676 # fun7的第一个参数0x413814 m[0x413814] = 0x24 = 36401a18: 8fc50018 lw a1,24(s8) # fun7的第二个参数,即输入的数401a1c: 0c100629 jal 4018a4 <fun7> # 进入fun7401a20: 00000000 nop401a24: 8fdc0010 lw gp,16(s8)401a28: 00401821 move v1,v0401a2c: 24020007 li v0,7401a30: 10620004 beq v1,v0,401a44 <secret_phase+0xb4> # fun7返回值为7 = 111B时才不会引爆401a34: 00000000 nop401a38: 0c10087c jal 4021f0 <explode_bomb>401a3c: 00000000 nop401a40: 8fdc0010 lw gp,16(s8)401a44: 3c020040 lui v0,0x40401a48: 244427b8 addiu a0,v0,10168401a4c: 8f828038 lw v0,-32712(gp)401a50: 00000000 nop401a54: 0040c821 move t9,v0401a58: 0320f809 jalr t9401a5c: 00000000 nop401a60: 8fdc0010 lw gp,16(s8)401a64: 0c100899 jal 402264 <phase_defused>401a68: 00000000 nop401a6c: 8fdc0010 lw gp,16(s8)401a70: 03c0e821 move sp,s8401a74: 8fbf0024 lw ra,36(sp)401a78: 8fbe0020 lw s8,32(sp)401a7c: 27bd0028 addiu sp,sp,40401a80: 03e00008 jr ra401a84: 00000000 nop
总结
每个阶段对应的C++代码
只给出关键部分。简洁明了,一看就懂,理解炸弹大概流程用。
//输入ID
int ID;
cin>>ID;
phase_1
//input
string str;
cin>>str;//phase_1
string ans = "Let's begin now!";
if (str == ans) return ;
else explode_bomb();
phase_2
//input
int a[6];
for (int i = 0;i < 6;i++)cin>>a[i];//phase_2
if (a[0] != 1) explode_bomb();
for (int i = 0;i < 6;i++)if (a[i] * ((ID >> i) & 1) != a[i + 1])explode_bomb();
phase_3
//input
int a[2];
char c
cin>>a[0]>>c>>a[1];
//phase_3
char c0;
int b;
switch(a[0]) {case 0:c0 = 'q';b = 777;if ((ID & 1) * a[1] != b) explode_bomb();break;case 1:c0 = 'b';b = 214;if ((ID & 1) * a[1] != b) explode_bomb();break;case 2:c0 = 'b';b = 755;if ((ID & 1) * a[1] != b) explode_bomb();break;case 3:c0 = 'k';if ((ID & 1) * a[1] != 0) explode_bomb();break;case 4:c0 = 'o';b = 228;if ((ID & 1) * a[1] != b) explode_bomb();break;case 5:c0 = 't';b = 513;if ((ID & 1) * a[1] != b) explode_bomb();break;case 6:c0 = 'v';b = 780;if ((ID & 1) * a[1] != b) explode_bomb();break;case 7:c0 = 'b';b = 824;if ((ID & 1) * a[1] != b) explode_bomb();break;default: explode_bomb();
}
if (c != c0) explode_bomb();
phase_4
//input
int x;
cin>>x;
//fun4
int fun4(int x) {if (x < 2) return 1;return f(x - 1) + f(x - 2);
}
//phase_4
if (ID & 1) {if (fun4(x) != 8) explode_bomb();
}
else {if (fun4(x) != 13) explode_bomb();
}
phase_5
//input
char str[6];
cin>>str;
//phase_5
char res[6];
char S[16] = "isrveawhobpnutfg";
char ans[6] = "giants";
for (int i = 0;i < 6;i++) {int pos = str[i] & 15;//15D = FH = 1111Bres[i] = S[pos];
}
for (int i = 0;i < 6;i++)if (res[i] != ans[i])explode_bomb();
phase_6
//input
int a[6];
for (int i = 0;i < 6;i++)cin>>a[i];
//phase_6
for (int i = 0;i < 6;i++) {if (!(i > 0 && i < 7) explode_bomb();for (int j = i + 1;j < 6;j++)if (a[i] == a[j]) explode_bomb();
}
chain c = {0x0fd, 0x2d5, 0x12d, 0x3e5, 0x0d4, 0x1b0};
chainNode res[6];
for (int i = 0;i < 6;i++) {chainNode *node = c.firstNode;for (int j = 1;j < a[i];j++)node = node->next;res[i] = node;
}
chainNode *node = c.firstNode;
for (int i = 1;i < 6;i++) {node->next = res[i];node = res[i];
}
node->next = null;
if (ID & 1) {node = c.firstNode;for (int i = 1;i < 6;i++)if (node->element < node->next->element)explode_bomb();
}
else {node = c.firstNode;for (int i = 1;i < 6;i++)if (node->element > node->next->element)explode_bomb();
}
MIPS反汇编拆炸弹相关推荐
- MIPS - 反汇编 - 拆炸弹 - bomb
MIPS - 反汇编 - 拆炸弹 - bomb 前言 整理文档发现了之前的实验报告,鉴于从17级开始才开始使用MIPS实验环境,取实验报告精华,整理主要思路如下.该博客叙述风格参考了窦优秀学长的博客. ...
- 汇编 二进制拆炸弹 r -t 3 -x 124
文章目录 注 实验环境: 实验内容 实验步骤 调试过程及实验 总结 附录 注 QUT大二汇编最后一个作业:拆炸弹 通过两天中间隙来做这个实验,不能交个实验报告就完事了,毕竟是第一次接触逆向工程,老师为 ...
- CSAPP_实验二 拆炸弹 汇编知识应用
CSAPP--实验二 拆炸弹 Phase1 disas phase_1, 反汇编 phase_1 函数 在 phase_1函数入口处 设置断点 break phase_1 run 开始运行,输入字符串 ...
- CSAPP 拆炸弹 中科大实验
实验二 拆炸弹 准备工作 首先反汇编 objdump -s -d bomb > bomb.txt phase_1 开启gdb调试,并打断点到phase_1 >> gbd bomb ( ...
- 【LeetCode】1652. 拆炸弹(C++)
1652. 拆炸弹(C++) 1 题目描述 2 示例描述 2.1 示例1 2.2 示例2 2.3 示例3 3 解题提示 4 解题思路 5 源码详解(C++) 1 题目描述 你有一个炸弹需要拆除,时间紧 ...
- 计算机系统实验拆炸弹,CSAPP 炸弹实验解析上
CSAPP(Computer Systems A Programmer's Perspective),中译名为深入理解计算机系统,是一本优秀的计算机教材.该书配套了若干个课后实验,可供读者检验所学知识 ...
- bomblab 拆炸弹
#南京航空航天大学<计算机组成原理Ⅱ课程设计>报告 姓名:xx 班级:1617 学号:1617 报告阶段:Bomblab 完成日期:2019.5.26 ##目录 文章目录 实验内容 1.B ...
- LeetCode简单题之拆炸弹
题目 你有一个炸弹需要拆除,时间紧迫!你的情报员会给你一个长度为 n 的 循环 数组 code 以及一个密钥 k . 为了获得正确的密码,你需要替换掉每一个数字.所有数字会 同时 被替换. 如果 k ...
- LeetCode 1652. 拆炸弹(前缀和)
文章目录 1. 题目 2. 解题 1. 题目 你有一个炸弹需要拆除,时间紧迫!你的情报员会给你一个长度为 n 的 循环 数组 code 以及一个密钥 k . 为了获得正确的密码,你需要替换掉每一个数字 ...
最新文章
- 安装openssl-devel
- mysql ormlite_Loogn.OrmLite
- 广义的B端产品人,都是什么职位?
- 删除个别主机的Know_hosts文件信息
- oracle的asmcmd获取归档日志,分析oracle的联机日志和归档日志
- Android studio编译出现Failed to finalize session : INSTALL_FAILED_INVALID_APK
- MySQL 配置错误
- 正则表达式捕获分组和非捕获分组及用法
- 使用Python编写简单网络爬虫抓取视频下载资源
- arailsdemo 1
- 瞬时电压示波器matlab,示波器测量瞬时电压的方法与步骤
- 当p.1引脚的电平正跳变c语言程序,数字电路笔试题目1
- Python+Pid实现车辆速度跟踪
- python中element什么意思_什么是Python中等效的’nth_element’函数?
- 文本挖掘基本流程概述 分词和TF-IDF值计算方法介绍
- 笔记本插入耳机依然外放,但开机前插上耳机可以使用耳机 (解决了我多年的问题)
- 深入理解HashMap
- mysql safe file priv_解决MySQL导入数据时遇到secure-file-priv的问题
- 解决webpack打包报错: Cannot find module '@webassemblyjs/wasm-parser'
- 【函数参数传递】编写一个函数,统计字符串中小写字母的个数,并把字符串中的小写字母转化成大写字母。
热门文章
- 西门子博图HMI与倍福进行PLC使用OPC DA服务器进行通讯配置
- 同轴电缆抗干扰措施(二)
- 中止执行后超过2年_执行中止后恢复执行的期限有什么规定
- 插入u盘计算机未响应,U盘插入win7电脑没反应如何解决 Win7插入U盘没反应怎么办...
- 规则在自然语言处理领域的重要地位
- python 桑基图_3行代码基于python的matplotlib绘制桑基图
- 推荐模型-上下文感知-2017:AFM模型【FM家族】【NFM的改进版】【引入Attention机制】
- 软件测试测试用例—用户注册界面
- mapbox-gl开发:deck.gl轨迹图效果
- 【环境搭建】Ubuntu18.04 nvidia显卡 OpenCL环境搭建