How To: Empire’s Cross Platform Office Macro

David Fletcher //

During our testing, we encounter organizations of various different sizes, shapes, and composition.  One that we’ve run across a number of times includes a fairly even mixture of Microsoft Windows and Apple OSX operating systems. Under normal circumstances it can be difficult to identify which users are using Windows and which are using OSX.  This can make phishing with malware challenging.  If the wrong payload is delivered to the wrong operating system…no shell.

As a solution, we can just include some intelligence in our macro malware to decide whether to execute a PowerShell or Python payload based on the target operating system.  Fortunately, with the integration of the PowerShell Empire and EmPyre projects into PowerShell Empire 2.0, we have ready-made stagers to accomplish this goal.

The stager listing from PowerShell Empire 2.0 can be seen below with the macro payloads for Windows and OSX both highlighted.

Before we can generate our stagers, we have to get a listener up and running.  For this demonstration, we’ll just use the default configuration with the listener name “xplatform_macro”. However, I would encourage you to modify the default communication profile to deviate from the standard requests, include jitter, and use a valid TLS certificate.  This will decrease the chances of your malware communication getting stopped by a proxy or detected by anti-malware tools looking for beaconing behavior.

With the listener configured, just issue the “execute” command to launch it.

Next, we need to grab output from each of the two launchers.  Here we just need to set the listener name and issue the “generate” command.  The output from each instance should be copied into a text editor so we can manipulate them. Generation of the Windows and OSX macros can be seen below.


With the macro content at hand, we can now build our cross platform malicious macro document.

First, open the Macro editor in Word (both the Windows and OSX versions will work for this). The Macro editor is accessed by enabling the Developer tab in the Office Ribbon and clicking the Macros button.

Next, paste the declare statement that appears in the OSX macro as seen below.  Windows will safely ignore this statement because the “system” function is never called by the PowerShell based macro.  Then create the necessary AutoOpen() subroutine and use the “Mac” directive to to conditionally execute either the PowerShell or Python payload based on the detected operating system.  In this case, I named the resulting functions DebugMac and DebugWin as seen below.

Next, the original macro subroutines are refactored into the target functions as seen below.  In the case of the Windows Macro, a Dim statement had to be added to explicitly declare the strComputer variable.  No other modifications were made (remember to end each function with “End Function”).

With the malicious macro document complete, the only thing left to do is to test on each of the targeted platforms.  After execution, we have two agents that have called back to our PowerShell Empire listener.  One running PowerShell and one running Python…both from the same document.

This technique has its limitations.  It only works with modern macro-enabled office documents.  Office for Mac did not support macros in the older format.  In addition, Office 2016 for Mac doesn’t appear to allow access to the C library used to make the Python system call.

Go pwn some mixed platform environments!!