Hackergame 2022 Writeup
Last updated on 2022-10-31, Mon, 01:47 AM
a.k.a 水银 2022 7-Day Trial
说了只做签到,然后心痒痒,就想着继续做吧。
然后发现我啥都不会,就是个跳梁小丑,真是丢人现眼。
部分吐槽见源码中注释掉的部分。
签到
先随便提交一次,然后会蹦出错误
注意 URL 变化,修改 ?result=????
为 ?result=2022
成功
举办猫咪问答喵谢谢喵(猫咪问答)
***,真难找,我只找到三个 upd:六个答案已经都搞到了。
- 搜了一下 Google 上的结果,第一次出现这个战队是在 https://cybersec.ustc.edu.cn/2019/0624/c15751a387753/page.htm , 但这并没有什么用。然后估计一下也不可能在 2012 年以前成立,那就和第六问一样,把答案枚举出来就行,反正最多才 96 种可能,连第六问都不如(
- 在 https://lug.ustc.edu.cn/wiki/lug/events/sfd/ 找到 陶柯宇 闪电演讲:《GNOME Wayland 使用体验:一个普通用户的视角》 slide 第 15 页,应该就是我们要找的程序。看起来似乎是一个影视后期处理软件,而且提到是 KDE 程序,那就前往 https://apps.kde.org/ 看看。好像有个叫 Kdenlive 的,一看长得一模一样,那就是了。
- 直接翻译成英文搜,得到最后的大版本是 12.
- 在 https://github.com/torvalds/linux.git 网页左上角的搜索框里输入
CVE-2021-4034
, 选择 “in this repository” 即可得知唯一符合的 commit hash 为dcd46d897adb70d63e025f175a00a89797d31a43
- 提示说是 1996 年注册的域名,而且有且只有六个字母,就想到 Z 佬的 GPG uid 里有个 sdf.org 的号,结合当时和群友聊到这个站的历史和会员的难以获取,就瞎猜了一个 sdf.org 居然对了
浅浅找了下妮可网络通的内容也只有 https://netfee.ustc.edu.cn/faq/index.html#fee , 然后在 wayback machine 上也没有找到 2012 年以前的记录。心一冷,直接谷歌搜 “网络通 ustc” 然后把时间调到 2009-01-01 和 2011-01-01 之间。好家伙,给我碰上了 https://www.ustc.edu.cn/info/1057/4931.htm . 其中提到的 “网字〔2003〕1号《关于实行新的网络费用分担办法的通知》” 没法在公网搜索引擎上找到了,似乎。
想到大狐狸苏卡卡酱以前打 hg 的绝招,我也来试试枚举吧,拿着做 Xcaptcha 时候写的机器人改两笔就行了。从 2003-01-01 到 2003-12-31 总共才 365 个可能,这种数据规模还不到市面常见 CC 攻击的零头。
偷家(家目录里的秘密)
解压,得到 user
家目录。然后用 vscode 打开文件夹,直接搜索 “flag”.
Vscode
搜索结果中有一个 “DUGV.c”, 注释第五行可以看到 flag.
Rclone
在 user/.config/rclone/rclone.conf
出现 “flag2”, 其中有被 obscure 过的 pass.
搜谷歌的时候发现了提到这个 playground 的帖子,改掉 YOUR PSEUDO-ENCRYPTED PASSWORD HERE
就能得到结果。
考虑到原链接随时可能失效,拷贝程序源码如下:
真甜(Heilang)
直接替换 |
为 ]=a[
难看,但这 py 语法葡萄糖真甜,除杂都省了,直接饮用(
我是机器人(Xcaptcha)
上来就跳转是怎么回事?草
手速拉满,然后开了 noscript 终于不跳了,总算看到了里面有个一秒就提交的 <script>
, 还有一个 <form>
用来放三个计算题。但还是没啥用,1 秒的限制在后端也有。
那就干脆 py request 模拟,这样够 bot 了吧(
然后我一个根本不会写代码的,开始搭建 python 危房。
三个计算题包装在 <label>
中,格式如下:
掏出正则模拟器随便糊个表达式,用 Match Group 把那俩数字拎出来。
然后转换格式、计算、送走(
访问题目时需要使用 cookie, 也即填写此处 session
的值。用浏览器开一下题目,F12 就能拿到,顺便随手交一次看下 form 格式。
完整代码如下:
搞定,成功证明自己是 bot.
果然 bot 的活还是得交给 bot, 想到最近的 AI 画画,心情复杂((
woc 恶俗啊(旅行照片 2.0)
照片分析
用 gwenview 或者 jhead -v
得到 exif 信息
社工实践
放大照片,可看见前方的圆形建筑有字 ZOZOMARINE STADIUM 和 CHIBA LOTTE MARINE. 搜索后可知与“千葉海洋球場”有关。从拍摄角度能推测拍摄者所在建筑相对于球场的方向,顺带对比图中的道路,估计其位于 APA度假飯店東京灣幕張 ,邮政编号 261-0021.
已知该机器是小米的,搜索 gsmarena 对比各代机型猜测为 Redmi 9T, 屏幕分辨率 2340x1080.
航班的话,观察照片中飞机的姿态,结合拍摄者所在位置和拍摄角度,判断这架飞机大致是朝北方飞行。尚能目视,那么高度不算太高。且附近也没有其他飞机。
想回溯那么久以前的航班只能靠 flightradar24 了。先骗个 7-day gold trial, 然后回溯一下照片拍摄时的空域情况。注意,exif 中还有时区信息 +0900, 之前的时间是当地时间,需要换算成 UTC. 调至 2022-05-14 09:23:35 UTC 不难得知航班为 NH683 (HND -> HIJ)
拿到 flag, 别忘了把 gold subscription 取消掉
胶衣 PLAY(LaTeX 机器人)
纯文本
咕咕搜索 “Latex include other file in the file system”
然后在这里看到了大佬们的指点。于是:
然后输出了第一个 flag. 记得补上花括号。
特殊字符混入
混进去的两个都是 escape char, 一时有点头大。
搜了 regex, 没有;搜到 verbatim, 不行。
脚本里面有 -no-shell-escape
没法干坏事。真麻了。
在搜 escape char 的时候,摸到 \catcode
这个东西。心灰意冷之下试了试居然能用。
又在学习胶衣基本语法的时候看到了 \\ 的用法。拿出来试了下还真能用,那就可以在 form data 里面塞入多行内容了。
那就好办了。
把 #
和 _
的 catcode 改成 12 就行了。
补上花括号,搞定。
垃圾运维(Flag 的痕迹)
又没什么登录的线索,只好简单学习了一下 dokuwiki 的官方 wiki, 发现除了 revision 还有 diff 这个好东西。
在 URL 末尾追加 &do=diff
即可打开 diff 页面,然后就能查看修改历史了。
工程1.psd(线路板)
大概是个 gerber file.
用 gerbv 导入所有设计图,逐个查看后发现 ebaz_sdr-F_Cu
好像有类似 flag 的玩意印在上面,后面被一些东西挡住了。鼠标选中直接删掉就能看到 flag.
黑色高级自动机(Flag 自动机)
随便 HexDump 一下就能看见好多 flag, 可那有什么用呢,又不是真的 flag, 旁边还有神户小鸟(Kanbe_Kotori)呢((
不过有个提示,好像说不需要直接啃 flag, 看来还得骗出来才行?
首先尝试运行,“残忍夺取”的按钮居然会躲着鼠标走,实在是很有上古时代恶搞程序的感觉了。
打开 IDA 按一下 F5, 主程序的入口应该在 _WinMain@16_
处,在里面翻了一圈以后发现 pfnSubclass
里面的东西有点像是按钮乱飞的罪魁祸首。
直接看汇编的话,长这样:
触发这玩意的条件是 uMsg == 512
. 搜了一下,似乎是一种叫做 windows message 的玩意,在 winehq 上有比较完整的取值列表。查表,看起来真的是鼠标移动触发,那就删掉吧。
咋办呢?看了下汇编代码,把成立条件改成 uMsg==0
就好了。
(.text.00401963) 00000D63: 02 -> 00
改完以后
IDA patch 改起来太慢,干脆用 HxD 改完开跑,按钮确实不飞了。
接下来就是骗 flag 了。把 flag 骗出来主要靠 sub_401510
函数。想要到达输出 flag 的程序段需要经过三次 if. 第一次是根据 Msg
也即上文的 uMsg
, 第二次是 a3
, 第三次是 lParam
.
要素给的很到位捏,意义是无意识:
汇编长这样:
再次按下按钮准备残忍夺取 flag, 怎料突然弹出窗口,说我不是“超级管理员”。窗口大小很接近 300x100, 看来 sub_401510
函数里面的 Msg
是 1 了,那就直接把第二处比较的数字从 111h 改成 1 就行,反正最后一个 case 分支没有跳转入口。
(.text.00401523) 00000923: 11 -> 01
(.text.00401524) 00000924: 01 -> 00
再次尝试进去的时候窗口空白,从逻辑关系图看,大概是进了 nop
了,至少 a3
不等于 2. 那就试着改下跳转条件吧,改成 a3==3
才跳走(jz
),这样就能继续执行对 lParam
的判断,以及到 loc_401840
的跳转了:那是 flag 的所在。
(.text.00401800) 00000C05: 85 -> 84
看起来没啥问题,大不了回头再改。
至于 lParam
显然不可能是那么臭的数字,直接改成 lParam!=114514
跳走(jnz short
)。
(.text.00401811) 00000C11: 74 -> 75
改出来效果大概就是这样:
然后成功了,与预期一致的祝贺消息框以及输出的 flag_machine.txt. 打开一看,应该不会是假 flag. 骗到了。
当时没有在强行逆向解码函数的路上走太远…准确说,看见里面的某个不确定数组以后就放弃了,没想到真能单独拿出来跑。
XSS 好难,想死死(微积分计算小练习)
从 bot 的代码来看,flag 就在 cookie 里面。只要拿到 cookie 就行了。
先是想往 return 的结果里面下毒,显然没成。
然后一直没思路,倒数第二天晚上终于想到,既然是想执行代码,那就考虑 XSS, 可是自己也不会 XSS 啊,对 js 也是一窍不通;不过看了一下里面的代码,搜了一下,判断出分享链接里的 result 只是把 score:name
编码成 base64, 再次打开时则会解码,得分和名字用冒号切开,然后用 document.querySelector().innerHTML
去替换对应元素里面的内容。
那就可以直接构造了,把想要植入到 HTML 里面的内容按照格式写好编码就行。数字在前,那就尽可能只改 name.
一开始是想直接放个 script 去改变量、改网页,然后但是发现换进去的 inline script 根本没被执行,后来才知道 script 的执行也有顺序。
另外发现如果 base64 字串里面出现 +
就会让服务器 500. script 直接丢进 query string 好像也会 500.
然后想往里面塞 img, 把 cookie 放在 URL query string 里面偷走,然后用自己的服务器去收,结果发现死在同样的问题上,如果要把变量塞进 src link 里面就要用 script, 但是用 script 就要面对执行顺序的问题。
心灰意冷之下搜了 “innerhtml inject javascript”, 找到了 StackOverFlow 帖子 Executing <script> elements inserted with .innerHTML
里面的一个回答。简单说就是用一个 img 元素在 onload 的时候执行 js 代码。这样就会等到后面的 script 把元素替换好以后才开始执行代码。
那就很简单了,直接把整个 greeting 换成 cookie 就行了。
还是半天都不行,然后 F12 发现 document.querySelector("#greeting")
的第一个双引号后面居然被加了空格…从高亮来看似乎是和 onload 的双引号冲突了… escape char 也无效。
真麻了,凭着自己以前折腾博客的经验,大概试了一下用单引号去换,设置成 0 分是防止出现加号。分数可以随意设置,当时要是早点意识到的话,就不用亲自算那五道题目了(
base64 以后,补全 path
成了。
然后丢进 web shell, 得到的 greeting 就变成 cookie 的内容,也就是 flag 了。
好难,想死。
这酒有毒(杯窗鹅影)
flag1
手生了不会写 C 了,那就直接搜一下 C 语言怎么读文件吧(
https://www.geeksforgeeks.org/c-program-to-read-contents-of-whole-file/
直接跑,然后 server 会绝赞报错。
然后发现 do-while 会把 EOF 也输出到 stdout, 那避免掉就行。
没想到这 150 分就和白给一样。然后 flag2 就卡住了
浇窝 WebGL 好不好嘛(光与影)
折腾了半天也不是很懂。
网页结构很简单,很适合在本地跑,我也确实是这样做的。咱猜是要修改那四个 js.
WebGL 确实也看不大懂,搜了下里面的函数名字,大概是用光线追踪写的玩具。
但里面最让我感到奇怪的就是五个 SDF. 前四个那么大那么沉,而最后那个又那么短,结合图像中固定的 flag 字样,还有那个模糊的后半段,很难不联想到前四个 SDF 就是把字母画出来,最后那个负责画一个矩形挡住 flag.
看了下只有 sceneSDF
中调用过这五个函数。
直接把其中的 t5 被赋值/调用的地方改成随便一个浮点数(比如 1e1 之类的常量,或者其他 float 变量)就行了。
重新渲染,就能看到 flag 了。
数数(企鹅拼盘)
这么简单我闭眼都可以
枚举,从 0000 开始试,试到 1000 碰上了,成功。
写在最后
最近发生的事情对我打击还是挺大的,一直摆烂得很,也不知道发了什么疯来碰 hg.
这应该是咱这辈子第一次打 CTF, 没有想到自己真的能拿到除了签到以外的那么多分数。
只不过大部分都是 misc 和 web 的雕虫小技,没啥科技含量,窝基本是靠着 Google 一路走过来的,而且 Google 用得也很差(你看这题解写得多稀烂);binary 和 math 也没怎么碰。虽然也学到了不少细碎的知识,却感觉还是没啥提升。看完官方题解才意识到我的认知还是太狭隘了,真得从头恶补才行。
遗憾的是自己还是太麻木,把猜数字、OJ、轮盘赌和杯窗鹅影这几题给放掉了,本来是很好的一个学习 C 和 Linux 的机会。好在平台还会继续运行三个月,还可以慢慢折腾那些好玩的题目。
也更强烈地意识到几件事情:
- 有什么想法就要大胆地记录或者投入实践。
- 自己的思维高度还是不及大佬们,应当继续学习。
- 基础不牢地动山摇,该恶补了。
但是为了解题而紧张的感觉已经很久没有过了。打下一题就写一题的 wp 也很有成就感。
中午 12 点 wp 解禁的时候,竟有种如释重负的感觉。
打 hg 的时候就仿佛在吸电子鸦片。
和群友们讨论时,简直是在 ToS 边缘疯狂试探,还能因为各种趣事而狂笑不止。
课都不上了 就想着打 hg 了
感觉 hg2022 大概是咱未来这段时间里最充实的时刻了
最后,感谢在幕后为这次 Hackergame 作出贡献的 staff 们,把这么棒的比赛呈现给了我们。
明年也会继续来玩的!