上一篇【为拆炸弹实验做的预习与准备】讲述了一些必须的知识
这个实验是给出可执行文件,要求用gdb反编译出汇编代码,一共有6个关卡,要求玩家输入6个输入,要通过分析汇编代码来找到何种输入不会触发炸弹,然后输入正确的输入信息以拆解炸弹
第一关 字符串比对
汇编原码及个人注释
0000000000400e70 <phase_1>:
400e70: 48 83 ec 08 sub $0x8,%rsp // 开栈
400e74: be f8 1a 40 00 mov $0x401af8,%esi // 函数的第二个参数是$0x401af8,猜测是常量字符串
400e79: e8 bf 03 00 00 callq 40123d <strings_not_equal>
400e7e: 85 c0 test %eax,%eax // 返回值等于0,即两个字符串相等,则结束否则bomb
400e80: 74 05 je 400e87 <phase_1+0x17>
400e82: e8 b6 07 00 00 callq 40163d <explode_bomb>
400e87: 48 83 c4 08 add $0x8,%rsp // 退栈
400e8b: c3
前三句是压栈,调用一个strings_not_equal
函数,根据英文阅读理解,判断这个函数是输入和一常量字符串比较判断是否相同,如果不同则返回true(1),如果相同则返回false(0)
然后根据返回值,用je进行跳转,如果eax即函数返回值为0则跳转成功,不会触发<explode_bomb>,然后关注到它将0x401af8赋值给esi,函数string_not_equal
的第二个参数,而第一个参数仍然是phase1调用的第一个参数,应该是输入值,所以我猜测这第二个参数是一个常量字符串的地址,于是gdb试一下,gdb查看对应内存地址的字符串
发现这个常量字符串是Science isn’t about why, it’s about why not? 结合上面的分析不难看出,输入串必须与其相等,方可通关!
答案:
Science isn't about why, it's about why not?
第二关:数组与循环
汇编源码及个人注释
0000000000400e8c <phase_2>:
400e8c: 48 89 5c 24 e0 mov %rbx,-0x20(%rsp) // 保存父函数数据,压栈
400e91: 48 89 6c 24 e8 mov %rbp,-0x18(%rsp)
400e96: 4c 89 64 24 f0 mov %r12,-0x10(%rsp)
400e9b: 4c 89 6c 24 f8 mov %r13,-0x8(%rsp)
400ea0: 48 83 ec 48 sub $0x48,%rsp // 开栈
400ea4: 48 89 e6 mov %rsp,%rsi // 栈顶指针给到第二个参数
400ea7: e8 97 08 00 00 callq 401743 <read_six_numbers> // 调用函数读数据
400eac: 48 89 e5 mov %rsp,%rbp // 保存栈指针到rbp
400eaf: 4c 8d 6c 24 0c lea 0xc(%rsp),%r13 // 栈指针+12保存到r13
400eb4: 41 bc 00 00 00 00 mov $0x0,%r12d // r12低32位清零
// ----------------------------------------------------- 循环 -------------------------------------------- //
400eba: 48 89 eb mov %rbp,%rbx // rbp的值保存到rbx,【下文跳转到这】
400ebd: 8b 45 0c mov 0xc(%rbp),%eax // M[rbp+12]保存到eax
400ec0: 39 45 00 cmp %eax,0x0(%rbp) // 看 M[rbp] 和 M[rbp+12] 是否相等
400ec3: 74 05 je 400eca <phase_2+0x3e> // 如果M[rbp]和M[rbp+12]不等则bomb
400ec5: e8 73 07 00 00 callq 40163d <explode_bomb>
400eca: 44 03 23 add (%rbx),%r12d // r12 += M[rbx]
400ecd: 48 83 c5 04 add $0x4,%rbp // rbp += 4,rbp为迭代指针
400ed1: 4c 39 ed cmp %r13,%rbp // r13和rbp如果不等则跳转
400ed4: 75 e4 jne 400eba <phase_2+0x2e>
// ---------------------------------------------------- 循环结束 ------------------------------------------ //
400ed6: 45 85 e4 test %r12d,%r12d // r12d是累加值,累加值为0则bomb
400ed9: 75 05 jne 400ee0 <phase_2+0x54>
400edb: e8 5d 07 00 00 callq 40163d <explode_bomb>
400ee0: 48 8b 5c 24 28 mov 0x28(%rsp),%rbx // 退栈
400ee5: 48 8b 6c 24 30 mov 0x30(%rsp),%rbp
400eea: 4c 8b 64 24 38 mov 0x38(%rsp),%r12
400eef: 4c 8b 6c 24 40 mov 0x40(%rsp),%r13
400ef4: 48 83 c4 48 add $0x48,%rsp
400ef8: c3 retq
可以清晰的看到,一开始先读取6个数(英文阅读理解可知),然后使用rbp作为迭代指针,rbp+12为迭代终点,一共迭代三次,而每次我们都将M[rbp] 和 M[rbp+12] 处的数据比对,如果不等则bomb,而且一个int刚好是4字节,三个就是12!结合刚刚的读取6个数字,可以大胆的猜测,这是在判断 a[i] 和 a[i+3] 是否相等!
r12之前清零,但是每次又 += M[rbx],猜测 是在计算累加和,根据后文的test $r12d $r12d,可以知道,如果三个数累加起来是0,即使a[i] = a[i+3] 也会炸,所以可以拆弹了!
因为1145141919810是好数字,不妨输入 114 514 1919810 114 514 1919810,可以满足条件!
答案:
114 514 1919810 114 514 1919810
a b c a b c 且 (a+b+c)!=0 即可
第三关switch
汇编源码及个人注释