CSAPP_BombLab
Published:
代码参考:https://github.com/ChenYuHengSJTU/CSAPP_Labs/tree/main/bomblab/bomb
准备
- 从 README.md 中,可知,我们可以创建一个 answer.txt 文件放置输出,这样就可以使用./bomb answer.txt 来运行 bomb,无需多次输入
- 使用 gdb bomb 启动调试
- 进入 gdb 界面后,输入 run answer.txt 运行
- 拆解第一个炸弹,进入 gdb 调试界面后加入断点 b phase_1, 拆解后面的炸弹以此类推
Phase_1
启动 gdb 后设置断点,然后 c 运行至断点
在 answer.txt 中输入 hello 作为假设的输入
gdb 中输入 layout asm 显示汇编代码
si 单步运行(进入调用的函数)
首先进入函数 string_not_equal
- 打印寄存器 ` p $rdi ` , 发现是我们的输入,再打印另外一个传给
string_not_equal
的参数,p $rsi
, 即得到答案Border relations with Canada have never been better
Phase_2:
还是侥幸地输入 hello,然而还是炸了
打断点,然后调出 tui 的汇编界面
- 可以看到,
read_six_numbers
的函数调用 - 输入
1 2 3 4 5 6
接着向下看汇编,可以看到,这是一个循环,依次对输入的六个数进行一定的操作
其中最重要的应该是 add %eax,%eax, 将每次读入的数乘 2,然后与下一个数比较
于是,我们的输入应该是一个公比为 2 的等比数列
我的输入:1 2 4 8 16 32
我们依旧侥幸地输入 hello
炸!
看了一眼 phase_3 的汇编代码,第一眼并没有看到一些很有用的信息,于是从头开始单步执行 si 或 ni
走到输入的函数调用
__isoc99 sscanfaplt
那么,传入的参数是什么呢
打印 $edi
p (char*)$esi
!
发现新大陆,是 C 语言里极其常见的格式字符串 “%d %d”
应该传入两个参数
继续发扬优良传统,输入 0,1
炸!
- 在这里(上图),我们发现,程序将两个参数
*(int*)$rsp,*(int*)($rsp+0xc)
依次与$eax
比较,我们打印栈上的内容,发现是我们的输入!
- 再依次查看赋给
$eax
的值,可得答案:1 311
Phase_4
- hello!!!
- 查看汇编,我们发现,phase_4 调用了函数 func4
至于接下去嘛,试着试着,就过了,看汇编,好像就是输入 0 1
我的输入:0 1
Phase_5
孤单的黑夜途中,只要输入 hello,bomb 就不会惶恐
查看汇编,string_length,嗷,还是输入字符串
不过这次有意思得多
phase_5 的汇编代码很长,跳来跳去,还随时接一句
callq 0x40143a<explode_bomb>
我们发现有一个常量地址,0x4024b0,我们打印之,发现!!!
maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?!
我的回答是 ctrl-c 不行,但是 hello 可以
不过这个字符串要怎么利用呢
一阵 ni,发现代码一直在这段汇编之间跳,然后处理完后调用 string_not_equal
layout regs
, 方便查看寄存器的变化,我们发现,这个过程是,使用 0xf 依次对我们输入的每个字符的 ascii 码取低位,得到的值作为索引,到maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?!
中取字符,来生成比较的字符串通过打印参数传递寄存器,得到被比较的字符串是
flyers
然后仔细比较、取字符、拼接
我的输入
ionefg
Phase_6
hello
不能皮了,phase_6 的代码还是又臭又长很难懂的
不过做到 phase_6 了,不难看出输入还是六个数
难道是???
1 2 3 4 5 6
bomb!
并且 —
由这里的循环,发现,这六个数必须在 1 和 6 之间,且不能相等
呦吼,我们的输入到此刚好符合要求
往下看
发现这里也有一个常量地址
$0x6032d0
迫不及待地打印之
p *(int*)0x6032d0
发现是 332
咦,奇怪的数!
往后打印,
p *(int*)(0x6032d0 + 8)
这或许是?结构体?因为
p *(int*)(0x6032d0 + 8)
的结果恰是0x6032d0 + 16
,而指针长度恰好是 8 bytes,像不像链表?一顿打印猛如虎
得到 332,1 -> 168,2 -> 924,3 -> 691,4 -> 477,5 -> 443,6
不过虽然发现至此,我们的答案还是被炸了
直接看最后!
我们发现,这个循环只有当最后的链表,从头到尾的数值依次增大才可以安全退出
我们打印这时候的链表,可以得到结论,phase_6 是按照我们输入的 1 - 6 的序列来对链表进行排序的,我们输入 1 2 3 4 5 6,得到的是逆序链表,类似于翻转链表
根据此规律,得到答案
我的输入:
4 3 2 1 6 5