本实验是解除二进制炸弹。给你一个二进制可执行文件,运行该文件,你需要在没有任何提示的情况下输入6个password,如果都输入正确,则炸弹被解除(完成了实验);如果输入错误,则炸弹爆炸(当然不是真爆炸了,需要重做)。

第一关

x /s $rsi 即可看到比较函数的字符串参数

第二关

输入6个数字,仔细阅读汇编代码,即可发现是比较后三个和前三个是否相等

第三关

查看sscanf参数 x /s $rsi “%d %d”,输入两个整数

观察cmpl $0x7 0xc(%rsp),并且由于sscanf的参数是从后向前压栈,输入两个整数存在 0x8(%rsp), 0xc(%rsp) 两个位置,并且第一个数要不大于7

下面就是根据第一个输入 switch

一共8组,输入任何一组都可以

(0, 535), (1, 926), (2, 214), (3, 339), (4, 119), (5, 352), (6, 919), (7, 412)

第四关

查看sscanf参数 x /s $rsi “%d”,输入一个整数,要大于 0 ,接着调用 func4,返回结果必须是 0x37

下面就是分析func4,这是一个递归函数,就是著名的 Fibnacci 数列

Fib(n) = Fib(n-1) + Fib(n-2)

第五关

输入两个整数 x, y

第一个数 %eax = x AND 0xF != 0xF,即第一个数二进制低4位不能全为 1

mov 0x401ba0(,%rax,4),%eax

0x401ba0 是数组起始地址,该数组一共有16个数 (gdb)p *0x401ba0@16

{10, 2, 14, 7, 8, 12, 15, 11, 0, 4, 1, 13, 3, 9, 6, 5}

phase_5 还原成 C 语言大致如下。要求最终 count = 0xC,r 等于输入的第二个数 y

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
int a[] = {10, 2, 14, 7, 8, 12, 15, 11, 0, 4, 1, 13, 3, 9, 6, 5};

void phase_5()
{
	int x = ???;  /* 0 ~ 14 */
	int r = 0;
	int count = 0;

	do {
		x = a[x];
		r += x;
		++count;
	} while(x != 15);

	assert(count == 12);

	printf("%d\n", r);
}

第六关

链表