Skip to content

Commit 0b257c7

Browse files
authored
Merge pull request #51 from tkmikan/master
add tkmk's unintended solution for cybercook
2 parents 7dc9ba1 + 592a238 commit 0b257c7

File tree

4 files changed

+37
-0
lines changed

4 files changed

+37
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
| [lyq1996](players/lyq1996/README.md) | 总排名第 109, [blog](https://lyq.blogd.club/2021/10/31/hackgame-2021-wp/) | 助力、Amnesia轻度失忆、Amnesia重度失忆、只读文件系统、catchGPA |
9595
| [lxdlam](players/lxdlam/README.md) | 总排名第 67,[blog](https://blog.lxdlam.com/post/f37e3945/) | 签到、进制十六——参上、去吧!追寻自由的电波、猫咪问答 Pro Max、卖瓜、透明的文件、旅行照片、FLAG 助力大红包、Amnesia、图之上的信息、Easy RSA、加密的 U 盘、赛博厨房(Level 0、Level 1)、助记词(第一顿大餐)、Co-Program(Co-Login)|
9696
| [Vifly](https://viflythink.com/Hackergame_2021_writeups/) | | 签到,进制十六——参上,猫咪问答 Pro Max,卖瓜,Amnesia (轻度失忆),图之上的信息,加密的 U 盘,赛博厨房(LEVEL 0、LEVEL 1) |
97+
| [tkmk](players/tkmk/) | 总排名第 9 名 | 赛博厨房(LEVEL 3 非预期) |
9798

9899
## 其他资源
99100

players/tkmk/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Writeup
2+
周四下午之后因为各种原因 AFK 了,等有空再回来的时候,大家已经陆续在分享各自的 writeup 了。阅读了一下**赛博厨房** Level 3 的官方题解、以及另外两位 dalao mcfx & 4qwerty7 的题解(膜拜),发现自己做是**非预期**,于是也记录分享一下。
3+
### 赛博厨房
4+
Level 0 和 1 我的做法和大家类似。在解 Level 2 时,我从 js map 恢复了前端代码,对题目生成随机种子和菜谱的方法进行了分析。抓包测试发现后端并不会对每一条程序进行合法性分析,于是我选择的是类似官方题解的方法,但是只生成 127 条固定的程序,最后一条直接枚举爆破递增的数字,就等菜谱落到我会做的范围。个人感觉不用修改程序容易一些,它们的 hash 也不用重复计算。
5+
至于 Level 3,爆破肯定是不可行的。鉴于本题在前端使用 TypeScript 封装了大量的模型和方法,推测前后端可能存在代码复用,即后端也使用的是 NodeJS。那么会不会存在一些类型上的问题呢?
6+
7+
让我们来以 Level 1 为例,看一下提交答案的请求:
8+
9+
![](./images/1.png)
10+
11+
后端读取要执行的程序,大概是类似这样的代码:`req.body.programs[req.body.executions[0]]`
12+
13+
现在试试把 `programs` 从数组改成对象:
14+
15+
![](./images/2.png)
16+
17+
后端没有报什么大错,反而是非常贴心地告诉我们 seed 不对。把请求中的 seed 修正之后,顺利得到 Level 1 的 flag。
18+
19+
这个 `e3b0...` 是哪里来的呢?搜一下就能发现,它是空字符串的 sha256。看一下前端的计算方法就知道了:
20+
21+
```typescript
22+
public getInstrsHashes(programs: Array<string>) {
23+
let hashes = [];
24+
for (let i = 0; i < programs.length; i++) {
25+
const content = programs[i].trim();
26+
const hash = CryptoJS.SHA256(content).toString(CryptoJS.enc.Hex);
27+
hashes.push(hash);
28+
}
29+
let hashesConcat = hashes.join('\n');
30+
return CryptoJS.SHA256(hashesConcat).toString(CryptoJS.enc.Hex);
31+
}
32+
```
33+
34+
现在 `programs` 是个对象,`programs.length``undefined``0<undefined`为假,于是并不会进入循环,最后一次 sha256 的输入就是空串。(当然乐意的话也可以给 `programs` 随意加个 `length`
35+
36+
有了固定的 seed,意味着固定的菜谱,后面怎么做就不用多说了吧。

players/tkmk/images/1.png

244 KB
Loading

players/tkmk/images/2.png

266 KB
Loading

0 commit comments

Comments
 (0)