diff --git a/official/生活在博弈树上/README.md b/official/生活在博弈树上/README.md index 347d1f4..3378ff5 100644 --- a/official/生活在博弈树上/README.md +++ b/official/生活在博弈树上/README.md @@ -1 +1,36 @@ # 生活在博弈树上 + +很明显这道题题面是根据 2020 年浙江的满分高考作文《生活在树上》魔改而来的,没有任何逻辑性可言的版本。打开题目后,就会发现它其实是一个井字棋,并且在算法(Minimax)实现正确的情况下,后手的人类是赢不了先手的电脑的。 + +既然是信息安全大赛,那肯定要用信息安全的思路去解题。如果用 CTF 的方式去分类的话,这应该算是一道典型的简单 pwn 题了。 + +## 始终热爱大地 + +打开源代码读过代码,我们就能轻易发现一个很危险的信号: + +```c +printf("Your turn. Input like (x,y), such as (0,1): "); +gets(input); +x = input[1] - '0'; +y = input[3] - '0'; +``` + +尽管很多初学 C 语言的同学会使用 `gets()` 去读取一行字符串(至少我所观察到很多没有编程基础初学 C 语言的大一新生会这么做),但是这个函数是非常危险的:它不会限制输入的长度,可以构造出长度大于接受输入的数组长度的字符串,从而实现一些“意料之外”的事情。 + +为了获得第一个 flag,我们的目标是让程序运行 `success` 分支,输出 flag。正常下井字棋是肯定赢不了的(除非我代码写错了 :)),那么我们就需要在程序运行时想办法让 `success` 的值变为 `true` (1),然后就能立刻跳出 `while` 循环而胜利。可以注意到,在变量定义的时候,`success` 就贴在 `input` 数组的旁边。 + +```c +bool success = false; // human wins? +char input[128] = {}; // input is large and it will be ok. +``` + +那么我们能不能在 `gets` 的时候,就把 `success` 弄成 `true` 呢?答案是可以的! + +[TBD] + + +## 升上天空 + +第一题的 flag 提示我们要 getshell 得到第二个 flag。使用 `checksec` 检查程序文件。 + +[TBD] \ No newline at end of file