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=" ]) shortOptions += "T:" # 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 == "--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.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 expose_ls2(commands): if commands[0] == 'ls': commands.pop(0) for arg in commands: if arg in ['-a', '--all']: printcmd( arg, ''' do not ignore entries starting with . ''') elif arg == '-A' or arg == '--almost-all': printcmd(arg, ''' do not list implied . and .. ''') elif arg == '--author': printcmd( arg, ''' with -l, print the author of each file ''') elif arg == '-b' or arg == '--escape': printcmd( arg, ''' print C-style escapes for nongraphic characters ''') elif arg.startswith('--block-size='): printcmd( arg, ''' scale sizes by SIZE before printing them. E.g., '--block-size=M' prints sizes in units of 1,048,576 bytes. See SIZE format below. ''') elif arg in ['-B', '--ignore-backups']: printcmd( arg, ''' do not list implied entries ending with ~ ''') elif arg == '-c': printcmd( arg, ''' with -lt: sort by, and show, ctime (time of last modification of file status information) with -l: show ctime and sort by name otherwise: sort by ctime, newest first ''') elif arg == '-C': printcmd(arg, ''' list entries by columns ''') elif arg.startswith('--color'): printcmd( arg, ''' colorize the output. WHEN defaults to 'always' or can be 'never' or 'auto'. More info below ''') elif arg in ['-d', '--directory']: printcmd( arg, ''' list directory entries instead of contents, and do not derefer- ence symbolic links ''') elif arg in ['-D', '--dired']: printcmd( arg, ''' generate output designed for Emacs' dired mode ''') elif arg == '-f': printcmd( arg, ''' do not sort, enable -aU, disable -ls --color ''') elif arg in ['-F', '--classify']: printcmd( arg, ''' append indicator (one of */=>@|) to entries ''') elif arg == '--file-type': printcmd(arg, """ likewise, except do not append '*' """) elif arg.startswith('--format'): printcmd( arg, ''' across -x, commas -m, horizontal -x, long -l, single-column -1, verbose -l, vertical -C ''') elif arg == '--full-time': printcmd(arg, ''' like -l --time-style=full-iso ''') elif arg == '-g': printcmd(arg, ''' like -l, but do not list owner ''') elif arg == '--group-directories-first': printcmd( arg, ''' group directories before files. augment with a --sort option, but any use of --sort=none (-U) disables grouping ''') elif arg in ['-G', '--no-group']: printcmd( arg, ''' in a long listing, don't print group names ''') elif arg in ['-h', '--human-readable']: printcmd( arg, ''' with -l, print sizes in human readable format (e.g., 1K 234M 2G) ''') elif arg == '--si': printcmd( arg, ''' likewise (as -h), but use powers of 1000 not 1024 ''') elif arg in ['-H', '--dereference-command-line']: printcmd( arg, ''' follow symbolic links listed on the command line ''') elif arg == '--dereference-command-line-symlink-to-dir': printcmd( arg, ''' follow each command line symbolic link that points to a direc- tory ''') elif arg.startswith('--hide='): printcmd( arg, ''' do not list implied entries matching shell PATTERN (overridden by -a or -A) ''') elif arg.startswith('--indicator-style='): printcmd( arg, ''' append indicator with style WORD to entry names: none (default), slash (-p), file-type (--file-type), classify (-F) ''') elif arg in ['-i', '--inode']: printcmd( arg, ''' print the index number of each file ''') elif arg == '-I' or arg.startswith('--ignore='): printcmd( arg, ''' do not list implied entries matching shell PATTERN ''') elif arg in ['-k', '--kibibytes']: printcmd(arg, ''' use 1024-byte blocks ''') elif arg == '-l': printcmd(arg, ''' use a long listing format ''') elif arg in ['-L', '--dereference']: printcmd( arg, ''' when showing file information for a symbolic link, show informa- tion for the file the link references rather than for the link itself ''') elif arg == '-m': printcmd( arg, ''' fill width with a comma separated list of entries ''') elif arg in ['-n', '--numeric-uid-gid']: printcmd( arg, ''' like -l, but list numeric user and group IDs ''') elif arg in ['-N', '--literal']: printcmd( arg, ''' print raw entry names (don't treat e.g. control characters spe- cially) ''') elif arg == '-o': printcmd( arg, ''' like -l, but do not list group information ''') elif arg == '-p' or arg.startswith('--indicator-style='): printcmd(arg, ''' append / indicator to directories ''') elif arg in ['-q', '--hide-control-chars']: printcmd( arg, ''' print ? instead of non graphic characters ''') elif arg == '--show-control-chars': printcmd( arg, ''' show non graphic characters as-is (default unless program is 'ls' and output is a terminal) ''') elif arg in ['-Q', '--quote-name']: printcmd( arg, ''' enclose entry names in double quotes ''') elif arg.startswith('--quoting-style='): printcmd( arg, ''' use quoting style WORD for entry names: literal, locale, shell, shell-always, c, escape ''') elif arg in ['-r', '--reverse']: printcmd(arg, ''' reverse order while sorting ''') elif arg in ['-R', '--recursive']: printcmd(arg, ''' list subdirectories recursively ''') elif arg in ['-s', '--size']: printcmd( arg, ''' print the allocated size of each file, in blocks ''') elif arg == '-S': printcmd(arg, ''' sort by file size ''') elif arg.startswith('--sort='): printcmd( arg, ''' sort by WORD instead of name: none -U, extension -X, size -S, time -t, version -v ''') elif arg.startswith('--time='): printcmd( arg, ''' with -l, show time as WORD instead of modification time: atime -u, access -u, use -u, ctime -c, or status -c; use specified time as sort key if --sort=time ''') elif arg.startswith('--time-style='): printcmd( arg, ''' with -l, show times using style STYLE: full-iso, long-iso, iso, locale, +FORMAT. FORMAT is interpreted like 'date'; if FORMAT is FORMAT1<newline>FORMAT2, FORMAT1 applies to non-recent files and FORMAT2 to recent files; if STYLE is prefixed with 'posix-', STYLE takes effect only outside the POSIX locale ''') elif arg == '-t': printcmd( arg, ''' sort by modification time, newest first ''') elif arg == '-T' or arg.startswith('--tabsize='): printcmd( arg, ''' assume tab stops at each COLS instead of 8 ''') elif arg == '-u': printcmd( arg, ''' with -lt: sort by, and show, access time with -l: show access time and sort by name otherwise: sort by access time ''') elif arg == '-U': printcmd( arg, ''' do not sort; list entries in directory order ''') elif arg == '-v': printcmd( arg, ''' natural sort of (version) numbers within text ''') elif arg == '-w' or arg.startswith('--width='): printcmd( arg, ''' assume screen width instead of current value ''') elif arg == '-x': printcmd( arg, ''' list entries by lines instead of by columns ''') elif arg == '-X': printcmd( arg, ''' sort alphabetically by entry extension ''') elif arg in ['-Z', '--context']: printcmd( arg, ''' print any SELinux security context of each file ''') elif arg == '-1': printcmd(arg, ''' list one file per line ''') elif arg == '--help': printcmd(arg, ''' display this help and exit ''') elif arg == '--version': printcmd( arg, ''' output version information and exit ''') # 'ls' can have options like '-lAF', which means same as '-l -A -F'. # compressed options elif arg.startswith('-'): if len(arg) == 2: printcmd(arg, 'Unknown or too new or error') else: # Separate and add '-' for example, # '-df' becomes ['-d', '-f'] expose_ls2(['-' + c for c in arg[1:]]) else: allmessage = '{0}' if arg == '.': message = ''' current directory ''' elif arg == '..': message = ''' parent directory ''' elif arg == '*': message = ''' every file and directory, in case of directory, list content of the directory (not recursive unless '-R') ''' elif arg.startswith('*'): message = ''' every file and directory ends with '{}', in case of directory, list content of the directory (not recursive unless '-R') '''.format(arg[1:]) elif arg.endswith('*'): message = ''' every file and directory starts with '{}', in case of directory, list content of the directory (not recursive unless '-R') '''.format(arg[1:]) elif '*' in arg: globArgs = arg.split('*') globLen = len(globArgs) if globLen == 2: message = ''' every file and directory starts with '{}' and ends with '{}', in case of directory, list content of the directory (not recursive unless '-R') '''.format(globArgs[0], globArgs[1]) else: message = ''' every files and directory satisfies the glob, in case of directory, list content of the directory (not recursive unless '-R') ''' else: message = arg printcmd(arg, allmessage.format(message))
def main(argv): logLevel = "INFO" # initialize macro_pack session object mpSession = mp_session.MpSession(WORKING_DIR, 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=", "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" ]) 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 = arg elif opt == "--port": mpSession.listenPort = int(arg) mpSession.WlistenPort = int(arg) elif opt == "-w" or opt == "--webdav-listen": mpSession.Wlisten = True mpSession.WRoot = 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 == "--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 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 mod, file are tojane if they already exist and created if they dont. # Thid 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_DIR) if not os.path.exists(WORKING_DIR): os.makedirs(WORKING_DIR) try: # Create temporary work file. if mpSession.ddeMode or mpSession.template or ( mpSession.outputFileType not in MSTypes.VB_FORMATS): 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) # 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) 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: generator = VBAGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.SCF: generator = SCFGenerator(mpSession) generator.run() if mpSession.outputFileType == MSTypes.XSL: generator = XSLGenerator(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() #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_DIR) 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 = [ "quiet", "input-file=", "vba-output=", "mask-strings", "encode", "obfuscate", "obfuscate-form", "obfuscate-names", "obfuscate-strings", "file=", "template=", "start-function=", "dde" ] # 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: 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 == "-f" or opt == "--input-file": mpSession.vbaInput = 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 == "-v" or opt == "--vba-output": mpSession.vbaFilePath = os.path.abspath(arg) mpSession.fileOutput = True elif opt == "--dde": if sys.platform == "win32": mpSession.ddeMode = 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": 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 == "--trojan": mpSession.trojan = True elif opt == "--stealth": mpSession.stealth = True 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: 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 mod, 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. if mpSession.ddeMode: 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: f = open(inputFile, 'w') f.writelines(mpSession.stdinContent) f.close() else: # Create temporary work file shutil.copy2(mpSession.vbaInput, inputFile) logging.info(" [-] Temporary file: %s" % inputFile) if mpSession.ddeMode: # DDE Attack mode if mpSession.wordFilePath or mpSession.word97FilePath: generator = WordDDE(mpSession) generator.run() else: # VBA macro mode # 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)