2025年Solar应急响应公益月赛-3月
窃密排查-1
题目描述
发现内部数据被窃取,进行紧急上机。请通过黑客遗留痕迹进行排查:
找到黑客窃密工具的账号
容器账号密码:root:Solar@2025_03!
tmp目录下发现megacmd,搜一下得知log日志在~/.megaCmd中,遂而发现登录账户
25solar3abc@habenwir.com
窃密排查-2
题目描述
发现内部数据被窃取,进行紧急上机。请通过黑客遗留痕迹进行排查:
获取黑客账号找到flag
在~/.megaCmd/
发现sqlite数据库文件megaclient_statecache14_eHlWQTZuLWNFNGf3Nv5gC10JM48JzGHTc8y6.db ,其中包含flag文件痕迹,不过mega对这些信息都加密了
~/.megaCmd/
下还存在session文件,找到Forensic Investigation of the MEGAcmd Client这篇文章,奈何方向错误
可能是因为密码被重置过导致session失效
查询该邮箱,发现记录在yopmail.com
访问该公共邮箱平台YOPmail : 临时、匿名的免费邮箱地址。
登录发现有封邮件是recover code恢复密钥
尝试恢复mega账户帐户恢复 - MEGA,会发送重置链接到邮箱
输入刚才的恢复密钥
重置密码
在共享项目中找到flag
flag{h4S8_h4m1_8Wlq_b3Xz}
窃密排查-3
获取黑客最终转移账号找到flag
右上角微信标进入聊天框,发现badguy2503@wishy.fr给我们发来session
利用session直接登录
【签到】和黑客去Battle把!
题目描述
某某文化有限公司被加密啦!老板给了小王5000美元请你帮助小王和黑客谈判争取使用最低的价格买下密钥!
【用户ID为登录青少年CTF平台的手机号】
【本题为模拟请勿当真!禁止攻击平台!】
讲价
溯源排查-1
raw转vmdk
qemu-img convert -f raw .\AFEWgf_m-f8zj02psjoasq9hitdu2_system.raw -O vmdk .\solar-3.vmdk
R-studio取证可以得知是centOS-7
然后vmware新建虚拟机
centOS-7
虚拟磁盘
开机按e修改启动配置
删掉静默模式以及一堆网卡串口配置,添加rw init=/sysroot/bin/sh
不删要不然可能会系统堵塞
系统初始化后到了shell环境
切换一下根目录
mount -o remount rw /sysroot
chroot /sysroot
LANG=C
改root密码
touch /.autorelabel
passwd
exit
reboot
重启登入后ifconfig查看确定有网卡
直接ssh连接,密码为所设密码,抓个包查看是否有外连
156.238.230.167:46578
溯源排查-2
ps查看cpu占用较大的进程
systemctl status查看服务发现同时有两个systemd-journald.service相似,其中systemd-journald为标准日志守护进程,而另一个journaled是伪造成系统进程,多了一个e
R-studio也可以看到该服务比较新
[Unit]
Description=journaled
ConditionFileIsExecutable=/usr/local/systemd/journaled
[Service]
StartLimitInterval=5
StartLimitBurst=10
ExecStart=/usr/local/systemd/journaled
Restart=always
RestartSec=120
EnvironmentFile=-/etc/sysconfig/systemd-journaled
[Install]
WantedBy=multi-user.target
该服务的二进制文件/usr/local/systemd/journaled与/root/tmp/hsperfdata_root/2233以及/root/tmp/tomcat-docbase.8848.7206919844684045987/journaled都是同一个文件(后两者被删除),可以相互链接
flag{/usr/local/systemd/journaled}
溯源排查-3
完整服务名称为systemd-journaled
溯源排查-4
题目描述
业务系统已被删除,找出可能存在漏洞的应用
R-studio恢复,发现nacos-server
溯源排查-6
题目描述
找出黑客利用漏洞使用的工具的地址,该工具为开源工具
检索一下nocas RCE漏洞发现c0olw/NacosRce: Nacos JRaft Hessian 反序列化 RCE 加载字节码 注入内存马 不出网利用
项目地址https://github.com/c0olw/NacosRce
溯源排查-5
题目描述
请提交漏洞cve编号
Nacos Hessian 反序列化漏洞
CNVD-2023-45001阿里云漏洞库
明明是cnvd,改成CVE才对
2503逆向
seed为开机时间
qa0wserdf1tg9yuhjio2pklz8xbvcn4mPL7JKOIHUG3YTF6DSREAWQZX5MNCBV伪随机生成十六位key
sub_140001350标准rc4
flag.txt读入明文,flag.txt.freefix输出密文
爆破seed解密,ai搓脚本
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
// 密钥生成使用的字符集
const char charset[] = "qa0wserdf1tg9yuhjio2pklz8xbvcn4mPL7JKOIHUG3YTF6DSREAWQZX5MNCBV";
// 加密数据
const unsigned char encrypted_data[] = {
0x4C, 0x00, 0x2F, 0xAD, 0x84, 0x10, 0x58, 0xAC,
0x8D, 0xD1, 0x59, 0x69, 0x79, 0xFB, 0x9D, 0xB5,
0xC5, 0xFA, 0x60, 0x17, 0xB0, 0x46, 0xE8, 0x75,
0xD6, 0xCD, 0xDE, 0xD7, 0x57, 0xDC, 0x7C, 0x96,
0xE1, 0x15, 0xF3, 0xBD, 0xC0, 0x72, 0x98, 0x91,
0x88, 0x4D, 0x0C, 0xBA, 0x66, 0x04, 0xC9
};
const size_t encrypted_size = sizeof(encrypted_data);
/**
* 根据给定的种子(TickCount)生成密钥
* @param seed 随机数种子,来自GetTickCount()
* @param key 输出参数,存储生成的密钥
* @param key_length 密钥长度,原程序为16
*/
void generate_key(uint32_t seed, char* key, int key_length) {
// 设置随机数种子
srand(seed);
int count = 0;
// 生成16个字符的密钥
while (count < key_length) {
int r = rand();
int idx = r % 62; // 与原代码相同的取模操作
// 确保索引在有效范围内
if (idx <= 61 && idx < strlen(charset)) {
key[count] = charset[idx];
count++;
}
}
key[key_length] = '\0'; // 字符串结束符
}
/**
* 设置RC4状态数组
* @param key 密钥
* @param key_len 密钥长度
* @param S 输出参数,256字节的状态数组
*/
void setup_rc4(char* key, size_t key_len, unsigned char* S) {
int i, j = 0;
unsigned char temp;
// 初始化S盒
for (i = 0; i < 256; i++) {
S[i] = i;
}
// 密钥调度算法 (KSA)
for (i = 0; i < 256; i++) {
// 使用密钥更新j
j = (j + S[i] + key[i % key_len]) % 256;
// 交换S[i]和S[j]
temp = S[i];
S[i] = S[j];
S[j] = temp;
}
}
/**
* 使用RC4算法解密数据
* @param encrypted 加密数据
* @param decrypted 输出参数,解密后的数据
* @param data_len 数据长度
* @param key 密钥
* @param key_len 密钥长度
*/
void rc4_decrypt(const unsigned char* encrypted, unsigned char* decrypted,
size_t data_len, char* key, size_t key_len) {
unsigned char S[256];
int i = 0, j = 0;
unsigned char temp;
// 设置RC4状态
setup_rc4(key, key_len, S);
// 解密 (PRGA - 伪随机生成算法)
for (size_t k = 0; k < data_len; k++) {
// 更新索引i和j
i = (i + 1) % 256;
j = (j + S[i]) % 256;
// 交换S[i]和S[j]
temp = S[i];
S[i] = S[j];
S[j] = temp;
// 使用生成的密钥流进行XOR解密
decrypted[k] = encrypted[k] ^ S[(S[i] + S[j]) % 256];
}
}
/**
* 检查解密是否成功
* @param decrypted 解密后的数据
* @return 如果前4个字节是"flag"则返回1,否则返回0
*/
int is_flag(const unsigned char* decrypted) {
// 检查前4个字节是否为'flag'
return (decrypted[0] == 'f' &&
decrypted[1] == 'l' &&
decrypted[2] == 'a' &&
decrypted[3] == 'g');
}
/**
* 打印解密后的数据,以十六进制和ASCII格式显示
* @param decrypted 解密后的数据
* @param length 数据长度
*/
void print_decrypted(const unsigned char* decrypted, size_t length) {
printf("解密后(十六进制): ");
for (size_t i = 0; i < length; i++) {
printf("%02X ", decrypted[i]);
}
printf("\n解密后(ASCII): ");
for (size_t i = 0; i < length; i++) {
// 只打印可见字符,其他用点号代替
if (decrypted[i] >= 32 && decrypted[i] <= 126) {
printf("%c", decrypted[i]);
}
else {
printf(".");
}
}
printf("\n");
}
int main() {
char key[17]; // 16个字符 + 结束符
unsigned char decrypted[encrypted_size];
uint32_t tick_count;
uint32_t start_tick = 0;
uint32_t end_tick = 86400000; // 24小时的毫秒数(根据需要调整)
uint32_t step = 1; // 先每秒检查一次
printf("开始暴力破解,TickCount范围从%u到%u\n", start_tick, end_tick);
// 第一轮 - 每秒检查一次
for (tick_count = start_tick; tick_count <= end_tick; tick_count += step) {
// 生成密钥
generate_key(tick_count, key, 16);
// 尝试解密
rc4_decrypt(encrypted_data, decrypted, encrypted_size, key, 16);
// 检查是否成功解密
if (is_flag(decrypted)) {
printf("在TickCount = %u时找到可能的匹配\n", tick_count);
printf("密钥: %s\n", key);
print_decrypted(decrypted, encrypted_size);
// 如果想在找到第一个匹配时退出:
// return 0;
}
// 每百万次尝试显示一次进度
if (tick_count % 1000000 == 0) {
printf("进度:已测试TickCount至%u\n", tick_count);
}
}
printf("第一轮完成。未找到匹配。\n");
// 第二轮 - 如果第一轮失败,进行更细粒度的搜索
// 如果需要更彻底的搜索,取消下面注释
/*
printf("开始第二轮搜索,使用更小的步长...\n");
step = 100; // 每100毫秒检查一次
for (tick_count = start_tick; tick_count <= end_tick; tick_count += step) {
generate_key(tick_count, key, 16);
rc4_decrypt(encrypted_data, decrypted, encrypted_size, key, 16);
if (is_flag(decrypted)) {
printf("在TickCount = %u时找到可能的匹配\n", tick_count);
printf("密钥: %s\n", key);
print_decrypted(decrypted, encrypted_size);
return 0;
}
// 进度指示器
if (tick_count % 1000000 == 0) {
printf("进度:已测试TickCount至%u\n", tick_count);
}
}
*/
printf("在指定范围内未找到匹配结果。\n");
return 0;
}
python
import sys
# 假设的字符数组
chars = "qa0wserdf1tg9yuhjio2pklz8xbvcn4mPL7JKOIHUG3YTF6DSREAWQZX5MNCBV"
def cpp_rand(seed):
seed = (seed * 214013 + 2531011) & 0xFFFFFFFF
return (seed >> 16) & 0x7FFF, seed
def generate_key(initial_seed):
key = []
current_seed = initial_seed
for _ in range(16):
current_seed = (current_seed * 214013 + 2531011) & 0xFFFFFFFF
rand_val = (current_seed >> 16) & 0x7FFF
index = rand_val % 62
key.append(chars[index])
return ''.join(key)
def decrypt_rc4(ciphertext, key):
s = list(range(256))
j = 0
key_bytes = [ord(c) for c in key]
key_len = len(key_bytes)
# KSA
for i in range(256):
j = (j + s[i] + key_bytes[i % key_len]) % 256
s[i], s[j] = s[j], s[i]
# PRGA
i = j = 0
plaintext = []
for byte in ciphertext:
i = (i + 1) % 256
j = (j + s[i]) % 256
s[i], s[j] = s[j], s[i]
k = s[(s[i] + s[j]) % 256]
plaintext.append(byte ^ k)
return bytes(plaintext)
ciphertext = bytes.fromhex("4C002FAD841058AC8DD1596979FB9DB5C5FA6017B046E875D6CDDED757DC7C96E115F3BDC0729891884D0CBA6604C9")
# 遍历种子范围(示例取较小范围)
for seed in range(0, 10000000):
key = generate_key(seed)
plaintext = decrypt_rc4(ciphertext, key)
if plaintext.startswith(b'flag'):
print(f"Seed: {seed}, Key: {key}, Flag: {plaintext.decode()}")
sys.exit(0)
print("Flag not found in range.")
c
python