Skip to content

Commit 9d6b91a

Browse files
authored
Merge pull request #31 from ICS-25Fall-FDU/flowlab-fix
Add requirement and some example pictures; and some small fixes
2 parents c0849a2 + bd7300b commit 9d6b91a

File tree

5 files changed

+48
-21
lines changed

5 files changed

+48
-21
lines changed

docs/lab/flowlab/problem4-8.png

79.7 KB
Loading

docs/lab/flowlab/task2-1.png

47.4 KB
Loading

docs/lab/flowlab/try_raise.png

272 KB
Loading

docs/lab/lab3.md

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
# Lab3: FlowLab
22

3-
> Deadline:2025-11-11 23:59:59
3+
> Deadline:2025-11-18 23:59:59
44
55
## 〇、实验简介
66

77
### 实验简介
88

99
栈帧与程序控制流相关实验。
1010

11-
本学期,我们仍然将金老师 ICS 第三个 Lab 回炉重造,减轻代码工作量并添加更多讲解和提示,以加深各位同学对栈帧和程序控制流的理解,并探索协程的应用,最后从宏观角度思考程序控制流的发展,丰富同学们的知识面
11+
本学期,我们依然将金老师 ICS 第三个 Lab 回炉重造,减轻代码工作量并添加更多讲解和提示,以加深各位同学对栈帧和程序控制流的理解。
1212

1313
本次Lab由五个部分组成,含四个主题:
1414

1515
- 尝试在含有漏洞的程序中实现**任意代码执行**
1616
- 学习 Canary 机制,了解栈溢出的**防御**
1717
- 在栈帧基础上探索更多有意思的功能,如**协程**
18-
- 从高处思考程序**控制流**的运行
18+
- 从高处思考程序**控制流**的运行机制,探索其发展方向
1919

2020
> [!tip]
2121
>
@@ -28,6 +28,15 @@
2828
> - `b *[address]`:直接在指定地址处设定断点(例如 `b *0x401000`
2929
> - ![设定断点](flowlab/b_gdb.png)
3030
31+
### 实验要求
32+
33+
0. (复读)前排温馨提醒:本实验任务量可能较大,请尽早开始;
34+
1. Problem 需要在实验报告中作答,如有要求需附上截图;
35+
2. Task 需要在实验报告中附上代码,结果截图和**简要**的实验过程;
36+
3. **不应**修改不含 TODO 标记的代码,或添加额外的函数;
37+
4. 欢迎在实验报告中吐槽/建议/记日记(划掉
38+
5. 发挥创造力吧;)
39+
3140
## 一、危险的计算器
3241

3342
### RCE 攻击
@@ -100,7 +109,7 @@ void foo() {
100109

101110
> [!NOTE]Task 1.1 (10 pts)
102111
>
103-
> 你的任务是:利用栈溢出漏洞,控制程序执行 `./malware` 。这个“恶意程序”会检测自己的父进程调用,如果发现自己由 `dark-calc` 调用,就会输出 `You have successfully detonated the bomb! Congratulations!`,表示你已经成功完成了任务。
112+
> 你的任务是:利用栈溢出漏洞,控制程序执行 `./malware` 。这个“恶意程序”会检测自己的父进程调用,如果发现自己由 `dark-calc` 调用,就会输出 `You have successfully detonated the bomb! Congratulations!`,表示你已经成功完成了任务。在实验报告中描述你的攻击流程。
104113
105114
#### 实验步骤
106115

@@ -143,7 +152,7 @@ void foo() {
143152

144153
> [!tip]
145154
>
146-
> cmd 字符串对应地址处的值在输入完后不变。
155+
> 注意:cmd 字符串对应地址处的值在输入完后不变。
147156
>
148157
> 我们的目标类似于执行 `system("./malware")`,如果你已经构造成功了 payload 使程序执行 `system("./malware")`,但程序在 `system` 函数的内部崩溃了,这在我们的预期内。**也就是说,只需要见到 `You have successfully detonated the bomb! Congratulations!` 这一行就算通过实验。**
149158
>
@@ -159,7 +168,7 @@ void foo() {
159168

160169
> [!NOTE]Problem 1.1 (5 pts)
161170
>
162-
> 除了在报告描述你的攻击流程之外,你还需要在报告中回答以下问题:实验任务中导致溢出的函数早就成为了一个臭名昭著的函数,现如今几乎没有人会再使用它。但即使在 2025 年的今天,我们依然会看到许许多多的栈溢出、堆溢出漏洞。请你思考一下,还有什么其他的场景、函数会导致溢出?你自己是否在编程中遇到过栈溢出的情况?
171+
> 实验任务中导致溢出的函数早就成为了一个臭名昭著的函数,现如今几乎没有人会再使用它。但即使在 2025 年的今天,我们依然会看到许许多多的栈溢出、堆溢出漏洞。请你思考一下,还有什么其他的场景、函数会导致溢出?你自己是否在编程中遇到过栈溢出的情况?
163172

164173
## 二、更危险的计算器
165174

@@ -179,7 +188,7 @@ void foo() {
179188

180189
但是存在漏洞,使得我们可以编译出栈空间可执行的程序(参照[这篇文章](https://mp.weixin.qq.com/s/D43kHb5_b0U9EPt_dA4p7g))。
181190

182-
很不幸的是,上述危险的计算器的编译过程存在这样的漏洞,使这个计算器变得更加危险了。这意味着我们可以利用漏洞,在栈空间执行自己编写的简易汇编程序,例如修改一些寄存器的值之后跳转到其他地方。
191+
很不幸的是,我们编译危险的计算器时没有注意到这一点,使这个计算器变得更加危险了。这意味着我们可以在栈空间执行自己编写的简易汇编程序,例如修改一些寄存器的值之后跳转到其他地方。
183192

184193
### 实验任务
185194

@@ -189,23 +198,29 @@ void foo() {
189198

190199
> [!tip]
191200
>
192-
> 可以用与 Task 1.1 相似的方法保存 payload 并进行调试。
201+
> 可以用与 Task 1.1 相似的方法保存 payload 并在 GDB 调试。
202+
>
203+
> GDB 内,默认情况下程序的栈空间位置在**较长时间内**固定;而直接执行程序时,栈空间位置一般是随机的,且与 GDB 内不同。
193204
>
194-
>GDB 中,默认程序的栈空间位置在**一次重启期间**固定。
195205
> 我们需要在栈空间内执行代码,期望效果是**赋值输入参数****调用函数**
196206
>
197-
> 大家学过 CSAPP,打过 BombLab,想必对常用 x86-64 汇编指令的机器码有一些了解,此处给出 mov 和 jmp 指令的机器码参考
207+
> 大家已经学过 CSAPP 中有关汇编与机器码对应的知识点,此处给出 x86-64 汇编指令 mov 和 jmp 指令的机器码形式参考
198208
>
199-
> - `mov $imm, %rxx`64 位立即数移动, 7 字节):`48 c7 [Mod+Reg+R/M](1 byte) [imm](4 byte)`
209+
> - `mov $imm, %rxx`64 位立即数移动, 7 字节):`48` `c7` `[Mod+Reg+R/M]`(1 字节) `[imm]`(4 字节)
200210
> - `Mod` 指定寄存器模式(2 位,`11` 为寄存器寻址)
201211
> - `Reg` 源操作数(3 位,这里是立即数,所以置为 0
202212
> - `R/M` 指定目标寄存器(3 位);
203-
> - `jmp *%rxx` (跳转到 `rxx` 寄存器指向的地址, 2 字节):`ff [Mod+Reg+R/M](1 byte)`
213+
> - `jmp *%rxx` (跳转到 `rxx` 寄存器指向的地址, 2 字节):`ff` `[Mod+Reg+R/M]`(1 字节)
204214
> - `Mod` 指定寄存器模式(2 位,`11` 为寄存器寻址)
205215
> - `Reg` 设为 `100` 指定此指令为 `jmp` 指令(3 位,此处代表指令模式选择值)
206216
> - `R/M` 指定目标寄存器(3 位);
207217
>
208218
> <s>善用人工智能工具编写汇编/机器代码(逃</s>
219+
>
220+
> 样例截图:
221+
>
222+
> ![祝大家门门拿 A](flowlab/task2-1.png)
223+
>
209224

210225
## 三、栈溢出的防御
211226

@@ -232,17 +247,23 @@ gcc -fno-pie -no-pie -o dark-calc-my dark-calc.c
232247
233248
> [!NOTE]Problem 3.2 (5 pts)
234249
>
235-
> 尝试根据资料复原出之前实验中 `dark-calc` 的编译指令。
250+
> 尝试根据线索复原出之前实验中(漏洞百出的) `dark-calc` 的编译指令。
236251
237252
> [!tip]
238253
>
239254
> 通过**特定命令行参数**,可以不开启防御机制;
240255
>
241-
> 为触发可写栈空间漏洞,编译时包含了额外文件,不仅包含 `dark-calc.c`
256+
> 为触发可写栈空间漏洞,编译时包含了**额外文件**(在哪呢
242257
243258
## 四、栈帧的更多应用——协程
244259

260+
>[!tip]
261+
>
245262
> 改编自 2024 StackLab 的第三部分(源于 2022 年 Kieray Lab),减少协程部分的代码工作量,替换为阅读思考题。
263+
>
264+
> 往届 TA 在 `coroutine` 文件夹中留下了 `QA.md` 作为常见问题 QA。
265+
>
266+
> (此次不用亲自实现如此多的功能,不过对理解有帮助)
246267
247268
在前两项任务中,我们已经加深了对程序运行时的栈帧的认识,接下来,我们使用栈帧和一定的汇编语言,来给 C 语言实现一些更加现代的功能吧。
248269

@@ -357,7 +378,7 @@ funcB:
357378

358379
> [!NOTE]Problem 4.4 (2 pts)
359380
>
360-
> 在实验报告中填写你的答案:假如变量 x 被存放在栈帧上,在 restore 操作后,x 的值为 ________________ ;假如变量 x 被存放在寄存器上,在 restore 操作后,x 的值为 ________________
381+
> 在实验报告中填写答案:假如变量 x 被存放在栈帧上,在 restore 操作后,x 的值为 ________________ ;假如变量 x 被存放在寄存器上,在 restore 操作后,x 的值为 ________________
361382
362383
由于变量放在寄存器还是内存是由编译器决定的,根据编译器策略的不同,可能会导致同一份代码产生不同的运行结果。为了简化问题,我们可以做出如下限定:在 save 语句后修改过的局部变量,在 restore 操作后都是未知的,让开发者不要在 restore 之后直接使用这些变量的值。
363384

@@ -396,7 +417,7 @@ naive_func(void **p):
396417
>
397418
> 也许你在课上学过函数开头两条指令的固定格式 `push rbp; mov rbp, rsp`。但是前面所写的 naive_func 显然不遵循这样的格式,为什么这是可以的呢?
398419
399-
接下来,我们开始着手实现 save 和 restore 函数,为了实现更多后续功能,这两个函数的定义与上文所述有略微不同,请参见 API 手册
420+
接下来,我们开始着手实现 save 和 restore 函数,为了实现更多后续功能,这两个函数的定义与上文所述有略微不同,请参见 API 文档(coroutine-api.md)
400421

401422
> [!NOTE]Task 4.1 (8 pts)
402423
>
@@ -561,11 +582,15 @@ funcB:
561582
562583
> [!NOTE]Problem 4.7 (5 pts)
563584
>
564-
> 请阅读 `context.c` 中的函数 `send``yield``back_to_reality``context.h` 中对 `try``catch``throw` 的宏定义,并在报告中解释这些函数和宏定义的功能。
585+
> 请阅读 `context.c` 中的函数 `send``yield``back_to_reality`以及 `context.h` 中对 `try``catch``throw` 的宏定义,并在报告中解释这些函数和宏定义的功能。
565586
566587
> [!NOTE]Problem 4.8 (5 pts)
567588
>
568-
> 任选 test6、test7、test8 中的一个,使用 GDB 动态调试,运用 `x/10gx $rsp` 指令查看至少两种不同位置处开始的栈帧或是伪栈帧并截图,体会协程中开辟虚拟栈空间的设计。
589+
> 任选 test7、test8 中的一个,使用 GDB 动态调试,运用 `x/10gx $rsp` 指令查看默认栈帧,和协程产生的伪栈帧,体会协程中开辟虚拟栈空间的设计。
590+
>
591+
> 在报告中提交截图。
592+
>
593+
> - 参考 test6 的实验现象:![栈帧和伪栈帧](flowlab/problem4-8.png)
569594
570595
### 协程的一些实际应用
571596

@@ -600,7 +625,7 @@ def game():
600625
>
601626
> 基于上面的讨论,请你完善 `main.c` 中的 `progress_bar` 函数,实现一个自定义的进度条动画。发挥你的想象力即可。
602627
603-
![进度条](flowlab/task3_result.gif)
628+
![进度条](flowlab/coroutine_result.gif)
604629

605630
## 五、控制流和栈帧的进一步思考
606631

@@ -731,6 +756,8 @@ def game():
731756
> 长崎·raise: 要怎么做才能回来?只要是我能做的,我什么都愿意做!
732757
>
733758
> 丰try·祥子: 你这个人,满脑子都只想着自己呢。
759+
>
760+
> ![你这个人,满脑子都只想着自己呢](flowlab/try_raise.png)
734761
735762
和其它 lab 的评分标准相同,除去 Honor Part 的内容满分为 100 分,Honor Part 只能用来抵前面报告的扣分和迟交得分。Lab 的分数上限仍为 100 分。
736763

@@ -785,7 +812,7 @@ int main() {
785812
## 参考资料与鸣谢
786813
787814
- CMU 原版 [Attack Lab](http://csapp.cs.cmu.edu/3e/labs.html)
788-
- 2022年 Kieray Lab,作者 @[虎鲸](https://github.com/zzzly3)
789-
- 本实验参考 2024 年的 StackLab 实验开发,鸣谢24 Fall TA:@[y<sup>2</sup>](https://github.com/Cameudis)、@[Yosame](https://github.com/Yosame08)
815+
- 2022 Kieray Lab,作者 @[虎鲸](https://github.com/zzzly3)
816+
- 本实验参考 2024 年的 StackLab 实验开发,鸣谢 2024 Fall TA:@[y<sup>2</sup>](https://github.com/Cameudis)、@[Yosame](https://github.com/Yosame08)
790817
791818
> 负责助教:周弈成 @[JurFal](https://github.com/JurFal) 朱程炀 @[Zecyel](https://github.com/Zecyel)

0 commit comments

Comments
 (0)