#!/usr/bin/python import sys from scapy import sniff #sr1,IP,ICMP Count=0 IPCount = { } SynSentToTCPService = { } #Boolean dictionary: have we seen a syn sent to this IP:Port pair yet? LiveTCPService = { } #Boolean dictionary: Have we seen a SYN/ACK come back (true) or a RST (False) from this IP:Port pair? LiveUDPService = { } #Boolean dictionary: we've found a server here ServerDescription = { } #String dictionary: What server is this IP:Port pair? UDPServerDescription = { } #Similar for UDP ClientDescription = { } #String dictionary: What client is on this IP:port? NOTE: the port here is the _server_ port at the other end. So if #Firefox on 1.2.3.4 is making outbound connections to port 80 on remote servers, ClientDescription['1.2.3.4:80'] = "http/firefox" MacAddr = { } #String dictionary: For a given IP (key), what is its mac (value)? MuteWarned = { } #Boolean dictionary: if true for a given key, we've warned that we won't report this object any more. if len(sys.argv) > 1: bpfilter = sys.argv[1] else: bpfilter = "" def ReportId(Type, Location, Description): global ServerDescription global UDPServerDescription global ClientDescription global MacAddr global MuteWarned if (Type == "TCPServer"): ServerDescription[Location] = Description print Type + ":" + Location + "=" + Description elif (Type == "UDPServer"): UDPServerDescription[Location] = Description print Type + ":" + Location + "=" + Description elif (Type == "TCPClient"): ClientDescription[Location] = Description print Type + ":" + Location + "=" + Description elif (Type == "MacAddr"): Found = False for Key in MacAddr.keys(): if (MacAddr[Key] == Description): Found=True break if Found: if (not MuteWarned.has_key(Description)): print "Duplicate IPs found for " + Description + ", no longer printing for it." MuteWarned[Description] = True else: MacAddr[Location] = Description print Type + ":" + Location + "=" + Description def processpacket(p): #p.show() #quit() global Count global IPCount global SynSentToTCPService global LiveTCPService global LiveUDPService global ServerDescription global ClientDescription global MacAddr Count=Count+1 #print Count if p['Ethernet.type'] == 0x0806: #ARP pass #print "ARP" #p.show() elif p['Ethernet.type'] == 0x0800: #IP sIP=str(p['IP.src']) dIP=str(p['IP.dst']) if not MacAddr.has_key(sIP): ReportId("MacAddr", sIP, p['Ethernet.src']) if not MacAddr.has_key(dIP): ReportId("MacAddr", dIP, p['Ethernet.dst']) if not IPCount.has_key(p['IP.src']): IPCount[p['IP.src']] = 0 IPCount[p['IP.src']] += 1 if not IPCount.has_key(p['IP.dst']): IPCount[p['IP.dst']] = 0 IPCount[p['IP.dst']] += 1 if p['IP.proto'] == 1: #ICMP pass #print p['IP.src'], "(" + str(IPCount[p['IP.src']]) + ") -> ", p['IP.dst'], "(" + str(IPCount[p['IP.dst']]) + ") ", #print "ICMP" elif p['IP.proto'] == 2: #IGMP pass elif p['IP.proto'] == 6: #TCP sport=str(p['TCP.sport']) dport=str(p['TCP.dport']) #"(" + str(IPCount[p['IP.src']]) + ") "(" + str(IPCount[p['IP.dst']]) + ") #print p['IP.src'] + ":" + sport + " -> ", p['IP.dst'] + ":" + dport, #print "TCP ", if (p['TCP.flags'] & 0x17) == 0x12: #Syn-Ack (rst/fin off) #print "SA" Service = sIP + ":" + sport #If we've seen a syn sent to this port and have either not seen any SA/R, or we've seen a R in the past: #The last test is for a service that was previously closed and is now open; report each transition once. if ( (SynSentToTCPService.has_key(Service)) and ((not LiveTCPService.has_key(Service)) or (LiveTCPService[Service] == False)) ): LiveTCPService[Service] = True print "Live: " + Service #quit() elif (p['TCP.flags'] & 0x17) == 0x02: #Syn (ack/rst/fin off) #print "S" Service = dIP + ":" + dport if not SynSentToTCPService.has_key(Service): SynSentToTCPService[Service] = True #print "SynSentTo: " + Service #quit() elif (p['TCP.flags'] & 0x07) == 0x04: #Rst (syn/fin off) #print "R" Service = sIP + ":" + sport if ( (SynSentToTCPService.has_key(Service)) and ((not LiveTCPService.has_key(Service)) or (LiveTCPService[Service] == True)) ): LiveTCPService[Service] = False print "Dead: " + Service #quit() elif (p['TCP.flags'] & 0x17) == 0x10: #Ack (rst/syn/fin off) FromPort = sIP + ":" + sport ToPort = dIP + ":" + dport Payload = str(p['Raw.load']) if ( (LiveTCPService.has_key(FromPort)) and (LiveTCPService[FromPort] == True) and (LiveTCPService.has_key(ToPort)) and (LiveTCPService[ToPort] == True)): print "Logic failure: both " + FromPort + " and " + ToPort + " are listed as live services." elif ((LiveTCPService.has_key(FromPort)) and (LiveTCPService[FromPort] == True)): if (not ServerDescription.has_key(FromPort)): if (sport == "22") and ( (not Payload.find('SSH-1.99-OpenSSH_') == -1) or (not Payload.find('SSH-2.0-OpenSSH_') == -1) ): ReportId("TCPServer", FromPort, "ssh/openssh") elif (sport == "22") and (not Payload.find('SSH-1.5-') == -1): ReportId("TCPServer", FromPort, "ssh/generic") elif (sport == "25") and (not Payload.find(' ESMTP Sendmail ') == -1): ReportId("TCPServer", FromPort, "smtp/sendmail") elif (sport == "25") and (not Payload.find(' - Welcome to our SMTP server ESMTP') == -1): ReportId("TCPServer", FromPort, "smtp/generic") elif (sport == "80") and (not Payload.find('Server: Apache') == -1): ReportId("TCPServer", FromPort, "http/apache") elif (sport == "80") and (not Payload.find('Server: gws') == -1): ReportId("TCPServer", FromPort, "http/gws") elif (sport == "80") and (not Payload.find('Server: Microsoft-IIS') == -1): ReportId("TCPServer", FromPort, "http/iis") elif (sport == "80") and (not Payload.find('Server: MIIxpc') == -1): ReportId("TCPServer", FromPort, "http/mirrorimage") elif (sport == "80") and (not Payload.find('Server: nc -l -p 80') == -1): ReportId("TCPServer", FromPort, "http/nc") elif (sport == "80") and (not Payload.find('Server: Sun-ONE-Web-Server/') == -1): ReportId("TCPServer", FromPort, "http/sun-one") elif (sport == "80") and (not Payload.find('Server: YTS/') == -1): ReportId("TCPServer", FromPort, "http/yahoo") elif (sport == "143") and (not Payload.find('* OK dovecot ready') == -1): ReportId("TCPServer", FromPort, "imap/dovecot") elif (sport == "143") and (not Payload.find(' IMAP4rev1 ') == -1): ReportId("TCPServer", FromPort, "imap/generic") elif (sport == "783") and (not Payload.find('SPAMD/1.1 ') == -1): ReportId("TCPServer", FromPort, "spamd/spamd") elif ( (sport == "3128") or (sport == "80") ) and (not Payload.find('Via: ') == -1) and (not Payload.find(' (squid/') == -1): ReportId("TCPServer", FromPort, "proxy/squid") else: if (not Payload == "None"): print "FromSrv:" + FromPort + "====" + Payload + "=====" elif ((LiveTCPService.has_key(ToPort)) and (LiveTCPService[ToPort] == True)): ClientKey = sIP + ":" + dport #Note: CLIENT ip and SERVER port if (not ClientDescription.has_key(ClientKey)): if (dport == "22") and ( (not Payload.find('SSH-2.0-OpenSSH_') == -1) or (not Payload.find('SSH-1.5-OpenSSH_') == -1) ): ReportId("TCPClient", ClientKey, "ssh/openssh") elif (dport == "25") and (not Payload.find('Message-ID: ", p['IP.dst'] + ":" + str(p['UDP.dport']), #print "UDP" else: print p['IP.src'], "(" + str(IPCount[p['IP.src']]) + ") -> ", p['IP.dst'], "(" + str(IPCount[p['IP.dst']]) + ") ", p.show() print "Other" else: print "Unregistered ethernet type:", print p['Ethernet.type'] p.show() sniff(filter=bpfilter, prn=lambda x: processpacket(x), store=0) #, count=500 #if packets: # packets.show() #for packet in packets: # packet.show # print"====" #x.src source mac #x.dst dest mac