BinaryBombs(二进制炸弹实验)

实验介绍

  • 使用所学知识拆除Binary Bombs来增强对程序的机器级表示、汇编语言、调试器和逆向工程等理解。
  • Binary Bombs(二进制炸弹)是一个可执行程序,是C语言编译链接成的,包含phase1~phase6共6个阶段(还有隐藏阶段)。
  • 各阶段要求输入一个答案,若正确,该阶段炸弹被拆除,否则爆炸
  • 你需要拆除尽可能多的炸弹
  • 实验提供一个bomb.cbomb可执行文件,但是,bomb.c中只有主函数,和一些彩蛋。
  • bomb有一个命令行参数,为读入的文件。所以你可以将答案写入到一个txt文件,每个答案一行。

实验技巧

gdb调试

  • (gdb)info reg查看所有寄存器的信息
  • (gdb)info frame查看栈的信息
  • (gdb)b * 0x4050400x405040处设置断点
  • (gdb)b phase_1在函数phase_1处设置断点
  • (gdb)x/2s 0x405010输出0x405010开始的两个字符串
  • (gdb)stepi执行一条指令
  • (gdb)nexti类似于stepi,但以函数调用为单位
  • (gdb)c继续(遇到断点后)
  • (gdb)run ans.txt命令行参数运行
  • (gdb)q退出
  • (gdb)finish运行到当前函数返回
  • (gdb)delete删除所有断点
  • (gdb)delete 5删除断点 5
  • (gdb)layout asm展示当前的汇编语言(非常的好用,ctrl + L 刷新)
  • (gdb)p *(int *) 0x405012输出位于地址0x405012的整数
  • (gdb)p $rax输出%rax的值
  • (gdb)p /x $rax以十六进制输出%rax的值
  • (gdb)p *(int *)($rbp + 0x8)输出地址%rbp + 0x8的整数
  • (gdb)disas phase_1反汇编phase_1函数

我的实验经验

  • 先反汇编objdump -d bomb > asm.txt。然后把asm.txt的内容复制粘贴到word。用word来看汇编语言,方便涂色标注
  • 一边分析汇编语言,一边利用gdb调试。
  • 先熟读CSAPP第三章,最好把习题做完

phase_1

密码如下:I am not part of the problem. I am a Republican.

破解过程:

  1. phase_1函数处设置断点。

  2. 随便输出一个答案,如 abcdef

  3. 观察断点信息,input_strings可知,答案确实是一个字符串。

  4. 反汇编观察到 strings_not_equal,推测是在判断字符串是否相等。然后,test命令测试返回值,如果非0,则爆炸。

  5. 0为真,1为假,那么非0对于strings_not_equal,应该是字符串不等,所以现在要找到那个与输出的字符串匹配的字符串。

  6. 观察到,传递给寄存器%esi的值0x403150

  7. 打印此处的字符串: x/2s 0x403150

  8. 得到答案

汇编代码:

点击查看代码
00000000004013f9 <phase_1>:
 4013f9:	55 	push %rbp
 4013fa:	48 89 e5 	mov %rsp,%rbp
 4013fd:	be 50 31 40 00 	mov $0x403150,%esi
 401402:	e8 3d 04 00 00 	callq 401844 <strings_not_equal>
 401407:	85 c0 	test %eax,%eax
 401409:	75 02 	jne 40140d <phase_1+0x14>
 40140b:	5d 	pop %rbp
 40140c:	c3 	retq 
 40140d:	e8 2e 05 00 00 	callq 401940 <explode_bomb>
 401412:	eb f7 	jmp 40140b <phase_1+0x12>****

phase_2

密码如下:0 1 3 6 10 15

破解过程:

  1. phase_2设置断点。

  2. 运行,参数为ans.txt,其中写有刚刚得到的第一个的答案。

  3. 先随便输入,这里输入一个数 5

  4. 反汇编观察,一开始调用了<read_six_numbers>函数,那么可以先把输入改为6个数

  5. 继续观察下面的汇编语言,发现 -30(%rbp)不就是存放第一个数的位置吗?这里判断第一个数必须为0,否则炸弹爆炸

  6. 在后面,%ebx先赋值为1,然后判断是否大于5,是一个循环,然后根据输入的6个数,每轮打印发现规律。

  7. 得出代码:for(int i = 1; i <= 5; i ++) a[i] = a[i - 1] + i;

  8. 则得出答案。

汇编代码:

点击查看代码
0000000000401414 <phase_2>:
 401414:	55 	push %rbp
 401415:	48 89 e5 	mov %rsp,%rbp
 401418:	53 	push %rbx
 401419:	48 83 ec 28 	sub $0x28,%rsp
 40141d:	48 8d 75 d0 	lea -0x30(%rbp),%rsi
 401421:	e8 3c 05 00 00 	callq 401962 <read_six_numbers>
 401426:	83 7d d0 00 	cmpl $0x0,-0x30(%rbp)
 40142a:	78 07 	js 401433 <phase_2+0x1f>
 40142c:	bb 01 00 00 00 	mov $0x1,%ebx
 401431:	eb 0f 	jmp 401442 <phase_2+0x2e>
 401433:	e8 08 05 00 00 	callq 401940 <explode_bomb>
 401438:	eb f2 	jmp 40142c <phase_2+0x18>
 40143a:	e8 01 05 00 00 	callq 401940 <explode_bomb>
 40143f:	83 c3 01 	add $0x1,%ebx
 401442:	83 fb 05 	cmp $0x5,%ebx
 401445:	7f 17 	jg 40145e <phase_2+0x4a>
 401447:	48 63 c3 	movslq %ebx,%rax
 40144a:	8d 53 ff 	lea -0x1(%rbx),%edx
 40144d:	48 63 d2 	movslq %edx,%rdx
 401450:	89 d9 	mov %ebx,%ecx
 401452:	03 4c 95 d0 	add -0x30(%rbp,%rdx,4),%ecx
 401456:	39 4c 85 d0 	cmp %ecx,-0x30(%rbp,%rax,4)
 40145a:	74 e3 	je 40143f <phase_2+0x2b>
 40145c:	eb dc 	jmp 40143a <phase_2+0x26>
 40145e:	48 83 c4 28 	add $0x28,%rsp
 401462:	5b 	pop %rbx
 401463:	5d 	pop %rbp
 401464:	c3 	retq 

phase_3

密码如下:1 -1199

破解过程:

  1. 设置断点,运行,反汇编。

  2. 发现线索: 401475:be 1f 33 40 00 mov $0x40331f,%esi

  3. 打印0x40331f处的字符串,得到:

  4. 结合后边的40147f:e88cfcff ff callq 401110 <__isoc99_sscanf@plt>可知,本题答案为两个整型变量

401489: 8b 45 fc mov -0x4(%rbp),%eax
40148c: 83 f8 07 cmp $0x7,%eax 
40148f: 77 7b ja 40150c <phase_3+0xa7> 

第一个输入的数不能大于7
结合后面的可猜测,是一个根据第一个输入的数的switch语句

  1. 那就输入 1 2 进行调试测试

  2. 观察到

4014cf: 39 45 f8 	cmp %eax,-0x8(%rbp)
4014d2: 74 05 	je 4014d9 <phase_3+0x74>
4014d4: e8 67 04 00 00 callq 401940 <explode_bomb>
4014d9: c9 	leaveq 

​ 是函数不爆炸的出口

​ 在这里设置断点,打印出%eax,得到-1199

  1. 得到答案,1 -1199。答案不唯一。

汇编代码:

点击查看代码
0000000000401465 <phase_3>:
 401465:	55 	push %rbp
 401466:	48 89 e5 	mov %rsp,%rbp
 401469:	48 83 ec 10 	sub $0x10,%rsp
 40146d:	48 8d 4d f8 	lea -0x8(%rbp),%rcx
 401471:	48 8d 55 fc 	lea -0x4(%rbp),%rdx
 401475:	be 1f 33 40 00 	mov $0x40331f,%esi
 40147a:	b8 00 00 00 00 	mov $0x0,%eax
 40147f:	e8 8c fc ff ff 	callq 401110 <__isoc99_sscanf@plt>
 401484:	83 f8 01 	cmp $0x1,%eax
 401487:	7e 11 	jle 40149a <phase_3+0x35>
 401489:	8b 45 fc 	mov -0x4(%rbp),%eax
 40148c:	83 f8 07 	cmp $0x7,%eax
 40148f:	77 7b 	ja 40150c <phase_3+0xa7>
 401491:	89 c0 	mov %eax,%eax
 401493:	ff 24 c5 c0 31 40 00 	jmpq *0x4031c0(,%rax,8)
 40149a:	e8 a1 04 00 00 	callq 401940 <explode_bomb>
 40149f:	eb e8 	jmp 401489 <phase_3+0x24>
 4014a1:	b8 00 00 00 00 	mov $0x0,%eax
 4014a6:	2d 7b 02 00 00 	sub $0x27b,%eax
 4014ab:	05 2c 01 00 00 	add $0x12c,%eax
 4014b0:	2d 60 03 00 00 	sub $0x360,%eax
 4014b5:	05 60 03 00 00 	add $0x360,%eax
 4014ba:	2d 60 03 00 00 	sub $0x360,%eax
 4014bf:	05 60 03 00 00 	add $0x360,%eax
 4014c4:	2d 60 03 00 00 	sub $0x360,%eax
 4014c9:	83 7d fc 05 	cmpl $0x5,-0x4(%rbp)
 4014cd:	7f 05 	jg 4014d4 <phase_3+0x6f>
 4014cf:	39 45 f8 	cmp %eax,-0x8(%rbp)
 4014d2:	74 05 	je 4014d9 <phase_3+0x74>
 4014d4:	e8 67 04 00 00 	callq 401940 <explode_bomb>
 4014d9:	c9 	leaveq 
 4014da:	c3 	retq 
 4014db:	b8 95 02 00 00 	mov $0x295,%eax
 4014e0:	eb c4 	jmp 4014a6 <phase_3+0x41>
 4014e2:	b8 00 00 00 00 	mov $0x0,%eax
 4014e7:	eb c2 	jmp 4014ab <phase_3+0x46>
 4014e9:	b8 00 00 00 00 	mov $0x0,%eax
 4014ee:	eb c0 	jmp 4014b0 <phase_3+0x4b>
 4014f0:	b8 00 00 00 00 	mov $0x0,%eax
 4014f5:	eb be 	jmp 4014b5 <phase_3+0x50>
 4014f7:	b8 00 00 00 00 	mov $0x0,%eax
 4014fc:	eb bc 	jmp 4014ba <phase_3+0x55>
 4014fe:	b8 00 00 00 00 	mov $0x0,%eax
 401503:	eb ba 	jmp 4014bf <phase_3+0x5a>
 401505:	b8 00 00 00 00 	mov $0x0,%eax
 40150a:	eb b8 	jmp 4014c4 <phase_3+0x5f>
 40150c:	e8 2f 04 00 00 	callq 401940 <explode_bomb>
 401511:	b8 00 00 00 00 	mov $0x0,%eax
 401516:	eb b1 	jmp 4014c9 <phase_3+0x64>

phase_4

密码如下:10 5

破解过程:

  1. 设置断点,运行,反汇编

  2. 观察到

    401562: be 1f 33 40 00 mov $0x40331f,%esi
    401567: b8 00 00 00 00 mov $0x0,%eax
    40156c: e8 9f fb ff ff callq 401110 <__isoc99_sscanf@plt>
    

​ 调用scanf读入,那么先打印下0x40331f是什么

​ 答案是两个整型变量

  1. 再根据下面这段汇编语言
401576:8b 45 fc mov -0x4(%rbp),%eax
401579:85 c0 test %eax,%eax
40157b:78 05 js 401582 <phase_4+0x30> 
40157d:83 f8 0e cmp $0xe,%eax
401580:7e 05 jle 401587 <phase_4+0x35>
401582:e8 b9 03 00 00 callq 401940 <explode_bomb>
401587:ba 0e 00 00 00 mov $0xe,%edx

得出,输入的第一个数范围:[0, 14]

401594: e8 7f ff ff ff callq 401518 <func4>
401599: 83 f8 05 	cmp $0x5,%eax
40159c: 75 06 	jne 4015a4 <phase_4+0x52>

​ 可知func4的返回值必须为5

40159e: 83 7d f8 05 	cmpl $0x5,-0x8(%rbp)
4015a2: 74 05 	je 4015a9 <phase_4+0x57>
4015a4: e8 97 03 00 00 	callq 401940 <explode_bomb>

​ 可知,输入的第二个数必须为5

  1. 下面分析递归函数func4

    func4里每次都用到 %edi, %esi,%edx,%eax

    而我们输入的第一个数在一开始便是%edi 的值,%esi 一开始为0%edx一开始为0xe,即为14

    不妨,将这四个寄存器, 记为 a,b,c,res

看看这几段

40151c: 89 d1 mov %edx,%ecx
40151e: 29 f1 sub %esi,%ecx
401520: 89 c8 mov %ecx,%eax
401522: c1 e8 1f shr $0x1f,%eax// 逻辑右移31
401525:01c8 add %ecx,%eax 401527: d1 f8 sar %eax //算术右移
401529: 01 f0 add %esi,%eax

写为公式:\(res = [(c - b) >> 31 + (c - b)] / 2 + b\).

化简一下,\(res = (c - b) / 2 + b\).

再看后面的分支,和分支的执行:

if(a < res) func4(a, b, res – 1, res), res *= 2, return res
else if(a > res) func(a, res + 1, c, res), res = res * 2 + 1; return res
else return 0
  1. 现在从最终返回值5倒推一下:
  • \(5 = 2 * 2 + 1\)\(res = (14 - 0) / 2 + 0 = 7\) 当前func4(a, 0, 14, 7) 则递归func4(a, 8, 14, 7)

  • \(2 = 2 * 1\)\(res = (14 - 8) / 2 + 8 = 11\) 当前func4(a, 8, 14, 11) 则递归func4(a, 8, 10, 11)

  • \(1 = 2 * 0 + 1\)\(res = (10 - 8) / 2 + 8 = 9\) 当前func4(a, 8, 10, 9) 则递归func4(a, 10, 10, 9)

  • \(0 = 0\) ,递归终止条件,此时$ res = (10 - 10) / 2 + 10 = 10$

好,那么可以得出 a = 10

  1. 则答案为 10, 5

汇编代码:

点击查看代码
0000000000401518 <func4>:
 401518:	55 	push %rbp
 401519:	48 89 e5 	mov %rsp,%rbp
 40151c:	89 d1 	mov %edx,%ecx
 40151e:	29 f1 	sub %esi,%ecx
 401520:	89 c8 	mov %ecx,%eax
 401522:	c1 e8 1f 	shr $0x1f,%eax
 401525:	01 c8 	add %ecx,%eax
 401527:	d1 f8 	sar %eax
 401529:	01 f0 	add %esi,%eax
 40152b:	39 f8 	cmp %edi,%eax
 40152d:	7f 09 	jg 401538 <func4+0x20>
 40152f:	7c 13 	jl 401544 <func4+0x2c>
 401531:	b8 00 00 00 00 	mov $0x0,%eax
 401536:	5d 	pop %rbp
 401537:	c3 	retq 
 401538:	8d 50 ff 	lea -0x1(%rax),%edx
 40153b:	e8 d8 ff ff ff 	callq 401518 <func4>
 401540:	01 c0 	add %eax,%eax
 401542:	eb f2 	jmp 401536 <func4+0x1e>
 401544:	8d 70 01 	lea 0x1(%rax),%esi
 401547:	e8 cc ff ff ff 	callq 401518 <func4>
 40154c:	8d 44 00 01 	lea 0x1(%rax,%rax,1),%eax
 401550:	eb e4 	jmp 401536 <func4+0x1e>
0000000000401552 <phase_4>:
 401552:	55 	push %rbp
 401553:	48 89 e5 	mov %rsp,%rbp
 401556:	48 83 ec 10 	sub $0x10,%rsp
 40155a:	48 8d 4d f8 	lea -0x8(%rbp),%rcx
 40155e:	48 8d 55 fc 	lea -0x4(%rbp),%rdx
 401562:	be 1f 33 40 00 	mov $0x40331f,%esi
 401567:	b8 00 00 00 00 	mov $0x0,%eax
 40156c:	e8 9f fb ff ff 	callq 401110 <__isoc99_sscanf@plt>
 401571:	83 f8 02 	cmp $0x2,%eax
 401574:	75 0c 	jne 401582 <phase_4+0x30>
 401576:	8b 45 fc 	mov -0x4(%rbp),%eax
 401579:	85 c0 	test %eax,%eax
 40157b:	78 05 	js 401582 <phase_4+0x30>
 40157d:	83 f8 0e 	cmp $0xe,%eax
 401580:	7e 05 	jle 401587 <phase_4+0x35>
 401582:	e8 b9 03 00 00 	callq 401940 <explode_bomb>
 401587:	ba 0e 00 00 00 	mov $0xe,%edx
 40158c:	be 00 00 00 00 	mov $0x0,%esi
 401591:	8b 7d fc 	mov -0x4(%rbp),%edi
 401594:	e8 7f ff ff ff 	callq 401518 <func4>
 401599:	83 f8 05 	cmp $0x5,%eax
 40159c:	75 06 	jne 4015a4 <phase_4+0x52>
 40159e:	83 7d f8 05 	cmpl $0x5,-0x8(%rbp)
 4015a2:	74 05 	je 4015a9 <phase_4+0x57>
 4015a4:	e8 97 03 00 00 	callq 401940 <explode_bomb>
 4015a9:	c9 	leaveq 
 4015aa:	c3 	retq 

phase_5

密码如下:ionefg

破解过程:

  1. 设置断点,运行,反汇编

  2. 观察到

4015b7: e8 74 02 00 00 	callq 401830 <string_length>
4015bc: 83 f8 06 	cmp $0x6,%eax
4015bf: 75 24 	jne 4015e5 <phase_5+0x3a>

​ 推测输入为字符串,且长度为6

  1. 再看接下来一段
4015c1: b8 00 00 00 00 	mov $0x0,%eax
4015c6: 83 f8 05 	cmp $0x5,%eax//循环了6次
4015c9: 7f 21 	jg 4015ec <phase_5+0x41>
4015cb: 48 63 c8 	movslq %eax,%rcx
4015ce: 0f b6 14 0b 	movzbl (%rbx,%rcx,1),%edx 
// 逐个取你输的字符
4015d2: 83 e2 0f 	and $0xf,%edx // 转为[0,15]
4015d5: 0f b6 92 00 32 40 00 movzbl 0x403200(%rdx),%edx
4015dc: 88 54 0d e9 	mov %dl,-0x17(%rbp,%rcx,1)
4015e0: 83 c0 01 	add $0x1,%eax 

可以看出,它取出字符串中每一个字符,然后转为[0, 15]的一个数,然后从地址0x403200 加这个数的偏移量,然后取出一个东西,再把它放入栈的内存中,注意!这里的%dl说明是一个字节,那不还是字符嘛

好,先打印下0x403200处的字符串

​ 发现打印出的一段奇怪的字符串。

​ 但是,根据刚刚分析出的[0,15]的偏移量,我们取出前16个字符

​ 得到:maduiersnfotvbyl

  1. 再将断点设在循环内,每次打印出%dl , 发现对于输入的abcdef,得到了aduierASCII码,再联系一下ASCII码十六进制a0x61。和0xf运算得到 0x1

  2. 发现,输出的字符串中的字符的ASCII码0x60的偏移量 与 原字符串的字符的下标是相等的。

  3. 继续向下看

4015f0: be ae 31 40 00 	mov $0x4031ae,%esi
4015f5: 48 8d 7d e9 	lea -0x17(%rbp),%rdi
4015f9: e8 46 02 00 00 	callq 401844 <strings_not_equal>
4015fe: 85 c0 	test %eax,%eax
401600: 75 07 	jne 401609 <phase_5+0x5e>

​ 发现又是字符串匹配,先看看0x4031ae处的字符串

​ 根据前面得到的结论。先取出这些字符,看在原字符串中的下标。

​ 得到:9 15 14 5 6 7,然后加上0x60, 查阅ASCII码

​ 得到:ionefg

汇编代码:

点击查看代码
00000000004015ab <phase_5>:
 4015ab:	55 	push %rbp
 4015ac:	48 89 e5 	mov %rsp,%rbp
 4015af:	53 	push %rbx
 4015b0:	48 83 ec 18 	sub $0x18,%rsp
 4015b4:	48 89 fb 	mov %rdi,%rbx
 4015b7:	e8 74 02 00 00 	callq 401830 <string_length>
 4015bc:	83 f8 06 	cmp $0x6,%eax
 4015bf:	75 24 	jne 4015e5 <phase_5+0x3a>
 4015c1:	b8 00 00 00 00 	mov $0x0,%eax
// 循环6次 0~5
 4015c6:	83 f8 05 	cmp $0x5,%eax
 4015c9:	7f 21 	jg 4015ec <phase_5+0x41>
 4015cb:	48 63 c8 	movslq %eax,%rcx
 4015ce:	0f b6 14 0b 	movzbl (%rbx,%rcx,1),%edx // 逐个取你输的字符
 4015d2:	83 e2 0f 	and $0xf,%edx // 转为[0,15]
 4015d5:	0f b6 92 00 32 40 00 	movzbl 0x403200(%rdx),%edx
 4015dc:	88 54 0d e9 	mov %dl,-0x17(%rbp,%rcx,1)
 4015e0:	83 c0 01 	add $0x1,%eax 
 4015e3:	eb e1 	jmp 4015c6 <phase_5+0x1b>
 4015e5:	e8 56 03 00 00 	callq 401940 <explode_bomb>
 4015ea:	eb d5 	jmp 4015c1 <phase_5+0x16>
 4015ec:	c6 45 ef 00 	movb $0x0,-0x11(%rbp)
 4015f0:	be ae 31 40 00 	mov $0x4031ae,%esi
 4015f5:	48 8d 7d e9 	lea -0x17(%rbp),%rdi
 4015f9:	e8 46 02 00 00 	callq 401844 <strings_not_equal>
 4015fe:	85 c0 	test %eax,%eax
 401600:	75 07 	jne 401609 <phase_5+0x5e>
 401602:	48 83 c4 18 	add $0x18,%rsp
 401606:	5b 	pop %rbx
 401607:	5d 	pop %rbp
 401608:	c3 	retq 
 401609:	e8 32 03 00 00 	callq 401940 <explode_bomb>
 40160e:	eb f2 	jmp 401602 <phase_5+0x57>

phase_6

密码如下:2 6 4 3 1 5

破解过程:

  1. 设置断点,运行,反汇编

  2. 解读汇编代码知:

    1. 读6个数
    2. 二重循环,判断是否每个数大于6,判断是否和其他数相等。即,输入的应该为1~6的排列
    3. 将每个数i转化为\(j = 7 – i\)
    4. 取出链表的第j个元素的值,放入栈中
    5. 遍历一遍放入栈的6个链表元素,判断是否为降序
  3. 链表的发现:

4016be: ba d0 52 40 00 	mov $0x4052d0,%edx // 链表头
4016c9: 48 89 d9 	mov %rbx,%rcx 
4016db: 48 89 51 08 	mov %rdx,0x8(%rcx) //next指针

发现是链式结构,设置断点,打印出:

发现nodej也是在提示

第一个为链表值,第二个为链表游标,第三个为next指针

  1. 那么,将链表值按降序排序,得到游标为5 1 3 4 6 2

  2. 再,由 \(j = 7 – i\), 得到答案 2 6 4 3 1 5

汇编代码:

点击查看代码
0000000000401610 <phase_6>:
 401610:	55 	push %rbp
 401611:	48 89 e5 	mov %rsp,%rbp
 401614:	41 55 	push %r13
 401616:	41 54 	push %r12
 401618:	53 	push %rbx
 401619:	48 83 ec 58 	sub $0x58,%rsp
 40161d:	48 8d 75 c0 	lea -0x40(%rbp),%rsi
 401621:	e8 3c 03 00 00 	callq 401962 <read_six_numbers>
 401626:	41 bc 00 00 00 00 mov $0x0,%r12d // %r12d = 0
 40162c:	eb 29 	jmp 401657 <phase_6+0x47>
 40162e:	e8 0d 03 00 00 	callq 401940 <explode_bomb>
 401633:	eb 37 	jmp 40166c <phase_6+0x5c>
 401635:	e8 06 03 00 00 	callq 401940 <explode_bomb>
 40163a:	83 c3 01 	add $0x1,%ebx
===============================================================
------------------------------------------------------------
 40163d:	83 fb 05 	cmp $0x5,%ebx // if(%ebx > 5)
 401640:	7f 12 	jg 401654 <phase_6+0x44>
 401642:	49 63 c4 	movslq %r12d,%rax // %rax = %r12d
 401645:	48 63 d3 	movslq %ebx,%rdx // %rdx = %ebx
 401648:	8b 7c 95 c0 	mov -0x40(%rbp,%rdx,4),%edi
	
 40164c:	39 7c 85 c0 	cmp %edi,-0x40(%rbp,%rax,4)
 401650:	75 e8 	jne 40163a <phase_6+0x2a>
-----------------------------------------------------------
 401652:	eb e1 	jmp 401635 <phase_6+0x25>
 401654:	45 89 ec 	mov %r13d,%r12d
 401657:	41 83 fc 05 	cmp $0x5,%r12d // cmp %r12d 5
 40165b:	7f 19 	jg 401676 <phase_6+0x66> // >
 40165d:	49 63 c4 	movslq %r12d,%rax	// %rax = %r12d
 401660:	8b 44 85 c0 	mov -0x40(%rbp,%rax,4),%eax 
 401664:	83 e8 01 	sub $0x1,%eax // %rax -= 1
 401667:	83 f8 05 	cmp $0x5,%eax	// if rax > 5
 40166a:	77 c2 	ja 40162e <phase_6+0x1e>
 40166c:	45 8d 6c 24 01 	lea 	0x1(%r12),%r13d 
// %r13d=(%r12d+1)
 401671:	44 89 eb 	mov %r13d,%ebx // %ebx = %r13d
 401674:	eb c7 	jmp 40163d <phase_6+0x2d>
================================================================
 401676:	b8 00 00 00 00 	mov $0x0,%eax // %eax = 0
 40167b:	eb 13 	jmp 401690 <phase_6+0x80>
// j = 7 - i
==========================================================
 40167d:	48 63 c8 	movslq %eax,%rcx
 401680:	ba 07 00 00 00 	mov $0x7,%edx
 401685:	2b 54 8d c0 	sub -0x40(%rbp,%rcx,4),%edx
 	从第一个数开始
 401689:	89 54 8d c0 	mov %edx,-0x40(%rbp,%rcx,4)
 40168d:	83 c0 01 	add $0x1,%eax
 401690:	83 f8 05 	cmp $0x5,%eax
 401693:	7e e8 	jle 40167d <phase_6+0x6d>
==========================================================
 401695:	be 00 00 00 00 	mov $0x0,%esi
 40169a:	eb 18 	jmp 4016b4 <phase_6+0xa4>
 40169c:	48 8b 52 08 	mov 0x8(%rdx),%rdx
 4016a0:	83 c0 01 	add $0x1,%eax
//二重循环,寻找第j个链表元素
==============================================================
 4016a3:	48 63 ce 	movslq %esi,%rcx
 4016a6:	39 44 8d c0 	cmp %eax,-0x40(%rbp,%rcx,4)
 4016aa:	7f f0 	jg 40169c <phase_6+0x8c>
 4016ac:	48 89 54 cd 90 	mov %rdx,-0x70(%rbp,%rcx,8)
 4016b1:	83 c6 01 	add $0x1,%esi
 4016b4:	83 fe 05 	cmp $0x5,%esi
 4016b7:	7f 0c 	jg 4016c5 <phase_6+0xb5>
 4016b9:	b8 01 00 00 00 	mov $0x1,%eax
 4016be:	ba d0 52 40 00 	mov $0x4052d0,%edx // 链表头
 4016c3:	eb de 	jmp 4016a3 <phase_6+0x93>
 4016c5:	48 8b 5d 90 	mov -0x70(%rbp) 
 4016c9:	48 89 d9 	mov %rbx,%rcx //%rcx = %rbx
 4016cc:	b8 01 00 00 00 	mov $0x1,%eax // eax = 1
 4016d1:	eb 12 	jmp 4016e5 <phase_6+0xd5>
 4016d3:	48 63 d0 	movslq %eax,%rdx // rdx = eax
 4016d6:	48 8b 54 d5 90 	mov -0x70(%rbp,%rdx,8),%rdx
 4016db:	48 89 51 08 	mov %rdx,0x8(%rcx) 
 4016df:	83 c0 01 	add $0x1,%eax
 4016e2:	48 89 d1 	mov %rdx,%rcx // rcx = rdx
 4016e5:	83 f8 05 	cmp $0x5,%eax // while 循环
 4016e8:	7e e9 	jle 4016d3 <phase_6+0xc3>
=========================================================
 4016ea:	48 c7 41 08 00 00 00 movq $0x0,0x8(%rcx)
 4016f1:	00 
 4016f2:	41 bc 00 00 00 00 mov $0x0,%r12d
 4016f8:	eb 08 	jmp 401702 <phase_6+0xf2>
 4016fa:	48 8b 5b 08 	mov 0x8(%rbx),%rbx
 4016fe:	41 83 c4 01 	add $0x1,%r12d
 401702:	41 83 fc 04 	cmp $0x4,%r12d
 401706:	7f 11 	jg 401719 <phase_6+0x109>
 401708:	48 8b 43 08 	mov 0x8(%rbx),%rax
 40170c:	8b 00 	mov (%rax),%eax
 40170e:	39 03 	cmp %eax,(%rbx)
 401710:	7d e8 	jge 4016fa <phase_6+0xea>
// 这里是一重循环,判断是否前个元素大于等于后一个元素,即降序
// 否则爆炸
 401712:	e8 29 02 00 00 	callq 401940 <explode_bomb>
 401717:	eb e1 	jmp 4016fa <phase_6+0xea>
 401719:	48 83 c4 58 	add $0x58,%rsp
 40171d:	5b 	pop %rbx
 40171e:	41 5c 	pop %r12
 401720:	41 5d 	pop %r13
 401722:	5d 	pop %rbp
 401723:	c3 	retq 

secret_phase

密码如下:47

破解过程:

  1. 首先要找到入口,看phase_defused函数
0000000000401ac9 <phase_defused>:
401ac9: 83 3d 9c 3c 00 00 06 cmpl $0x6,0x3c9c(%rip) \#40576c <num_input_strings>
401ad0: 74 01 je 401ad3 <phase_defused+0xa>

​ 在0x401ad0处设置断点,然后打印出0x3c9c(%rip)

​ 发现分别为 1 2 3 4 5 6

​ 则可以推断出,要在6个炸弹都拆后才可以进入后边。

401ae7: be 69 33 40 00 	mov $0x403369,%esi
401aec: bf 70 58 40 00 	mov $0x405870,%edi
----
401b0c: be 72 33 40 00 	mov $0x403372,%esi
401b11: 48 8d 7d b0 	lea -0x50(%rbp),%rdi
401b15: e8 2a fd ff ff 	callq 401844 <strings_not_equal>

先打印出这三个地址的字符串:

可以推断出,输入为两个整型变量和一个字符串。

且这个字符串必须为DrEvil。但是,phase_4phase_3的输入都是两个整数

那么我们在判断字符串相等处,设置断点,打印出值观察:

10 和 5!

那么就确定为phase_4的答案后加上DrEvil

  1. 成功进入隐藏关。

  2. secret_phase函数

000000000040175e <secret_phase>:
401767: e8 32 02 00 00 callq 40199e <read_line>
40176f: e8 cc f9 ff ff callq 401140 <atoi@plt

发现了readline函数和atoi函数,说明是输一个数字。(atoi函数作用为将字符串转为整型)

401776: 8d 40 ff 	lea -0x1(%rax),c%eax
401779: 3d e8 03 00 00 	cmp $0x3e8,%eax //1000
40177e: 77 27 	ja 4017a7 <secret_phase+0x49>
401780: 89 de 	mov %ebx,%esi
401782: bf f0 50 40 00 	mov $0x4050f0,%edi//此处地址的值为36
401787: e8 98 ff ff ff callq 401724 <fun7>
40178c: 83 f8 05 cmp $0x5,%eax //返回值得为5

则输出值不超1001

​ 输入进func7后,返回值必须为5

  1. 再看func7函数又是一个分支+递归。

    直接写出伪代码:

​ 记%rdip%raxres, %esix

​ 则func7(* p, int res, int x)

​ 一开始,\(*p = 36\)x为你输入的数。

if(x < *p) 
	p = *(p + 8),func7(p, res, x), res *= 2,return res; 
else if(x > *p)
	p = *(p + 10),func7(p, res, x), res = res * 2 + 1,return res;
else
	return 0; 

那么现在由返回值5逆推

5 = 2 * 2 + 1 	p = *p + 10
2 = 2 * 1 	p = *p + 8
1 = 2 * 0 + 1 	p = *p + 10
0 = 0 	*p == x

则可以调试打印出:

  1. \(0x2f = 47\)

汇编代码:

点击查看代码
0000000000401724 <fun7>:
 401724:	48 85 ff 	test %rdi,%rdi
 401727:	74 2f 	je 401758 <fun7+0x34>
 401729:	55 	push %rbp
 40172a:	48 89 e5 	mov %rsp,%rbp
 40172d:	8b 07 	mov (%rdi),%eax
 40172f:	39 f0 	cmp %esi,%eax
 401731:	7f 09 	jg 40173c <fun7+0x18>
 401733:	75 14 	jne 401749 <fun7+0x25>
 401735:	b8 00 00 00 00 	mov $0x0,%eax
 40173a:	5d 	pop %rbp
 40173b:	c3 	retq 
 40173c:	48 8b 7f 08 	mov 0x8(%rdi),%rdi
 401740:	e8 df ff ff ff 	callq 401724 <fun7>
 401745:	01 c0 	add %eax,%eax
 401747:	eb f1 	jmp 40173a <fun7+0x16>
 401749:	48 8b 7f 10 	mov 0x10(%rdi),%rdi
 40174d:	e8 d2 ff ff ff 	callq 401724 <fun7>
 401752:	8d 44 00 01 	lea 0x1(%rax,%rax,1),%eax
 401756:	eb e2 	jmp 40173a <fun7+0x16>
 401758:	b8 ff ff ff ff 	mov $0xffffffff,%eax
 40175d:	c3 	retq 
000000000040175e <secret_phase>:
 40175e:	55 	push %rbp
 40175f:	48 89 e5 	mov %rsp,%rbp
 401762:	53 	push %rbx
 401763:	48 83 ec 08 	sub $0x8,%rsp
 401767:	e8 32 02 00 00 	callq 40199e <read_line>
 40176c:	48 89 c7 	mov %rax,%rdi
 40176f:	e8 cc f9 ff ff 	callq 401140 <atoi@plt>
 401774:	89 c3 	mov %eax,%ebx
 401776:	8d 40 ff 	lea -0x1(%rax),%eax
 401779:	3d e8 03 00 00 	cmp $0x3e8,%eax
 40177e:	77 27 	ja 4017a7 <secret_phase+0x49>
 401780:	89 de 	mov %ebx,%esi
 401782:	bf f0 50 40 00 	mov $0x4050f0,%edi
 401787:	e8 98 ff ff ff 	callq 401724 <fun7>
 40178c:	83 f8 05 	cmp $0x5,%eax
 40178f:	75 1d 	jne 4017ae <secret_phase+0x50>
 401791:	bf 88 31 40 00 	mov $0x403188,%edi
 401796:	e8 c5 f8 ff ff 	callq 401060 <puts@plt>
 40179b:	e8 29 03 00 00 	callq 401ac9 <phase_defused>
 4017a0:	48 83 c4 08 	add $0x8,%rsp
 4017a4:	5b 	pop %rbx
 4017a5:	5d 	pop %rbp
 4017a6:	c3 	retq 
 4017a7:	e8 94 01 00 00 	callq 401940 <explode_bomb>
 4017ac:	eb d2 	jmp 401780 <secret_phase+0x22>
 4017ae:	e8 8d 01 00 00 	callq 401940 <explode_bomb>
 4017b3:	eb dc 	jmp 401791 <secret_phase+0x33>
0000000000401ac9 <phase_defused>:
 401ac9:	83 3d 9c 3c 00 00 06 	cmpl $0x6,0x3c9c(%rip) # 40576c <num_input_strings>
 401ad0:	74 01 	je 401ad3 <phase_defused+0xa>
 401ad2:	c3 	retq 
 401ad3:	55 	push %rbp
 401ad4:	48 89 e5 	mov %rsp,%rbp
 401ad7:	48 83 ec 60 	sub $0x60,%rsp
 401adb:	4c 8d 45 b0 	lea -0x50(%rbp),%r8
 401adf:	48 8d 4d a8 	lea -0x58(%rbp),%rcx
 401ae3:	48 8d 55 ac 	lea -0x54(%rbp),%rdx
 401ae7:	be 69 33 40 00 	mov $0x403369,%esi
 401aec:	bf 70 58 40 00 	mov $0x405870,%edi
 401af1:	b8 00 00 00 00 	mov $0x0,%eax
 401af6:	e8 15 f6 ff ff 	callq 401110 <__isoc99_sscanf@plt>
 401afb:	83 f8 03 	cmp $0x3,%eax
 401afe:	74 0c 	je 401b0c <phase_defused+0x43>
 401b00:	bf a8 32 40 00 	mov $0x4032a8,%edi
 401b05:	e8 56 f5 ff ff 	callq 401060 <puts@plt>
 401b0a:	c9 	leaveq 
 401b0b:	c3 	retq 
 401b0c:	be 72 33 40 00 	mov $0x403372,%esi
 401b11:	48 8d 7d b0 	lea -0x50(%rbp),%rdi
 401b15:	e8 2a fd ff ff 	callq 401844 <strings_not_equal>
 401b1a:	85 c0 	test %eax,%eax
 401b1c:	75 e2 	jne 401b00 <phase_defused+0x37>
 401b1e:	bf 48 32 40 00 	mov $0x403248,%edi
 401b23:	e8 38 f5 ff ff 	callq 401060 <puts@plt>
 401b28:	bf 70 32 40 00 	mov $0x403270,%edi
 401b2d:	e8 2e f5 ff ff 	callq 401060 <puts@plt>
 401b32:	b8 00 00 00 00 	mov $0x0,%eax
 401b37:	e8 22 fc ff ff 	callq 40175e <secret_phase>
 401b3c:	eb c2 	jmp 401b00 <phase_defused+0x37>

后记

做了一遍挺痛苦,然后写实验报告梳理了一遍思路,还是挺有收获的。

作者:江水为竭原文地址:https://www.cnblogs.com/Az1r/p/16769856.html

%s 个评论

要回复文章请先登录注册