4月月赛WP
1.6小时应急行动
1.1 分析
来到现场后,通过上机初步检查,细心的你发现了一些线索,请分析一下攻击者IP 地址和入侵时间。
flag{192.168.56.128 21/04/2025}
flag{ip DD/MM/YYYY}
在电脑上可以看到有瑞友天翼,我们可以检查瑞友天翼的日志,位置为 C:\Program Files (x86)\RealFriend\Rap Server\Logs\access.log

通过桌面上文件的修改时间,也就是加密时间,可以通过这个时间确认大致的时间段,也就是20号-23号左右,分析日志,在21/Apr/2025时间段有,有一个ip为192.168.56.128有SQL注入行为,并上传了webshell(pdyfzr7k.php)

1.2 溯源
在溯源的过程中,现场的运维告诉你,服务器不知道为什么多了个浏览器,并且这段时间服务器的流量有些异常,你决定一探究竟找找攻击者做了什么,配置了什么东西? 格式:flag{一大串字母}
flag{oisienfpqwlmdouydrsbhuisjAUGEDW}
通过题目提示可以知道电脑上浏览器是一个线索,并且桌面上存在edge浏览器的安装包,可知电脑上存在IE和edge两个浏览器,我们点击edge浏览器,查看下载历史,可以发现攻击者在电脑上下载了rclone,

rclone可以挂载网盘,结合题目说的流量异常,很大可能为攻击者用来窃取数据用的

rclone中有个重要的配置文件rclone.conf
打开配置文件就找到flag

1.3 恢复
现场的运维说软件的某个跳转地址被恶意的修改了,但是却不知道啥时候被修改的,请你找到文件(C:\Program Files (x86)\RealFriend\Rap Server\WebRoot\casweb\Home\View\Index\index.html )
最后被动手脚的时间
flag{2025-04-21 23:39:28}
例:flag{YYYY-MM-DD HH:MM:SS}
被伪造页面


可以使用数字取证工具--Autopsy分析
点击文件查看文件元数据,可以发现数据最后的修改时间才是真正攻击者篡改的时间

1.4 风险排查
一顿分析后,你决定掏出你的Windows安全加固手册对服务器做一次全面的排查,果然你发现了攻击者漏出的鸡脚(四只)
flag格式为:flag{part1+part2+part3+part4}
flag{zheshiyigenixiangbudaodeflag}
通过排查启动项、计划任务、账号排查、系统服务分别获得flag片段,最终组成完整的flag
1)计划任务
首先检查计划任务,找到可疑任务并查看详情信息,发现指向C:\Windows\Temp\update.ps1,

打开update.ps1,找flag1

2)系统服务
输入msconfig,检查系统配置中的服务,勾选隐藏所有Microsoft后,发现可疑系统服务Windows Network Sync

输入services.msc打开系统服务查看详情,找到对应的可疑服务,可以看到描述中有flag2

3)账号排查
注册表中,本地用户和组管理器均可查看,可以看到多个用户名,通过一一排查,可以得知Admin为可疑用户,右键查看属性可以得知flag

4)可疑进程
通过排查系统内的进程,找到可疑的进程svchost.exe,
通过可疑进程找到该程序并发现flag4


最终通过四个线索合成一个完整的flag
flag{part1+part2+part3+part4}
1.5 提交报告
轻轻松松的加固后,你需要写一份溯源分析报告,但是缺少了加密电脑文件的凶手(某加密程序),这份报告客户是不会感到满意的,请你想方法让客户认可这份报告吧
flag格式为:flag{名称}
flag{Encryptor123.exe}
通过题目提示知道要找的是加密程序,在真实的应急响应中,寻找加密器主要通过加密文件的修改时间、加密器常见路径(启动项,music,temp,users等目录下)、常见的加密器名称等线索排查加密器,在这里我们可以上传一个everything方便查找,可以看到一个名为Encryptor123的程序,很明显这就是我们要找的目标


2.可疑文件
拖入ida
发现是一个dll,查看导出函数

发现这个导出函数对f.txt进行了加密

加密算法为chacha20,并且在加密结束的时候对加密的字节进行了加一的操作
因此直接根据写死在程序中密钥写解密脚本即可
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
// ChaCha20 常量
#define KEY_SIZE 32 // 256位密钥
#define NONCE_SIZE 12 // 96位 Nonce
#define BLOCK_SIZE 64 // 64字节块
#define ROUNDS 20 // 20轮加密
// 将输入字符串密钥转换为 32 字节的密钥(不足补零,超过截断)
static void derive_key(const char* pass, uint8_t key[KEY_SIZE]) {
size_t len = strlen(pass);
memset(key, 0, KEY_SIZE);
memcpy(key, pass, len > KEY_SIZE ? KEY_SIZE : len);
}
// ChaCha20 四分之一轮操作
static inline void qround(uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d) {
*a += *b; *d ^= *a; *d = ( *d << 16 ) | ( *d >> 16 ); // 左移16位
*c += *d; *b ^= *c; *b = ( *b << 12 ) | ( *b >> 20 ); // 左移12位
*a += *b; *d ^= *a; *d = ( *d << 8 ) | ( *d >> 24 ); // 左移8位
*c += *d; *b ^= *c; *b = ( *b << 7 ) | ( *b >> 25 ); // 左移7位
}
// 生成单个64字节的密钥流块
static void chacha20_block(uint32_t state[16], uint8_t* key_stream) {
uint32_t workspace[16];
memcpy(workspace, state, 64); // 复制初始状态
// 执行20轮操作(10次双轮)
for (int i = 0; i < ROUNDS; i += 2) {
// 对列进行四分之一轮
qround(&workspace[0], &workspace[4], &workspace[8], &workspace[12]);
qround(&workspace[1], &workspace[5], &workspace[9], &workspace[13]);
qround(&workspace[2], &workspace[6], &workspace[10], &workspace[14]);
qround(&workspace[3], &workspace[7], &workspace[11], &workspace[15]);
// 对对角线进行四分之一轮
qround(&workspace[0], &workspace[5], &workspace[10], &workspace[15]);
qround(&workspace[1], &workspace[6], &workspace[11], &workspace[12]);
qround(&workspace[2], &workspace[7], &workspace[8], &workspace[13]);
qround(&workspace[3], &workspace[4], &workspace[9], &workspace[14]);
}
// 将结果与初始状态相加
for (int i = 0; i < 16; i++) {
workspace[i] += state[i];
}
// 转换为小端字节序
for (int i = 0; i < 16; i++) {
key_stream[i * 4 + 0] = (uint8_t)( workspace[i] >> 0 );
key_stream[i * 4 + 1] = (uint8_t)( workspace[i] >> 8 );
key_stream[i * 4 + 2] = (uint8_t)( workspace[i] >> 16 );
key_stream[i * 4 + 3] = (uint8_t)( workspace[i] >> 24 );
}
// 块计数器递增
state[12]++;
}
// 加密文件
static void encrypt_file(FILE* in, FILE* out, const uint8_t key[KEY_SIZE]) {
uint32_t state[16];
uint8_t nonce[NONCE_SIZE] = { 0 };
// 初始化状态矩阵(根据 RFC 7539)
state[0] = 0x61707865; // "expa"
state[1] = 0x3320646e; // "nd 3"
state[2] = 0x79622d32; // "2-by"
state[3] = 0x6b206574; // "te k"
memcpy(&state[4], key, KEY_SIZE); // 密钥
state[12] = 0; // 块计数器
memcpy(&state[13], nonce, NONCE_SIZE); // Nonce
uint8_t key_stream[BLOCK_SIZE];
uint8_t buffer[BLOCK_SIZE];
size_t bytes_read;
while (( bytes_read = fread(buffer, 1, BLOCK_SIZE, in) ) > 0) {
// 生成密钥流
chacha20_block(state, key_stream);
// 明文与密钥流异或
for (size_t i = 0; i < bytes_read; i++) {
buffer[i] -= 1;
buffer[i] ^= key_stream[i];
}
fwrite(buffer, 1, bytes_read, out);
}
}
int main() {
const char* in_file = "flag.enc";
const char* out_file = "flag.txt";
const char* user_key = "qewuri";
// 处理密钥
uint8_t key[KEY_SIZE];
derive_key(user_key, key);
// 打开文件
FILE* fin = fopen(in_file, "rb");
FILE* fout = fopen(out_file, "wb");
if (!fin || !fout) {
perror("文件打开失败");
return 1;
}
// 解密并保存
encrypt_file(fin, fout, key);
fclose(fin);
fclose(fout);
printf("解密完成: %s\n", out_file);
return 0;
}
flag{sierting_666_fpdsajf[psdfljnwqrlqwhperhqwoeiurhqweourhp}