上文说了汇编语言的基本要素和一些体系结构的东西。现在就付诸实践,来反编译试试。我用的是从一个公开课The Hardware/Software Interface上的lab,我上传了github。有兴趣的可以自己尝试。我花了大概5个小时才完全破解。而且还有一个过程没有弄明白,看到结果才明白过程是什么。。
GDB基础:
具体的可以看链接1。我基本就用到了下面的选项。i r和x是特别有用的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | gcc -g switch.c -o switch # 启用gdb,就可以在debug时查看源代码 disas # 反汇编目前代码 list # 查看源代码 step s si n c #下一步 help help status help info #帮助信息 break *0x40000123 break fun_1 #设置断点 i r #寄存器信息 x /10xw $rsp x /10d 0x400012 x /s $esi #按要求输出 |
objdump:
首先还是先把所有代码反汇编了再说,否则根本不知道框架。 objdump -d bomb > bomb.s 搞定。这下可以看出一共7个阶段,包括一个secret阶段。然后试着用 strings bomb ,说不定有惊喜。这样心里就更有数了,因为出来有一部分是这样的结果:
That’s number 2. Keep going!
Halfway there!
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
Phase 1 defused. How about the next one?
So you got that one. Try this one.
Congratulations! You’ve (mostly) defused the bomb!
Hit Control-C to escape phase 6 (for free!), but if you want to
try phase 6 for extra credit, you can continue. Just beware!
Science isn’t about why, it’s about why not?
Wow! You’ve defused the secret stage!
So you think you can stop the bomb with ctrl-c, do you?
nonexistenthost.cs.washington.edu
Curses, you’ve found the secret phase!
But finding it and solving it are quite different…
Congratulations! You’ve defused the bomb! Again!
正式破解:
阶段一:
这一步很简单,以下4个命令就能破解。你懂的,$esi就是参数。
1 2 3 4 | break phase_1 disas si x /s $esi |
阶段二:
从objdump的bomb.s可以看出,这次要输入6个数字。通过下面3步可以知道我输入的数字存储的位置。我刚开始当然不知道答案是哪几个数字,所以随便放几个。
1 2 3 4 5 | break phase_2 disas ni 7 i r x /20d 0x7fffffffdf40 |
从这里就可以看出这是要测试第零个数字和第三个是否一样,同理看看其他是什么关系。
1 2 3 4 5 6 7 8 | => 0x0000000000400eac <+32>: mov %rsp,%rbp 0x0000000000400eaf <+35>: lea 0xc(%rsp),%r13 0x0000000000400eb4 <+40>: mov $0x0,%r12d 0x0000000000400eba <+46>: mov %rbp,%rbx 0x0000000000400ebd <+49>: mov 0xc(%rbp),%eax 0x0000000000400ec0 <+52>: cmp %eax,0x0(%rbp) 0x0000000000400ec3 <+55>: je 0x400eca <phase_2+62> 0x0000000000400ec5 <+57>: callq 0x40163d <explode_bomb> |
阶段三:
这个好多mov, jmp。看到就吓尿了。关键点是
400f2b: ff 24 c5 60 1b 40 00 jmpq *0x401b60(,%rax,8) ,我刚开始不明白其意义,是根据答案得到结果的。后来经查找,发现这是switch,用
x /20xw 0x401b60 就可以检查。然后迎刃而解。
阶段四:
不说了,是个fibonacci数列。我觉得是第二简单的一个。
阶段五:
首先这里有个数组,如下: 然后程序的目的是经过12次指针切换后,最后指到值为15的array[i]。可知上一次i = 6。依次类推。然后他也是输入两个数字,一个是起点,一个是总和。可以看出每次迭代都是把值相加,跟输入值相比。
1 2 3 4 5 | x /16d 0x401ba0 0x401ba0 <array.3014>: 10 2 14 7 0x401bb0 <array.3014+16>: 8 12 15 11 0x401bc0 <array.3014+32>: 0 4 1 13 0x401bd0 <array.3014+48>: 3 9 6 5 |
阶段六:
那个fun6完全没有看懂,但是可以进行下去。按下面的步骤,得出的结果,一定能发现什么。然后就简单了。
1 2 3 4 5 6 | b *0x4010f2 b *0x4010fc r < solution.txt x /20x 0x602780 c x /20x 0x602780 |
Secret Phase:
在这里我搞了近两个小时。首先是找不到入口。phase_defused中明白的写着是从这进,而且要输入两个参数。而且第二个字符串是austinpowers。但是半天没有搞定。最后发现居然不是在最后输入。。。在哪输入自己找。顺利进入secret phase。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 401789: 83 3d f0 14 20 00 06 cmpl $0x6,0x2014f0(%rip) # 602c80 <num_input_strings> 401790: 75 5e jne 4017f0 <phase_defused+0x6b> 401792: 48 8d 4c 24 10 lea 0x10(%rsp),%rcx 401797: 48 8d 54 24 0c lea 0xc(%rsp),%rdx 40179c: be c4 1e 40 00 mov $0x401ec4,%esi 4017a1: bf 30 30 60 00 mov $0x603030,%edi 4017a6: b8 00 00 00 00 mov $0x0,%eax 4017ab: e8 00 f3 ff ff callq 400ab0 <__isoc99_sscanf@plt> 4017b0: 83 f8 02 cmp $0x2,%eax 4017b3: 75 31 jne 4017e6 <phase_defused+0x61> 4017b5: be ca 1e 40 00 mov $0x401eca,%esi 4017ba: 48 8d 7c 24 10 lea 0x10(%rsp),%rdi 4017bf: e8 79 fa ff ff callq 40123d <strings_not_equal> 4017c4: 85 c0 test %eax,%eax 4017c6: 75 1e jne 4017e6 <phase_defused+0x61> 4017c8: bf 40 1c 40 00 mov $0x401c40,%edi 4017cd: e8 ce f2 ff ff callq 400aa0 <puts@plt> 4017d2: bf 68 1c 40 00 mov $0x401c68,%edi 4017d7: e8 c4 f2 ff ff callq 400aa0 <puts@plt> 4017dc: b8 00 00 00 00 mov $0x0,%eax 4017e1: e8 74 f9 ff ff callq 40115a <secret_phase> |
进入secret phase后,查看相关数据。发现也是链表类型的。然后进入fun7。这是个递归的函数。不用笔不行啊,然后我就手动写了递归函数。坑的是我把cmp搞反了,郁闷了半天。 c代码都写出来了就简单了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | (gdb) x /50xw 0x6025a0 0x6025a0 <n1>: 0x00000024 0x00000000 0x006025c0 0x00000000 0x6025b0 <n1+16>: 0x006025e0 0x00000000 0x00000000 0x00000000 0x6025c0 <n21>: 0x00000008 0x00000000 0x00602640 0x00000000 0x6025d0 <n21+16>: 0x00602600 0x00000000 0x00000000 0x00000000 0x6025e0 <n22>: 0x00000032 0x00000000 0x00602620 0x00000000 0x6025f0 <n22+16>: 0x00602660 0x00000000 0x00000000 0x00000000 0x602600 <n32>: 0x00000016 0x00000000 0x00602720 0x00000000 0x602610 <n32+16>: 0x006026e0 0x00000000 0x00000000 0x00000000 0x602620 <n33>: 0x0000002d 0x00000000 0x00602680 0x00000000 0x602630 <n33+16>: 0x00602740 0x00000000 0x00000000 0x00000000 0x602640 <n31>: 0x00000006 0x00000000 0x006026a0 0x00000000 0x602650 <n31+16>: 0x00602700 0x00000000 0x00000000 0x00000000 0x602660 <n34>: 0x0000006b 0x00000000 |
链接: