diff --git a/src/common/utils.py b/src/common/utils.py index 3da50d6..8324136 100644 --- a/src/common/utils.py +++ b/src/common/utils.py @@ -62,9 +62,14 @@ class MSTypes(): URL="URL Shortcut" UNKNOWN = "Unknown" - MS_OFFICE_FORMATS = [ XL, XL97, WD, WD97, PPT, PPT97, MPP, PUB, VSD, VSD97] + MS_OFFICE_FORMATS = [ XL, XL97, WD, WD97, PPT, MPP, VSD, VSD97] # Formats supported by macro_pack VB_FORMATS = [VBA, VBS, HTA, SCT, WSF ] VB_FORMATS.extend(MS_OFFICE_FORMATS) + Shortcut_FORMATS = [LNK, GLK, SCF, URL] + + EXTENSION_DICT = { LNK:".lnk", GLK:".glk", SCF:".scf", URL:".url", XL:".xlsm", XL97:".xls", WD:".docm", + WD97:".doc", PPT:".pptm", PPT97:".ppt", MPP:".mpp", PUB:".pub", VSD:".vsdm", VSD97:".vsd", + VBA:".vba", VBS:".vbs", HTA:".hta", SCT:".wsc", WSF:".wsf" } @classmethod def guessApplicationType(self, documentPath): @@ -114,6 +119,9 @@ def guessApplicationType(self, documentPath): return result + + + diff --git a/src/macro_pack.py b/src/macro_pack.py index d5edfe1..9a559cd 100755 --- a/src/macro_pack.py +++ b/src/macro_pack.py @@ -158,13 +158,7 @@ def handleOfficeFormats(mpSession): else: logging.warn(" [!] Word and Word97 are only format supported for DDE attacks.") - if mpSession.runTarget: #run com attack - generator = ComGenerator(mpSession) - generator.run() - - if mpSession.dcom: #run dcom attack - generator = DcomGenerator(mpSession) - generator.run() + def main(argv): @@ -258,8 +252,9 @@ def main(argv): help.printUsage(BANNER, sys.argv[0], mpSession) sys.exit(0) - - os.system('cls' if os.name == 'nt' else 'clear') + if logLevel == "INFO": + os.system('cls' if os.name == 'nt' else 'clear') + # Logging logging.basicConfig(level=getattr(logging, logLevel),format="%(message)s", handlers=[utils.ColorLogFiler()]) @@ -271,7 +266,7 @@ def main(argv): # Check output file format if mpSession.outputFilePath: logging.info(" [-] Target output format: %s" % mpSession.outputFileType) - elif mpSession.listen == False: + elif mpSession.listen == False and mpSession.runTarget is None and mpSession.dcomTarget is None: logging.error(" [!] You need to provide an output file! (-G option)") sys.exit(2) @@ -384,6 +379,16 @@ def main(argv): generator = LNKGenerator(mpSession) generator.run() + #run com attack + if mpSession.runTarget: + generator = ComGenerator(mpSession) + generator.run() + + #run dcom attack + if mpSession.dcom: + generator = DcomGenerator(mpSession) + generator.run() + # Activate Web server if mpSession.listen: listener = ListenServer(mpSession) diff --git a/src/modules/mp_module.py b/src/modules/mp_module.py index 9d2e3dc..16ed9d6 100644 --- a/src/modules/mp_module.py +++ b/src/modules/mp_module.py @@ -85,7 +85,7 @@ def fillInputParams(self, paramDict): os.remove(cmdFile) inputValues = shlex.split(valuesFileContent)# split on space but preserve what is between quotes #logging.info(str(inputValues)) - if len(inputValues) == len(paramDict): + if len(inputValues) >= len(paramDict): i = 0 # Fill entry parameterds for key, value in paramDict.items(): diff --git a/test/mp_tests.py b/test/mp_tests.py new file mode 100644 index 0000000..0f37ed0 --- /dev/null +++ b/test/mp_tests.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python +# encoding: utf-8 +import sys, os +import logging +import __main__ as main # @UnresolvedImport To get the real origin of the script not the location of current file +from termcolor import colored +import colorama +colorama.init() # for nice colored output on windows +import tabulate # easy_install tabulate + +MACRO_PACK_PATH = os.path.abspath(os.path.join(os.path.abspath(main.__file__), '..', '..')) + +BUILD_SCRIPT = os.path.join(MACRO_PACK_PATH, "build.bat") +BIN_PATH=os.path.join(MACRO_PACK_PATH, "bin") + +# Import files from pacro_pack src +SRC_PATH=os.path.join(MACRO_PACK_PATH, "src") +TEST_PATH=os.path.join(MACRO_PACK_PATH, "test") +MP_MAIN=os.path.join(SRC_PATH, "macro_pack.py") + +sys.path.append(SRC_PATH) +from common import utils +from common.utils import MSTypes + + +fileToGenerate = os.path.abspath("resultFile.gug") +fileToGenerateContent = u"This file is the result of a test" + +VBA = \ +""" + +Sub AutoOpen() + CreateTxtFile "%s", "%s" +End Sub + + 'Create A Text and fill it + ' Will overwrite existing file +Private Sub CreateTxtFile(FilePath As String, FileContent As String) + + Dim fso As Object + Set fso = CreateObject("Scripting.FileSystemObject") + + Dim Fileout As Object + Set Fileout = fso.CreateTextFile(FilePath, True, True) + Fileout.Write FileContent + Fileout.Close + +End Sub +""" % (fileToGenerate,fileToGenerateContent ) + + +testSummary = {} + + +def testBuild(): + """ Test we can build macro_pack """ + logging.info(" [+] Testing macro_path build...") + try: + os.system("cd %s && %s > nul" % (MACRO_PACK_PATH, BUILD_SCRIPT)) + assert(os.path.isfile(os.path.join(BIN_PATH,"macro_pack.exe"))) + logging.info(" [-] Success!\n") + testSummary["Macro Pack Build"] = "[OK]" + except: + logging.exception(" [!] Error!\n") + testSummary["Macro Pack Build"] = "[KO]" + return False + + +def testLnkGenerators(): + result = True + for testFormat in MSTypes.Shortcut_FORMATS: + testFile = utils.randomAlpha(8)+MSTypes.EXTENSION_DICT[testFormat] + try: + logging.info(" [+] Testing generation of %s file..." % testFormat) + os.system("echo shortcut_dest icon_file  | %s %s -G %s -q" % (sys.executable,MP_MAIN, testFile)) + assert(os.path.isfile(testFile)) + logging.info(" [-] Success!\n") + testSummary[testFormat] = "[OK]" + except: + result = False + testSummary[testFormat] = "[KO]" + logging.exception(" [!] Error!\n") + + if os.path.isfile(testFile): + os.remove(testFile) + + + return result + + +def testVBGenerators(): + """ + will run test of MS Office and VBS based formats + The tests consist into creating the documents, then running them triggering a file creation macro. Then checking the file is well created + The tests are run in both cleartext and obfuscated mode. + + """ + result = True + vbaTestFile = "testmacro.vba" + logging.info(" [+] Build macro test file...") + with open(vbaTestFile, 'w') as outfile: + outfile.write(VBA) + for testFormat in MSTypes.VB_FORMATS: + testFile = utils.randomAlpha(8)+MSTypes.EXTENSION_DICT[testFormat] + try: + logging.info(" [+] Testing generation of %s file..." % testFormat) + os.system("%s %s -f %s -G %s -q" % (sys.executable,MP_MAIN,vbaTestFile, testFile)) + assert(os.path.isfile(testFile)) + logging.info(" [-] Success!\n") + + if testFormat not in [MSTypes.VBA, MSTypes.SCT]: + logging.info(" [+] Testing run of %s file..." % testFormat) + if testFormat in MSTypes.MS_OFFICE_FORMATS: + os.system("%s %s --run=%s -q" % (sys.executable,MP_MAIN, testFile)) + else: + os.system("cmd.exe /c %s" % (testFile)) + # Check result + assert(os.path.isfile(fileToGenerate)) + with open(fileToGenerate, 'rb') as infile: + content = infile.read().decode('utf-16') + #logging.info("Content:|%s| - fileToGenerateContent:|%s|" % (content, fileToGenerateContent)) + assert(content == fileToGenerateContent) + testSummary[testFormat+ " in Clear Text"] = "[OK]" + logging.info(" [-] Success!\n") + os.remove(fileToGenerate) + + except: + result = False + testSummary[testFormat+ " in Clear Text"] = "[KO]" + logging.exception(" [!] Error!\n") + + if os.path.isfile(testFile): + os.remove(testFile) + + testFile = utils.randomAlpha(8)+MSTypes.EXTENSION_DICT[testFormat] + try: + logging.info(" [+] Testing generation of %s obfuscated file..." % testFormat) + os.system("%s %s -f %s -G %s -o -q" % (sys.executable,MP_MAIN,vbaTestFile, testFile)) + assert(os.path.isfile(testFile)) + + logging.info(" [-] Success!\n") + + if testFormat not in [MSTypes.VBA, MSTypes.SCT]: + logging.info(" [+] Testing run of %s obfuscated file..." % testFormat) + if testFormat in MSTypes.MS_OFFICE_FORMATS: + os.system("%s %s --run=%s -q" % (sys.executable,MP_MAIN, testFile)) + else: + os.system("cmd.exe /c %s" % (testFile)) + # Check result + assert(os.path.isfile(fileToGenerate)) + with open(fileToGenerate, 'rb') as infile: + content = infile.read().decode('utf-16') + assert(content == fileToGenerateContent) + logging.info(" [-] Success!\n") + testSummary[testFormat+ " obfuscated"] = "[OK]" + os.remove(fileToGenerate) + + except: + result = False + testSummary[testFormat+ " obfuscated"] = "[KO]" + logging.exception(" [!] Error!\n") + + if os.path.isfile(testFile): + os.remove(testFile) + + + os.remove(vbaTestFile) + return result + + + +def main(): + logLevel = "INFO" + logging.basicConfig(level=getattr(logging, logLevel),format="%(message)s", handlers=[utils.ColorLogFiler()]) + finalResult = True + + logging.info(" [+] Current interpreter: %s" % sys.executable) + + if not testLnkGenerators(): finalResult = False + if not testVBGenerators(): finalResult = False + if not testBuild(): finalResult = False + + logging.info(" [+] Tests Summary:") + tableData = [] + index = ["Test","Result"] + for key, value in testSummary.items(): + value = value.replace("[KO]", colored("[KO]", "magenta", attrs = ["bold"])).replace("[OK]", colored("[OK]", "green", attrs = ["bold"])) + newLine = [key, value] + tableData.append(newLine) + + + logging.info(tabulate.tabulate(tableData,index,tablefmt="grid") + "\n") + finalResult = " [+] Complete test success: %s \n\n" % str(finalResult) + + logging.info(finalResult.replace("False", colored("[KO]", "red", attrs = ["bold"])).replace("True", colored("[OK]", "green", attrs = ["bold"]))) + + + + +if __name__ == '__main__': + main() + + \ No newline at end of file