ToB企服应用市场:ToB评测及商务社交产业平台
标题:
BinaryBombs(二进制炸弹实验)
[打印本页]
作者:
tsx81428
时间:
2022-10-8 20:04
标题:
BinaryBombs(二进制炸弹实验)
实验介绍
使用所学知识拆除
Binary Bombs
来增强对程序的机器级表示、汇编语言、调试器和逆向工程等理解。
Binary Bombs
(
二进制炸弹
)是一个可执行程序,是
C语言
编译链接成的,包含phase1~phase6共6个阶段(还有隐藏阶段)。
各阶段要求输入一个答案,若正确,该阶段炸弹被
拆除
,否则
爆炸
。
你需要拆除尽可能多的炸弹
实验提供一个
bomb.c
和
bomb
可执行文件,但是,
bomb.c
中只有主函数,和一些彩蛋。
bomb
有一个命令行参数,为读入的文件。所以你可以将答案写入到一个txt文件,每个答案一行。
实验技巧
gdb调试
(gdb)info reg查看所有寄存器的信息
(gdb)info frame查看栈的信息
(gdb)b * 0x405040在
0x405040
处设置断点
(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.
破解过程:
在
phase_1
函数处设置断点。
随便输出一个答案,如
abcdef
。
观察断点信息,
input_strings
可知,答案确实是一个字符串。
反汇编观察到
strings_not_equal
,推测是在判断字符串是否相等。然后,
test
命令测试返回值,如果非0,则爆炸。
0为真,1为假,那么非0对于
strings_not_equal
,应该是字符串不等,所以现在要找到那个与输出的字符串匹配的字符串。
观察到,传递给寄存器
%esi
的值
0x403150
打印此处的字符串: x/2s 0x403150
得到答案
汇编代码:
点击查看代码
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
破解过程:
<ol>在
phase_2
设置断点。
运行,参数为
ans.txt
,其中写有刚刚得到的第一个的答案。
先随便输入,这里输入一个数
5
。
反汇编观察,一开始调用了函数,那么可以先把输入改为6个数
继续观察下面的汇编语言,发现
-30(%rbp)
不就是存放第一个数的位置吗?这里判断第一个数必须为
0
,否则炸弹爆炸
在后面,
%ebx
先赋值为
1
,然后判断是否大于
5
,是一个循环,然后根据输入的
6
个数,每轮打印发现规律。
得出代码:for(int i = 1; i > 31 + (c - b)] / 2 + b\).
化简一下,\(res = (c - b) / 2 + b\).
再看后面的分支,和分支的执行:
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
复制代码
现在从最终返回值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
则答案为
10, 5
汇编代码:
点击查看代码
401489: 8b 45 fc mov -0x4(%rbp),%eax
40148c: 83 f8 07 cmp $0x7,%eax
40148f: 77 7b ja 40150c <phase_3+0xa7>
复制代码
phase_5
密码如下:ionefg
破解过程:
设置断点,运行,反汇编
观察到
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
复制代码
推测输入为字符串,且长度为
6
再看接下来一段
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>
复制代码
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>
复制代码
可以看出,它取出字符串中每一个字符,然后转为
[0, 15]
的一个数,然后从地址
0x403200
加这个数的
偏移量
,然后取出一个东西,再把它放入栈的内存中,注意!这里的
%dl
说明是一个字节,那不还是字符嘛
好,先打印下
0x403200
处的字符串
发现打印出的一段奇怪的字符串。
但是,根据刚刚分析出的
[0,15]
的偏移量,我们取出前16个字符
得到:
maduiersnfotvbyl
再将断点设在循环内,每次打印出
%dl
, 发现对于输入的
abcdef
,得到了
aduier
的
ASCII码
,再联系一下
ASCII码
的
十六进制
,
a
为
0x61
。和
0xf
做
与
运算得到
0x1
。
发现,输出的字符串中的字符的
ASCII码
对
0x60
的偏移量 与 原字符串的字符的
下标
是相等的。
继续向下看
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
复制代码
发现又是字符串匹配,先看看
0x4031ae
处的字符串
根据前面得到的结论。先取出这些字符,看在原字符串中的下标。
得到:9 15 14 5 6 7,然后加上
0x60
, 查阅ASCII码
得到:ionefg
汇编代码:
点击查看代码
401594: e8 7f ff ff ff callq 401518 <func4>
401599: 83 f8 05 cmp $0x5,%eax
40159c: 75 06 jne 4015a4 <phase_4+0x52>
复制代码
phase_6
密码如下:2 6 4 3 1 5
破解过程:
设置断点,运行,反汇编
解读汇编代码知:
读6个数
二重循环,判断是否每个数大于6,判断是否和其他数相等。即,输入的应该为1~6的排列
将每个数
i
转化为\(j = 7 – i\)
取出链表的第
j
个元素的值,放入栈中
遍历一遍放入栈的6个链表元素,判断是否为降序
链表的发现:
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>
复制代码
发现是链式结构,设置断点,打印出:
发现
nodej
也是在提示
第一个为链表值,第二个为链表游标,第三个为next指针
那么,将链表值按降序排序,得到游标为5 1 3 4 6 2
再,由 \(j = 7 – i\), 得到答案 2 6 4 3 1 5
汇编代码:
点击查看代码
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
复制代码
secret_phase
密码如下:47
破解过程:
首先要找到入口,看
phase_defused
函数
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
复制代码
在
0x401ad0
处设置断点,然后打印出
0x3c9c(%rip)
发现分别为 1 2 3 4 5 6
则可以推断出,要在6个炸弹都拆后才可以进入后边。
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
复制代码
先打印出这三个地址的字符串:
可以推断出,输入为两个整型变量和一个字符串。
且这个字符串必须为
DrEvil
。但是,
phase_4
和
phase_3
的输入都是两个整数
那么我们在判断字符串相等处,设置断点,打印出值观察:
10 和 5!
那么就确定为
phase_4
的答案后加上
DrEvil
成功进入隐藏关。
看
secret_phase
函数
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>
复制代码
那么现在由
返回值5
逆推
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>
复制代码
则可以调试打印出:
\(0x2f = 47\)
汇编代码:
点击查看代码
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
复制代码
后记
做了一遍挺痛苦,然后写实验报告梳理了一遍思路,还是挺有收获的。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4