CSAPP-Bomb Lab - write up

Bomb Lab - write up

[TOC]

资源来自于GitHub Repo:ICS-15213-CSAPP3e-CMU

调试环境: Ubuntu 20.04 LTS, cgdb-0.7.1

bomb 执行文件所在的文件夹下,打开 Terminal:

输入 cgdb bomb 开始调试 bomb 程序。按 Esc 进入 cgdb, ctrl + w 左右分屏,按i 切回 gdb。

对照 bomb.c 找到 phase_1(input); 将此行设置为断点位置: break 74, 即 break 空格 加上行号。

创建一个文件 in, 在第一行随便输入一些内容。

bomb1

run < in , 程序行至断点处,stepi 进入 phase_1() 函数内部。显示如下汇编内容:

image-20210219210624203

第 3 行:把 0x402400 放进了 %esi 作为函数参数。

第 4 行:调用了strings_not_equal判断两个字符串是否不同。

第 5 行:判断 %eax 是否为0,如果为0,则跳过第 7 行,运行至 +23 处,即第 8 行。

由上分析可知, phase_1() 的输入是 %esi中的内容,即 0x402400

输入print (char*) 0x402400 得到 $4 = 0x402400 "Border relations with Canada have never been better."

bomb2

在文件 in, 在第一行输入 Border relations with Canada have never been better. 跳过bomb1。第二行随意写。

输入 run < in, 观察第二个断点位置,设置在break 82

输入stepfinish 等命令,在 phase_2(input) 处输入stepi 进入第二个炸弹函数。

image-20210220162257086

观察到 第 6 行读取 6 个数字。

第 7 行: 比较 1 和 %rsp 中指向的第一个数据

第 8 行: 如果相等,则跳到 +52 处,即第 20 行。 如果不相等,则进入第 9 行引爆炸弹。

第 20 行: %rsp 拿出指向位置 + 0x4 的数据,放入 %rbx

第 21 行: %rsp 拿出指向位置 + 0x18 的数据,放入 %rbp

第 22 行: 跳回第 11 行。

小结: 输入内容为 6 个数字,并且第一个数字必须为 1%rbx 指向的内容此时为第 2 个数字。


第 11 行:%rbx 拿出前一个数字 %rbx - 0x4 放入 %eax

第 12 行:%eax = %eax + %eax

第 13 行: 比较 %eax%rbx 中指向的数据。

第 14 行:如果相等,则跳到 +41 处,即第 16 行。 如果不相等,则进入第 15 行引爆炸弹。

小结:因为 %eax%rbx 指向数字的前一个数字,经过第 12 行的累加,%eax%rbx 指向数字的前一个数字的两倍。要想炸弹不爆炸,则 %rbx 现在指向的数字必须为前一个数字的两倍。对于全输入的6个数字来说,第二个数字就是 1 的两倍,为 2


第 16 行:%rbx = %rbx + 0x4

第 17 行:比较 %rbp%rbx 中的数据

第 18 行:如果不相等,则跳到 +27 处,即 第 11 行。

小结%rbx 变为下一个输入的数字,对于 11-18 行的代码,他们属于一个循环。每次循环都在验证当前的数字是否为前一个数字的两倍


综上,输入的 6 个数字为公比为 2 的等比数列:1 2 4 8 16 32

bomb3

在文件 in, 在第一行输入 Border relations with Canada have never been better. 跳过bomb1。第二行输入 1 2 4 8 16 32。第三行随意写。

输入 run < in, 观察第二个断点位置,设置在break 89

输入stepfinish 等命令,在 phase_3(input) 处输入stepi 进入第三个炸弹函数

image-20210220172800167

输入 stepi 一步步观察运行位置:

第 8 行:比较 0x1%eax 的大小

第 9 行:如果 %eax 的内容比 0x1 大,就跳到第 11 行,否则继续执行到第 10 行爆炸。

那么 %eax 的内容在哪里呢?

在第 7 行调用的 sscanf 函数中获取了我们输入的数字, %eax 存储的是sscanf函数的返回值。

小结%eax 必须大于 1,所以至少输入 2 个参数


第 11 行:比较 0x7(%rsp) + 0x8 的结果。

第 12 行:如果 (%rsp) + 0x80X7 大,则炸弹爆炸。

第 13 行:(%rsp) + 0x8 放入 %eax 中。第 14 行:跳到第 17 行。

第 17 行:0x2c3 放入 %eax 中。第 18 行:跳到第 33 行。

第 33 行:比较 0xc(%rsp)%eax 中的内容。

第 34 行:如果相等,则结束,否则炸弹爆炸。

小结:第一个参数(%rsp) + 0x8 要比 7 小。第二个参数 0xc(%rsp) 要和 0x2c3 相等。通过计算,0x2c3 的十进制为 707

综上,答案为 2 707 ,不唯一。

bomb4

在文件 in, 在第一行输入 Border relations with Canada have never been better. 跳过bomb1。第二行输入 1 2 4 8 16 32。第三行输入2 707,第四行随意写。

输入 run < in, 观察第二个断点位置,设置在break 95

输入stepfinish 等命令,在 phase_4(input) 处输入stepi 进入第四个炸弹函数。

image-20210220225042778

第 7 - 9 行调用的 sscanf 函数中获取了我们输入的数字, %eax 存储的是sscanf函数的返回值,如果输入参数个数不等于 2 ,那么跳到第 12 行炸弹爆炸。

第 10 - 12 行,比较(%rsp) + 0x8是否小于等于 0xe,即第一个参数是否小于等于 14 ,有就跳到第 13 行,没有就执行到第 12 行炸弹爆炸。

第 16 行进入 func4

image-20210220232742815

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

rcx >>= 0x1f
eax += ecx
eax >>= 1
ecx = rax + rsi*1
if (ecx <= edi){
eax = 0
if ecx >= edi{
return
}else {
esi = rcx + 0x1
func4()
}
} else {
edx = rcx - 0x1
func4()
return
}

第 17 - 18 行,检查%eaxfunc4的返回值是否为 0,如果不为 0 炸弹爆炸。否则继续执行到第 19 行。

第 19 行: 比较 第二个输入数字是否为0,如果不为 0 炸弹爆炸,否则跳到第 22 行结束。