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()
函数内部。显示如下汇编内容:
第 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
。
输入step
、finish
等命令,在 phase_2(input)
处输入stepi
进入第二个炸弹函数。
观察到 第 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
。
输入step
、finish
等命令,在 phase_3(input)
处输入stepi
进入第三个炸弹函数
输入 stepi
一步步观察运行位置:
第 8 行:比较 0x1
和 %eax
的大小
第 9 行:如果 %eax
的内容比 0x1
大,就跳到第 11 行,否则继续执行到第 10 行爆炸。
那么 %eax
的内容在哪里呢?
在第 7 行调用的 sscanf
函数中获取了我们输入的数字, %eax
存储的是sscanf
函数的返回值。
小结:%eax
必须大于 1,所以至少输入 2 个参数。
第 11 行:比较 0x7
和 (%rsp) + 0x8
的结果。
第 12 行:如果 (%rsp) + 0x8
比 0X7
大,则炸弹爆炸。
第 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
。
输入step
、finish
等命令,在 phase_4(input)
处输入stepi
进入第四个炸弹函数。
第 7 - 9 行调用的 sscanf
函数中获取了我们输入的数字, %eax
存储的是sscanf
函数的返回值,如果输入参数个数不等于 2 ,那么跳到第 12 行炸弹爆炸。
第 10 - 12 行,比较(%rsp) + 0x8
是否小于等于 0xe
,即第一个参数是否小于等于 14 ,有就跳到第 13 行,没有就执行到第 12 行炸弹爆炸。
第 16 行进入 func4
1 |
|
第 17 - 18 行,检查%eax
即 func4
的返回值是否为 0,如果不为 0 炸弹爆炸。否则继续执行到第 19 行。
第 19 行: 比较 第二个输入数字是否为0,如果不为 0 炸弹爆炸,否则跳到第 22 行结束。