首先用IDA反编译bomb,可以大致了解整个程序的结构:
我们进入phase_1函数,发现很简单,就是和给定字符串进行比较:
所以 phase_1 的答案为:Public speaking is very easy.
对phase_2函数进行简要分析:
所以 phase_2 答案为:1 2 6 24 120 720
本关是利用输入的3个数进入switch分支语句进行相应判断。有不同的答案我们从中随意选取一个进行分析:
所以 phase_3 答案为:0 q 777
首先分析一下phase_4:
再分析一下func4函数:
我们直接把递归函数和调用函数复制下来,用0-127可显示字符的ASCII码来遍历:
代码如下:
#include<stdio.h> int __cdecl func4(signed int a1) { int v1; // esi if (a1 <= 1) return 1; v1 = func4(a1 - 1); return v1 + func4(a1 - 2); } int main() { int result; // eax int v2; // [esp+14h] [ebp-4h] for (int i = 0; i < 127; i++) { v2 = i; result = func4(v2); if (result == 55) { printf("%d\n", v2); return 0; } } return result; }运行结果如下:
所以 phase_4 答案为:9
分析一下函数phase_5:
可以看出,输入字符串的长度必须为6。且以这六个字符的ASCII码的低四位为下标,在数组array_123所对应的字符是"giants"这六个字符。编写代码破解:
代码如下:
#include<iostream> #include <string> using namespace std; int main() { string s = "giants"; int a[100] = { 0x69, 0x73, 0x72, 0x76, 0x65, 0x61, 0x77, 0x68, 0x6F, 0x62, 0x70,0x6E, 0x75, 0x74, 0x66, 0x67 }; char ch; int i, j; int ans[6]; for (i = 0; i < 6; i++) { for (j = 0; j < 16; j++) { ch = a[j]; if (ch == s[i]) { ans[i] = j; break; } } } char temp[26] = { 'q','w','e','r','t','y','u','i','o','p','a','s','d','f','g','h','j','k','l','z','x','c','v','b','n','m' }; for (i = 0; i < 6; i++) { for (j = 0; j < 26; j++) { if ((temp[j] & 0xF) == ans[i]) { cout << temp[j]; break; } } } return 1; }运行结果如下:
所以 phase_5 答案为:opekmq
最后一关比较难,难以看懂其间的寻址关系。但是通过看nodel 就得到了启发,猜测可能是链,并且通过尾部的指针进行链接。想通这个关键点,认真分析不难得出一下结论:
观察现有的node链接情况:
可以看出当前它们就是顺序链接的,而我们希望它们降序链接。于是我们可以整理出如下表格:
节点
Node1
Node2
Node3
Node4
Node5
Node6
数值
0x0FD
0x2D5
0x12D
0x3E5
0x0D4
0x1B0
当前链接序号
1
2
3
4
5
6
期望链接序号
4
2
6
3
1
5