SUCTF 2025

SU_checkin和SU_BBRE这两题都出了大半,但还是差了点,参考wp来复现一下,Pwn题等有时间也复现一下。

WriteUp

Misc

SU_RealCheckin

1
2
3
hello ctf -> 🏠 🦅🍋🍋🍊 🐈🌮🍟

$flag -> 🐍☂️🐈🌮🍟{🐋🦅🍋🐈🍊🏔️🦅_🌮🍊_🐍☂️🐈🌮🍟_🧶🍊☂️_🐈🍎🌃_🌈🦅🍎🍋🍋🧶_🐬🍎🌃🐈🦅}

仔细观察发现 flag 是每个图标的首字母

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
🐍->snake   ->s
☂️->umbrella->u
🐈->cat ->c
🌮->taco ->t
🍟->fry ->f
🐋->whale ->w
🦅->eagel ->e
🍋->lemon ->l
...
🍊->orange ->o
🏔️->mountain->m
...
🧶->yarn ->y
...
🍎->apple ->a
🌃->night ->n
...
🌈->rainbow ->r
...
🐬->dolphin ->d

suctf{welcome_to_suctf_you_can_really_dance}

SU_checkin

流量分析,直接搜索 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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
GET /download?filename=../../../../../../../../../root/flag.txt HTTP/1.1
Host: 192.168.58.128
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

HTTP/1.1 200
Content-Disposition: attachment; filename="../../../../../../../../../root/flag.txt"
Content-Type: application/octet-stream
Content-Length: 7
Date: Thu, 09 Jan 2025 06:59:21 GMT
Keep-Alive: timeout=60
Connection: keep-alive

nonono
GET /download?filename=../../../../../../../../../proc/self/cmdline HTTP/1.1
Host: 192.168.58.128
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

HTTP/1.1 200
Content-Disposition: attachment; filename="../../../../../../../../../proc/self/cmdline"
Content-Type: application/octet-stream
Content-Length: 65
Date: Thu, 09 Jan 2025 06:59:26 GMT
Keep-Alive: timeout=60
Connection: keep-alive

java.-jar.suctf-0.0.1-SNAPSHOT.jar.--password=SePassWordLen23SUCTGET /download?filename=../../../../../../../../../root/start.sh HTTP/1.1
Host: 192.168.58.128
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

HTTP/1.1 200
Content-Disposition: attachment; filename="../../../../../../../../../root/start.sh"
Content-Type: application/octet-stream
Content-Length: 1
Date: Thu, 09 Jan 2025 06:59:32 GMT
Keep-Alive: timeout=60
Connection: keep-alive


GET /download?filename=../../../../../../../../../proc/self/cwd/BOOT-INF/classes/hint HTTP/1.1
Host: 192.168.58.128
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

HTTP/1.1 200
Content-Disposition: attachment; filename="../../../../../../../../../proc/self/cwd/BOOT-INF/classes/hint"
Content-Type: application/octet-stream
Content-Length: 27
Date: Thu, 09 Jan 2025 06:59:38 GMT
Keep-Alive: timeout=60
Connection: keep-alive

algorithm=PBEWithMD5AndDES
GET /download?filename=../../../../../../../../../etc/shadow HTTP/1.1
Host: 192.168.58.128
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

HTTP/1.1 200
Content-Disposition: attachment; filename="../../../../../../../../../etc/shadow"
Content-Type: application/octet-stream
Content-Length: 909
Date: Thu, 09 Jan 2025 06:59:43 GMT
Keep-Alive: timeout=60
Connection: keep-alive

root:$6$MI.uuGSS7qKn4rEK$NlYB/kaAeRmd3CYY4mxDuMMMh1PzQZHTEL.BV3Dosp.15kD3MgSDzqbYRRazeglIRVAfe6ATwRZ9ekSwNTkit0:20077:0:99999:7:::
daemon:*:20007:0:99999:7:::
bin:*:20007:0:99999:7:::
sys:*:20007:0:99999:7:::
sync:*:20007:0:99999:7:::
games:*:20007:0:99999:7:::
man:*:20007:0:99999:7:::
lp:*:20007:0:99999:7:::
mail:*:20007:0:99999:7:::
news:*:20007:0:99999:7:::
uucp:*:20007:0:99999:7:::
proxy:*:20007:0:99999:7:::
www-data:*:20007:0:99999:7:::
backup:*:20007:0:99999:7:::
list:*:20007:0:99999:7:::
irc:*:20007:0:99999:7:::
gnats:*:20007:0:99999:7:::
nobody:*:20007:0:99999:7:::
_apt:*:20007:0:99999:7:::
systemd-timesync:*:20077:0:99999:7:::
systemd-network:*:20077:0:99999:7:::
systemd-resolve:*:20077:0:99999:7:::
messagebus:*:20077:0:99999:7:::
sshd:*:20077:0:99999:7:::
hacker:$6$rzdplO02wm/607Io$v9gjdKBiuEdA0F28qx1REs/L4Qo9dqBQD.fUUjans5qn/sWOjSffHWzlMvgwzxHyyrfSA8kLilzMMRGhRNHLk0:20077:0:99999:7:::
GET /download?filename=../../../../../../../../../proc/self/cwd/BOOT-INF/classes/application.properties HTTP/1.1
Host: 192.168.58.128
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

HTTP/1.1 200
Content-Disposition: attachment; filename="../../../../../../../../../proc/self/cwd/BOOT-INF/classes/application.properties"
Content-Type: application/octet-stream
Content-Length: 133
Date: Thu, 09 Jan 2025 06:59:47 GMT
Keep-Alive: timeout=60
Connection: keep-alive

spring.application.name=suctf
server.port = 8888
OUTPUT=ElV+bGCnJYHVR8m23GLhprTGY0gHi/tNXBkGBtQusB/zs0uIHHoXMJoYd6oSOoKuFWmAHYrxkbg=
GET /download?filename=../../../../../../../../../etc/passwd HTTP/1.1
Host: 192.168.58.128
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

HTTP/1.1 200
Content-Disposition: attachment; filename="../../../../../../../../../etc/passwd"
Content-Type: application/octet-stream
Content-Length: 1322
Date: Thu, 09 Jan 2025 06:59:53 GMT
Keep-Alive: timeout=60
Connection: keep-alive

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:101:101:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
systemd-network:x:102:103:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:103:104:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:104:106::/nonexistent:/usr/sbin/nologin
sshd:x:105:65534::/run/sshd:/usr/sbin/nologin
hacker:x:1000:1000::/home/hacker:/bin/bash

综合一下,有一个 flag.txt,但是没有 flag;还有一个 hint 是PBEWithMD5AndDES 算法,密文和密码也可看出来,密文是 OUTPUT 的内容,密码在 cmdline 中。

1
2
3
4
OUTPUT=ElV+bGCnJYHVR8m23GLhprTGY0gHi/tNXBkGBtQusB/zs0uIHHoXMJoYd6oSOoKuFWmAHYrxkbg=
password=SePassWordLen23SUCT

algorithm=PBEWithMD5AndDES

当时想着是PBEWithMD5AndDES 算法,然后去找脚本…就卡住了。实际上 password 是 23 位,但是只给出了 19 位,所以需要爆破4位密码(可以猜一个 F,然后变成爆破3位)。

借用一下 S1uM4i 战队的脚本

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
from Crypto.Util.number import *
from Crypto.Cipher import DES
from hashlib import md5
from base64 import b64decode
from tqdm import tqdm
from itertools import product
password = b"SePassWordLen23SUCTF"

OUTPUT = b"ElV+bGCnJYHVR8m23GLhprTGY0gHi/tNXBkGBtQusB/zs0uIHHoXMJoYd6oSOoKuFWmAHYrxkbg="
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/{}_-"
enc = b64decode(OUTPUT)

salt = enc[:8]
enc = enc[8:]
s = product(alphabet, repeat=3)

for a, b, c in tqdm(s):
key = password + (a+b+c).encode() + salt
for i in range(1000):
key = md5(key).digest()
cipher = DES.new(key[:8], DES.MODE_CBC, iv = key[8:])
dec = cipher.decrypt(enc)
if b'SUCTF{' in dec or b'suctf{' in dec:
print(dec)
print(a+b+c)
exit()

Reverse

SU_BBRE

使用 ai 还原为 C语言代码(做的时候没想到还原 C,跑出来第一部分跟第三部分,没意识到缺了第二部分)

main 函数调用 function2 函数进行加密,实际上是进行 rc4 加密并且对比了 16 个字符;之后调用了 function0 函数,但是我们看到 function1 函数中也有对比的了逻辑,实际上是通过 strcpy 来溢出,从而进入了 function1 中,function1 函数进行一个简单的输入比对。

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

// Function declarations
void function0(char *src);
void function1();
void function2(char *input);
void function3(char *key, int key_len, char *s_box);
void function4(char *s_box, char *input, int input_len);
void function5(char *key, int key_len, char *input, int input_len);

// Main function
int main(int argc, char **argv, char **envp) {
char src[100];

printf("please input your flag:");
scanf("%19s", src);

function2(src);
function0(src);

return 0;
}

// Function0: Copies the input string to a destination buffer
void function0(char *src) {
char dest[4];
strcpy(dest, src);
}

// Function1: Checks the input against a hardcoded string
void function1() {
// Hardcoded byte array for comparison
unsigned char expected_bytes[] = {
0x41, 0x6D, 0x62, 0x4D,
0x53, 0x49, 0x4E, 0x29,
0x28
};

// Buffer to store user input
char user_input[9]; // 8 characters + 1 for null terminator

// Prompt the user for input
puts("hhh,you find me:");
scanf("%s", user_input); // Read up to 8 characters to avoid buffer overflow

// Check if the input matches the expected bytes
for (int i = 0; i < 9; i++) {
if ((user_input[i] - i) != expected_bytes[i]) {
// If any byte doesn't match, exit the program
exit(0);
}
}

// If all bytes match, print success message and exit
puts("congratulate!!!");
exit(0);
}

// Function2: Checks the input against a hardcoded byte array
void function2(char *input) {
// Hardcoded byte array for comparison
unsigned char expected_bytes[] = {
0x2F, 0x5A, 0x57, 0x65, // "/ZWe"
0x14, 0x8F, 0x69, 0xCD, // Some bytes
0x93, 0x29, 0x1A, 0x55, // Some bytes
0x18, 0x40, 0xE4, 0x5E // Some bytes
};

// Call function5 to process the input
function5("suctf", 5, input, 16);

// Compare the processed input with the expected bytes
for (int i = 0; i < 16; i++) {
if ((input[i]&0xff) != expected_bytes[i]) {
// If any byte doesn't match, exit the program
exit(0);
}
}
}

// Function3: Initializes the S-box
void function3(char *key, int key_len, char *s_box) {
int j = 0;
for (int i = 0; i <= 255; i++) {
s_box[i] = i;
}

for (int i = 0; i <= 255; i++) {
j = (j + s_box[i] + key[i % key_len]) % 256;
char temp = s_box[i];
s_box[i] = s_box[j];
s_box[j] = temp;
}
}

// Function4: Encrypts the input using the S-box
void function4(char *s_box, char *input, int input_len) {
int i = 0, j = 0;
for (int k = 0; k < input_len; k++) {
i = (i + 1) % 256;
j = (j + s_box[i]) % 256;
char temp = s_box[i];
s_box[i] = s_box[j];
s_box[j] = temp;
input[k] ^= s_box[(s_box[i] + s_box[j]) % 256];
}
}

// Function5: Combines function3 and function4
void function5(char *key, int key_len, char *input, int input_len) {
char s_box[256];
function3(key, key_len, s_box);
function4(s_box, input, input_len);
}

rc4 可以直接解密,key 是 suctf

将 function1的地址40223D 按照小端序转成 ASCII 码的响应字符

最后是 function1 函数把 flag 按下标加回来即可

1
2
3
4
5
6
7
8
var_1F = [0x41, 0x6d, 0x62, 0x4d, 0x53, 0x49, 0x4e, 0x29, 0x28]

flag = ""
for i in range(len(var_1F)):
flag += chr(var_1F[i] + i)

print('Part 3:', flag)
#Part 3: AndPWNT00

suctf{We1com3ToReWorld=”@AndPWNT00}


SUCTF 2025
https://tsuk1ctf.github.io/post/23605.html
作者
Tsuk1
发布于
2025年1月14日
许可协议