def markmatchedippackets(addrkey): ((src, sport), (dst, dport)) = addrkey ((sip, sp), (dip, dp)) = addrkey newaddrkey = ((dip, dp), (sip, sp)) if addrkey in ippacketsdict.keys( ) and ippacketsdict[addrkey]['proto'] == 'UDP': ippacketsdict[addrkey]['matched'] = True ippacketsdict[addrkey]['id'] = configopts['packetct'] if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo( '[IP#%d.UDP#%d] Flow %s:%s - %s:%s marked to be written to a pcap' % (openudpflows[key]['ipct'], openudpflows[key]['id'], src, sport, dst, dport)) elif newaddrkey in ippacketsdict.keys( ) and ippacketsdict[newaddrkey]['proto'] == 'UDP': ippacketsdict[newaddrkey]['matched'] = True ippacketsdict[newaddrkey]['id'] = configopts['packetct'] if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo( '[IP#%d.UDP#%d] Flow %s:%s - %s:%s marked to be written to a pcap' % (openudpflows[key]['ipct'], openudpflows[key]['id'], src, sport, dst, dport)) elif configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo( '[IP#%d.UDP#%d] Flow %s:%s - %s:%s not found in ippacketsdict, something\'s wrong' % (openudpflows[key]['ipct'], openudpflows[key]['id'], src, sport, dst, dport))
def dumpippacketsdict(): doinfo('Dumping IP packets dictionary: %d' % len(ippacketsdict.keys())) for key in ippacketsdict.keys(): ((src, sport), (dst, dport)) = key doinfo('[%s#%08d] %s:%s - %s:%s { Packets: %d, Matched: %s}' % (ippacketsdict[key]['proto'], ippacketsdict[key]['id'], src, sport, dst, dport, len(ippacketsdict[key].keys()) - configopts['ipmetavars'], ippacketsdict[key]['matched']))
def dumpippacketsdict(): doinfo('Dumping IP packets dictionary: %d' % len(ippacketsdict.keys())) for key in ippacketsdict.keys(): ((src, sport), (dst, dport)) = key doinfo('[%s#%08d] %s:%s - %s:%s { Packets: %d, Matched: %s}' % ( ippacketsdict[key]['proto'], ippacketsdict[key]['id'], src, sport, dst, dport, len(ippacketsdict[key].keys()) - configopts['ipmetavars'], ippacketsdict[key]['matched']))
def markmatchedippackets(addrkey): ((src, sport), (dst, dport)) = addrkey ((sip, sp), (dip, dp)) = addrkey newaddrkey = ((dip, dp), (sip, sp)) if addrkey in ippacketsdict.keys() and ippacketsdict[addrkey]['proto'] == 'TCP': ippacketsdict[addrkey]['matched'] = True ippacketsdict[addrkey]['id'] = opentcpflows[addrkey]['id'] if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] Flow %s:%s - %s:%s marked to be written to a pcap' % ( opentcpflows[matchstats['addr']]['ipct'], opentcpflows[matchstats['addr']]['id'], src, sport, dst, dport)) elif newaddrkey in ippacketsdict.keys() and ippacketsdict[newaddrkey]['proto'] == 'TCP': ippacketsdict[newaddrkey]['matched'] = True ippacketsdict[newaddrkey]['id'] = opentcpflows[addrkey]['id'] if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] Flow %s:%s - %s:%s marked to be written to a pcap' % ( opentcpflows[matchstats['addr']]['ipct'], opentcpflows[matchstats['addr']]['id'], src, sport, dst, dport)) elif not configopts['linemode']: if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] Flow %s:%s - %s:%s not found in ippacketsdict, something\'s wrong' % ( opentcpflows[matchstats['addr']]['ipct'], opentcpflows[matchstats['addr']]['id'], src, sport, dst, dport))
def writepackets(): pktlist = [] for key in ippacketsdict.keys(): if ippacketsdict[key]['matched']: packets = 0 del pktlist[:] ((src, sport), (dst, dport)) = key pcapfile = '%s-%08d-%s.%s-%s.%s.pcap' % (ippacketsdict[key]['proto'], ippacketsdict[key]['id'], src, sport, dst, dport) for subkey in ippacketsdict[key].keys(): if subkey not in ['proto', 'id', 'matched', 'matchedid']: pktlist.append(ippacketsdict[key][subkey]) packets += 1 pcapwriter(pcapfile, pktlist) if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('Wrote %d packets to %s' % (packets, pcapfile)) del ippacketsdict[key]
def handletcp(tcp): id = 0 showmatch = False addrkey = tcp.addr ((src, sport), (dst, dport)) = tcp.addr if not configopts['linemode']: if configopts['tcpdone']: if configopts['udpdone']: if configopts['verbose'] and configopts['verboselevel'] >= 1: if addrkey in opentcpflows: id = opentcpflows[addrkey]['id'] doinfo('[IP#%d.TCP#%d] Done inspecting max packets (%d) and max streams (%d), preparing for exit' % ( opentcpflows[addrkey]['ipct'], opentcpflows[addrkey]['id'], configopts['maxinsppackets'], configopts['maxinspstreams'])) exitwithstats() else: if configopts['verbose'] and configopts['verboselevel'] >= 1: if addrkey in opentcpflows: id = opentcpflows[addrkey]['id'] doinfo('[IP#%d.TCP#%d] Ignoring stream %s:%s %s %s:%s { insptcppacketct: %d == maxinspstreams: %d }' % ( opentcpflows[addrkey]['ipct'], opentcpflows[addrkey]['id'], src, sport, dst, dport, configopts['insptcppacketct'], configopts['maxinspstreams'])) return regexes = [] fuzzpatterns = [] yararuleobjects = [] timestamp = datetime.datetime.fromtimestamp(nids.get_pkt_ts()).strftime('%H:%M:%S | %Y/%m/%d') endstates = [ nids.NIDS_CLOSE, nids.NIDS_TIMED_OUT, nids.NIDS_RESET ] inspectcts = False inspectstc = False if len(configopts['ctsregexes']) > 0 or len(configopts['ctsfuzzpatterns']) > 0 or len(configopts['ctsyararules']) > 0: inspectcts = True if len(configopts['stcregexes']) > 0 or len(configopts['stcfuzzpatterns']) > 0 or len(configopts['stcyararules']) > 0: inspectstc = True if tcp.nids_state == nids.NIDS_JUST_EST: if addrkey not in opentcpflows: tcp.server.collect = 0 tcp.client.collect = 0 if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] %s:%s - %s:%s remains untracked { IP tracking missed this flow }' % ( opentcpflows[addrkey]['ipct'], opentcpflows[addrkey]['id'], src, sport, dst, dport)) else: configopts['insptcpstreamct'] += 1 if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] %s:%s - %s:%s [NEW] { TRACKED: %d }' % ( opentcpflows[addrkey]['ipct'], opentcpflows[addrkey]['id'], src, sport, dst, dport, len(opentcpflows))) if configopts['linemode'] or 'shellcode' in configopts['inspectionmodes']: tcp.server.collect = 1 tcp.client.collect = 1 if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] Enabled both CTS and STC data collection for %s:%s - %s:%s' % ( opentcpflows[addrkey]['ipct'], opentcpflows[addrkey]['id'], src, sport, dst, dport)) else: if inspectcts or 'shellcode' in configopts['inspectionmodes']: tcp.server.collect = 1 if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] Enabled CTS data collection for %s:%s - %s:%s' % ( opentcpflows[addrkey]['ipct'], opentcpflows[addrkey]['id'], src, sport, dst, dport)) if inspectstc or 'shellcode' in configopts['inspectionmodes']: tcp.client.collect = 1 if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] Enabled STC data collection for %s:%s - %s:%s' % ( opentcpflows[addrkey]['ipct'], opentcpflows[addrkey]['id'], src, sport, dst, dport)) if tcp.nids_state == nids.NIDS_DATA: tcp.discard(0) configopts['insptcppacketct'] += 1 if tcp.server.count_new > 0: direction = configopts['ctsdirectionstring'] directionflag = configopts['ctsdirectionflag'] count = tcp.server.count newcount = tcp.server.count_new start = tcp.server.count - tcp.server.count_new end = tcp.server.count opentcpflows[addrkey]['totdatasize'] += tcp.server.count_new if configopts['offset'] > 0 and configopts['offset'] < count: offset = configopts['offset'] else: offset = 0 if configopts['depth'] > 0 and configopts['depth'] <= (count - offset): depth = configopts['depth'] + offset else: depth = count offset += opentcpflows[addrkey]['multimatchskipoffset'] configopts['inspoffset'] = offset inspdata = tcp.server.data[offset:depth] inspdatalen = len(inspdata) if 'regex' in configopts['inspectionmodes']: for regex in configopts['ctsregexes'].keys(): regexes.append(regex) if 'fuzzy' in configopts['inspectionmodes']: for fuzzpattern in configopts['ctsfuzzpatterns']: fuzzpatterns.append(fuzzpattern) if 'yara' in configopts['inspectionmodes']: for yararuleobj in configopts['ctsyararules']: yararuleobjects.append(yararuleobj) if tcp.client.count_new > 0: direction = configopts['stcdirectionstring'] directionflag = configopts['stcdirectionflag'] count = tcp.client.count newcount = tcp.client.count_new start = tcp.client.count - tcp.client.count_new end = tcp.client.count opentcpflows[addrkey]['totdatasize'] += tcp.client.count_new if configopts['offset'] > 0 and configopts['offset'] < count: offset = configopts['offset'] else: offset = 0 offset += opentcpflows[addrkey]['multimatchskipoffset'] configopts['inspoffset'] = offset if configopts['depth'] > 0 and configopts['depth'] < (count - offset): depth = offset + configopts['depth'] else: depth = count inspdata = tcp.client.data[offset:depth] inspdatalen = len(inspdata) if 'regex' in configopts['inspectionmodes']: for regex in configopts['stcregexes'].keys(): regexes.append(regex) if 'fuzzy' in configopts['inspectionmodes']: for fuzzpattern in configopts['stcfuzzpatterns']: fuzzpatterns.append(fuzzpattern) if 'yara' in configopts['inspectionmodes']: for yararuleobj in configopts['stcyararules']: yararuleobjects.append(yararuleobj) if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] %s:%s %s %s:%s [%dB] { CTS: %d, STC: %d, TOT: %d }' % ( opentcpflows[addrkey]['ipct'], opentcpflows[addrkey]['id'], src, sport, directionflag, dst, dport, newcount, tcp.server.count, tcp.client.count, opentcpflows[addrkey]['totdatasize'])) if configopts['linemode']: matchstats['addr'] = addrkey matchstats['start'] = start matchstats['end'] = end matchstats['matchsize'] = matchstats['end'] - matchstats['start'] matchstats['direction'] = direction matchstats['directionflag'] = directionflag donorm('[IP#%d.TCP#%d] Skipping inspection as linemode is enabled.' % (opentcpflows[addrkey]['ipct'], opentcpflows[addrkey]['id'])) showtcpmatches(inspdata[matchstats['start']:matchstats['end']]) if configopts['writepcap']: markmatchedippackets(addrkey) return if configopts['maxinspstreams'] != 0 and configopts['insptcppacketct'] >= configopts['maxinspstreams']: configopts['tcpdone'] = True if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] Initiating inspection on %s[%d:%d] - %dB' % ( opentcpflows[addrkey]['ipct'], opentcpflows[addrkey]['id'], direction, offset, depth, inspdatalen)) matched = inspect('TCP', inspdata, inspdatalen, regexes, fuzzpatterns, yararuleobjects, addrkey, direction, directionflag) if matched: if configopts['killtcp']: tcp.kill if configopts['writepcap']: markmatchedippackets(addrkey) elif configopts['writepcapfast']: if addrkey in ippacketsdict.keys() and ippacketsdict[addrkey]['proto'] == 'TCP': ippacketsdict[addrkey]['matched'] = True ippacketsdict[addrkey]['id'] = opentcpflows[addrkey]['id'] ippacketsdict[addrkey]['matchedid'] = len(ippacketsdict[addrkey].keys()) - configopts['ipmetavars'] else: ((sip, sp), (dip, dp)) = addrkey newaddrkey = ((dip, dp), (sip, sp)) if newaddrkey in ippacketsdict.keys() and ippacketsdict[newaddrkey]['proto'] == 'TCP': ippacketsdict[newaddrkey]['matched'] = True ippacketsdict[newaddrkey]['id'] = opentcpflows[newaddrkey]['id'] ippacketsdict[newaddrkey]['matchedid'] = len(ippacketsdict[newaddrkey].keys()) - configopts['ipmetavars'] if direction == configopts['ctsdirectionstring']: matchstats['direction'] = configopts['ctsdirectionstring'] matchstats['directionflag'] = configopts['ctsdirectionflag'] elif direction == 'STC': matchstats['direction'] = configopts['stcdirectionstring'] matchstats['directionflag'] = configopts['stcdirectionflag'] if configopts['tcpmatches'] == 0: configopts['shortestmatch']['stream'] = matchstats['matchsize'] configopts['shortestmatch']['streamid'] = opentcpflows[addrkey]['id'] configopts['longestmatch']['stream'] = matchstats['matchsize'] configopts['longestmatch']['streamid'] = opentcpflows[addrkey]['id'] else: if matchstats['matchsize'] <= configopts['shortestmatch']['stream']: configopts['shortestmatch']['stream'] = matchstats['matchsize'] configopts['shortestmatch']['streamid'] = opentcpflows[addrkey]['id'] if matchstats['matchsize'] >= configopts['longestmatch']['stream']: configopts['longestmatch']['stream'] = matchstats['matchsize'] configopts['longestmatch']['streamid'] = opentcpflows[addrkey]['id'] configopts['tcpmatches'] += 1 matchstats['addr'] = addrkey showtcpmatches(inspdata[matchstats['start']:matchstats['end']]) if not configopts['tcpmultimatch']: tcp.server.collect = 0 tcp.client.collect = 0 if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] %s:%s - %s:%s not being tracked any further { tcpmultimatch: %s }' % ( opentcpflows[addrkey]['ipct'], opentcpflows[addrkey]['id'], src, sport, dst, dport, configopts['tcpmultimatch'])) del opentcpflows[addrkey] else: if direction == configopts['ctsdirectionstring']: opentcpflows[addrkey]['ctspacketlendict'].clear() elif direction == configopts['stcdirectionstring']: opentcpflows[addrkey]['stcpacketlendict'].clear() opentcpflows[addrkey]['multimatchskipoffset'] += matchstats['end'] if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] Marked %dB to be skipped for further %s inspection' % ( opentcpflows[addrkey]['ipct'], opentcpflows[addrkey]['id'], opentcpflows[addrkey]['multimatchskipoffset'], direction)) else: opentcpflows[addrkey]['previnspbufsize'] = inspdatalen if tcp.nids_state in endstates: if addrkey in opentcpflows: ipct = opentcpflows[addrkey]['ipct'] id = opentcpflows[addrkey]['id'] del opentcpflows[addrkey] if configopts['verbose'] and configopts['verboselevel'] >= 1: if tcp.nids_state == nids.NIDS_CLOSE: state = 'FIN' elif tcp.nids_state == nids.NIDS_TIMED_OUT: state = 'TIMED_OUT' elif tcp.nids_state == nids.NIDS_RESET: state = 'RST' else: state = 'UNKNOWN' doinfo('[IP#%d.TCP#%d] %s:%s - %s:%s [%s] { TRACKED: %d }' % ( ipct, id, src, sport, dst, dport, state, len(opentcpflows)))
def handleudp(addr, payload, pkt): showmatch = False addrkey = addr ((src, sport), (dst, dport)) = addr count = len(payload) start = 0 end = count data = payload if len(configopts['ctsregexes']) > 0 or len(configopts['ctsfuzzpatterns']) > 0 or len(configopts['ctsyararules']) > 0: inspectcts = True else: inspectcts = False if len(configopts['stcregexes']) > 0 or len(configopts['stcfuzzpatterns']) > 0 or len(configopts['stcyararules']) > 0: inspectstc = True else: inspectstc = False keya = "%s:%s" % (src, sport) keyb = "%s:%s" % (dst, dport) key = None if keya in openudpflows: key = "%s:%s" % (src, sport) keydst = "%s:%s" % (dst, dport) direction = configopts['ctsdirectionstring'] directionflag = configopts['ctsdirectionflag'] elif keyb in openudpflows: key = "%s:%s" % (dst, dport) keydst = "%s:%s" % (src, sport) direction = configopts['stcdirectionstring'] directionflag = configopts['stcdirectionflag'] if key in openudpflows and openudpflows[key]['keydst'] == keydst: openudpflows[key]['totdatasize'] += count else: if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.UDP#%d] %s:%s - %s:%s remains untracked { IP tracking missed this flow }' % ( openudpflows[key]['ipct'], openudpflows[key]['id'], src, sport, dst, dport)) regexes = [] fuzzpatterns = [] yararuleobjects = [] timestamp = datetime.datetime.fromtimestamp(nids.get_pkt_ts()).strftime('%H:%M:%S | %Y/%m/%d') if direction == configopts['ctsdirectionstring']: openudpflows[key]['ctsdatasize'] += count if 'regex' in configopts['inspectionmodes']: for regex in configopts['ctsregexes']: regexes.append(regex) if 'fuzzy' in configopts['inspectionmodes']: for fuzzpattern in configopts['ctsfuzzpatterns']: fuzzpatterns.append(fuzzpattern) if 'yara' in configopts['inspectionmodes']: for yararuleobj in configopts['ctsyararules']: yararuleobjects.append(yararuleobj) elif direction == configopts['stcdirectionstring']: openudpflows[key]['stcdatasize'] += count if 'regex' in configopts['inspectionmodes']: for regex in configopts['stcregexes']: regexes.append(regex) if 'fuzzy' in configopts['inspectionmodes']: for fuzzpattern in configopts['stcfuzzpatterns']: fuzzpatterns.append(fuzzpattern) if 'yara' in configopts['inspectionmodes']: for yararuleobj in configopts['stcyararules']: yararuleobjects.append(yararuleobj) if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.UDP#%d] %s %s %s [%dB] { TRACKED: %d } { CTS: %dB, STC: %dB, TOT: %dB }' % ( openudpflows[key]['ipct'], openudpflows[key]['id'], key, directionflag, keydst, count, len(openudpflows), openudpflows[key]['ctsdatasize'], openudpflows[key]['stcdatasize'], openudpflows[key]['totdatasize'])) if not configopts['linemode']: if configopts['udpdone']: if configopts['tcpdone']: if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('Done inspecting max packets (%d) and max streams (%d), \ preparing for exit' % ( configopts['maxinsppackets'], configopts['maxinspstreams'])) exitwithstats() else: if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('Ignoring packet %s:%s %s %s:%s { inspudppacketct: %d == maxinsppackets: %d }' % ( src, sport, dst, dport, configopts['inspudppacketct'], configopts['maxinsppackets'])) return configopts['inspudppacketct'] += 1 if configopts['linemode']: matchstats['addr'] = addrkey matchstats['start'] = start matchstats['end'] = end matchstats['matchsize'] = matchstats['end'] - matchstats['start'] matchstats['direction'] = direction matchstats['directionflag'] = directionflag if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.UDP#%d] Skipping inspection as linemode is enabled.' % ( openudpflows[key]['ipct'], openudpflows[key]['id'])) showudpmatches(data[matchstats['start']:matchstats['end']]) if configopts['writepcap']: markmatchedippackets(addrkey) return if configopts['maxinsppackets'] != 0 and configopts['inspudppacketct'] >= configopts['maxinsppackets']: configopts['udpdone'] = True if configopts['offset'] > 0 and configopts['offset'] < count: offset = configopts['offset'] else: offset = 0 if configopts['depth'] > 0 and configopts['depth'] <= (count - offset): depth = configopts['depth'] + offset else: depth = count inspdata = data[offset:depth] inspdatalen = len(inspdata) if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.UDP#%d] Initiating inspection on %s[%d:%d] - %dB' % ( openudpflows[key]['ipct'], openudpflows[key]['id'], direction, offset, depth, inspdatalen)) matched = inspect('UDP', inspdata, inspdatalen, regexes, fuzzpatterns, yararuleobjects, addrkey, direction, directionflag) if matched: openudpflows[key]['matches'] += 1 if configopts['writepcap']: markmatchedippackets(addrkey) if configopts['writepcapfast']: if addrkey in ippacketsdict.keys() and ippacketsdict[addrkey]['proto'] == 'UDP': ippacketsdict[addrkey]['matched'] = True ippacketsdict[addrkey]['id'] = configopts['packetct'] ippacketsdict[addrkey]['matchedid'] = len(ippacketsdict[addrkey].keys()) - configopts['ipmetavars'] else: ((sip, sp), (dip, dp)) = addrkey newaddrkey = ((dip, dp), (sip, sp)) if newaddrkey in ippacketsdict.keys() and ippacketsdict[newaddrkey]['proto'] == 'UDP': ippacketsdict[newaddrkey]['matched'] = True ippacketsdict[newaddrkey]['id'] = configopts['packetct'] ippacketsdict[newaddrkey]['matchedid'] = len(ippacketsdict[newaddrkey].keys()) - configopts['ipmetavars'] matchstats['start'] += offset matchstats['end'] += offset matchstats['direction'] = direction matchstats['directionflag'] = directionflag if configopts['udpmatches'] == 0: configopts['shortestmatch']['packet'] = matchstats['matchsize'] configopts['shortestmatch']['packetid'] = configopts['packetct'] configopts['longestmatch']['packet'] = matchstats['matchsize'] configopts['longestmatch']['packetid'] = configopts['packetct'] else: if matchstats['matchsize'] <= configopts['shortestmatch']['packet']: configopts['shortestmatch']['packet'] = matchstats['matchsize'] configopts['shortestmatch']['packetid'] = configopts['packetct'] if matchstats['matchsize'] >= configopts['longestmatch']['packet']: configopts['longestmatch']['packet'] = matchstats['matchsize'] configopts['longestmatch']['packetid'] = configopts['packetct'] configopts['udpmatches'] += 1 matchstats['addr'] = addrkey showudpmatches(data[matchstats['start']:matchstats['end']]) del openudpflows[key]
def handleip(pkt): ipmetavars = configopts['ipmetavars'] iphdr = unpack('!BBHHHBBH4s4s', pkt[:20]) ipversion = iphdr[0] >> 4 ipihl = iphdr[0] & 0xF ipihl *= 4 iptos = iphdr[1] iptotallen = iphdr[2] ipid = iphdr[3] ipttl = iphdr[5] ipproto = iphdr[6] ipsrc = socket.inet_ntoa(iphdr[8]) ipdst = socket.inet_ntoa(iphdr[9]) if ipproto == ipprotodict['tcp']: tcphdr = unpack('!HHLLBBHHH', pkt[ipihl:ipihl+20]) tcpsport = tcphdr[0] tcpdport = tcphdr[1] tcpseq = tcphdr[2] tcpack = tcphdr[3] tcpoffset = tcphdr[4] >> 4 tcphl = tcpoffset * 4 tcpflags = tcphdr[5] tcpwindow = tcphdr[6] tcpchksum = tcphdr[7] tcpurgptr = tcphdr[8] data = pkt[ipihl+tcphl:] tcpflagsstr = [] if tcpflags & 1 == 1: tcpflagsstr.append('F') if tcpflags & 2 == 2: tcpflagsstr.append('S') if tcpflags & 4 == 4: tcpflagsstr.append('R') if tcpflags & 8 == 8: tcpflagsstr.append('P') if tcpflags & 16 == 16: tcpflagsstr.append('A') if tcpflags & 32 == 32: tcpflagsstr.append('U') tcpflagsstr = "".join(tcpflagsstr) pktstats = '' fivetuple = ((ipsrc, tcpsport), (ipdst, tcpdport)) revfivetuple = ((ipdst, tcpdport), (ipsrc, tcpsport)) if configopts['writepcap']: if fivetuple in ippacketsdict.keys() and ippacketsdict[fivetuple]['proto'] == 'TCP': key = len(ippacketsdict[fivetuple].keys()) - ipmetavars ippacketsdict[fivetuple][key] = pkt pktstats = 'pktid: %d | ' % (len(ippacketsdict[fivetuple]) - ipmetavars) elif revfivetuple in ippacketsdict.keys() and ippacketsdict[revfivetuple]['proto'] == 'TCP': key = len(ippacketsdict[revfivetuple].keys()) - ipmetavars ippacketsdict[revfivetuple][key] = pkt pktstats = 'pktid: %d | ' % (len(ippacketsdict[revfivetuple]) - ipmetavars) elif tcpflagsstr == 'S': ippacketsdict[fivetuple] = { 'proto': 'TCP', 'id': 0, 'matched':False, 'matchedid': 0, 0: pkt } pktstats = 'pktid: %d | ' % (len(ippacketsdict[fivetuple]) - ipmetavars) else: return if configopts['writepcapfast']: if fivetuple in ippacketsdict.keys() and ippacketsdict[fivetuple]['proto'] == 'TCP': if not ippacketsdict[fivetuple]['matched']: key = len(ippacketsdict[fivetuple].keys()) - ipmetavars ippacketsdict[fivetuple][key] = pkt pktstats = 'pktid: %d | ' % (len(ippacketsdict[fivetuple]) - ipmetavars) else: if (len(ippacketsdict[fivetuple]) - ipmetavars) == (ippacketsdict[fivetuple]['matchedid'] + configopts['pcappacketct']): if configopts['verbose'] and configopts['verboselevel'] >= 2: dodebug('Post match packet collection complete for %s:%s - %s:%s { matchpacket: %d, postpackets: +%d }' % ( ipsrc, tcpsport, ipdst, tcpdport, ippacketsdict[fivetuple]['matchedid'], configopts['pcappacketct'])) writepackets() else: key = len(ippacketsdict[fivetuple].keys()) - ipmetavars ippacketsdict[fivetuple][key] = pkt pktstats = 'pktid: %d | ' % (len(ippacketsdict[fivetuple]) - ipmetavars) elif revfivetuple in ippacketsdict.keys() and ippacketsdict[revfivetuple]['proto'] == 'TCP': if not ippacketsdict[revfivetuple]['matched']: key = len(ippacketsdict[revfivetuple].keys()) - ipmetavars ippacketsdict[revfivetuple][key] = pkt pktstats = 'pktid: %d | ' % (len(ippacketsdict[revfivetuple]) - ipmetavars) else: if (len(ippacketsdict[revfivetuple]) - ipmetavars) == (ippacketsdict[revfivetuple]['matchedid'] + configopts['pcappacketct']): if configopts['verbose'] and configopts['verboselevel'] >= 2: dodebug('Post match packet collection complete for %s:%s - %s:%s { matchpacket: %d, postpackets: +%d }' % ( ipsrc, tcpsport, ipdst, tcpdport, ippacketsdict[revfivetuple]['matchedid'], configopts['pcappacketct'])) writepackets() else: key = len(ippacketsdict[revfivetuple].keys()) - ipmetavars ippacketsdict[revfivetuple][key] = pkt pktstats = 'pktid: %d | ' % (len(ippacketsdict[revfivetuple]) - ipmetavars) elif tcpflagsstr == 'S': ippacketsdict[fivetuple] = { 'proto': 'TCP', 'id': 0, 'matched':False, 'matchedid': 0, 0: pkt } pktstats = 'pktid: %d | ' % (len(ippacketsdict[fivetuple]) - ipmetavars) else: return # if this is a new tcp stream, add it to the opentcpflows table addrkey = ((ipsrc, tcpsport), (ipdst, tcpdport)) tmpaddrkey = ((ipdst, tcpdport), (ipsrc, tcpsport)) if tcpflagsstr == 'S' and addrkey not in opentcpflows: configopts['ipflowsct'] += 1 configopts['streamct'] += 1 opentcpflows.update({addrkey:{ 'ipct': configopts['ipflowsct'], 'id': configopts['streamct'], 'totdatasize': 0, 'insppackets': 0, 'multimatchskipoffset': 0, 'ctspacketlendict': {}, 'stcpacketlendict': {}, } }) count = len(data) if addrkey in opentcpflows: # this tcp/ip packet is travelling from CTS direction opentcpflows[addrkey]['insppackets'] += 1 opentcpflows[addrkey]['ctspacketlendict'].update({ opentcpflows[addrkey]['insppackets']:count }) key = addrkey elif tmpaddrkey in opentcpflows: # this tcp/ip packet is travelling from STC direction opentcpflows[tmpaddrkey]['insppackets'] += 1 opentcpflows[tmpaddrkey]['stcpacketlendict'].update({ opentcpflows[tmpaddrkey]['insppackets']:count }) key = tmpaddrkey else: # this ip flow is untracked, let's not care about it key = None if configopts['verbose'] and configopts['verboselevel'] >= 2 and key in opentcpflows: dodebug('[IP#%d.TCP#%d] %s:%s %s %s:%s { %sflags: %s, seq: %d, ack: %d, win: %d, len: %dB }' % ( opentcpflows[key]['ipct'], opentcpflows[key]['id'], ipsrc, tcpsport, configopts['ctsdirectionflag'], ipdst, tcpdport, pktstats, tcpflagsstr, tcpseq, tcpack, tcpwindow, len(data))) elif ipproto == ipprotodict['udp']: udphdr = unpack('!HHHH', pkt[ipihl:ipihl+UDPHDRLEN]) udpsport = udphdr[0] udpdport = udphdr[1] udplen = udphdr[2] data = pkt[ipihl+UDPHDRLEN:] pktstats = '' fivetuple = ((ipsrc, udpsport), (ipdst, udpdport)) revfivetuple = ((ipdst, udpdport), (ipsrc, udpsport)) if configopts['writepcap']: if fivetuple in ippacketsdict.keys() and ippacketsdict[fivetuple]['proto'] == 'UDP': key = len(ippacketsdict[fivetuple].keys()) - ipmetavars ippacketsdict[fivetuple][key] = pkt pktstats = 'pktid: %d | ' % (len(ippacketsdict[fivetuple]) - ipmetavars) elif revfivetuple in ippacketsdict.keys() and ippacketsdict[revfivetuple]['proto'] == 'UDP': key = len(ippacketsdict[revfivetuple].keys()) - ipmetavars ippacketsdict[revfivetuple][key] = pkt pktstats = 'pktid: %d | ' % (len(ippacketsdict[revfivetuple]) - ipmetavars) else: ippacketsdict[fivetuple] = { 'proto': 'UDP', 'id': 0, 'matched':False, 'matchedid': 0, 0: pkt } pktstats = 'pktid: %d | ' % (len(ippacketsdict[fivetuple]) - ipmetavars) if configopts['writepcapfast']: if fivetuple in ippacketsdict.keys() and ippacketsdict[fivetuple]['proto'] == 'UDP': if not ippacketsdict[fivetuple]['matched']: key = len(ippacketsdict[fivetuple].keys()) - ipmetavars ippacketsdict[fivetuple][key] = pkt pktstats = 'pktid: %d | ' % (len(ippacketsdict[fivetuple]) - ipmetavars) else: if (len(ippacketsdict[fivetuple]) - ipmetavars) == (ippacketsdict[fivetuple]['matchedid'] + configopts['pcappacketct']): if configopts['verbose'] and configopts['verboselevel'] >= 2: dodebug('Post match packet collection complete for %s:%s - %s:%s { matchpacket: %d, postpackets: +%d }' % ( ipsrc, udpsport, ipdst, udpdport, ippacketsdict[fivetuple]['matchedid'], configopts['pcappacketct'])) writepackets() else: key = len(ippacketsdict[fivetuple].keys()) - ipmetavars ippacketsdict[fivetuple][key] = pkt pktstats = 'pktid: %d | ' % (len(ippacketsdict[fivetuple]) - ipmetavars) elif revfivetuple in ippacketsdict.keys() and ippacketsdict[revfivetuple]['proto'] == 'UDP': if not ippacketsdict[revfivetuple]['matched']: key = len(ippacketsdict[revfivetuple].keys()) - ipmetavars ippacketsdict[revfivetuple][key] = pkt pktstats = 'pktid: %d | ' % (len(ippacketsdict[revfivetuple]) - ipmetavars) else: if (len(ippacketsdict[revfivetuple]) - ipmetavars) == (ippacketsdict[revfivetuple]['matchedid'] + configopts['pcappacketct']): if configopts['verbose'] and configopts['verboselevel'] >= 2: dodebug('Post match packet collection complete for %s:%s - %s:%s { matchpacket: %d, postpackets: +%d }' % ( ipsrc, udpsport, ipdst, udpdport, ippacketsdict[revfivetuple]['matchedid'], configopts['pcappacketct'])) writepackets() else: key = len(ippacketsdict[revfivetuple].keys()) - ipmetavars ippacketsdict[revfivetuple][key] = pkt pktstats = 'pktid: %d | ' % (len(ippacketsdict[revfivetuple]) - ipmetavars) else: ippacketsdict[fivetuple] = { 'proto': 'UDP', 'id': 0, 'matched':False, 'matchedid': 0, 0: pkt } pktstats = 'pktid: %d | ' % (len(ippacketsdict[fivetuple]) - ipmetavars) keya = "%s:%s" % (ipsrc, udpsport) keyb = "%s:%s" % (ipdst, udpdport) if udpdport <= 1024 and udpsport >= 1024: key = keya keydst = keyb else: key = keyb keydst = keya if key not in openudpflows: configopts['ipflowsct'] += 1 configopts['packetct'] += 1 openudpflows.update({ key:{ 'ipct': configopts['ipflowsct'], 'id':configopts['packetct'], 'keydst':keydst, 'matches':0, 'ctsdatasize':0, 'stcdatasize':0, 'totdatasize':0, } }) if configopts['verbose'] and configopts['verboselevel'] >= 2 and key in openudpflows: dodebug('[IP#%d.UDP#%d] %s %s %s [%dB]' % ( openudpflows[key]['ipct'], openudpflows[key]['id'], key, configopts['ctsdirectionflag'], keydst, len(data)))
def handleudp(addr, payload, pkt): showmatch = False addrkey = addr ((src, sport), (dst, dport)) = addr count = len(payload) start = 0 end = count data = payload if len(configopts['ctsregexes']) > 0 or len( configopts['ctsfuzzpatterns']) > 0 or len( configopts['ctsyararules']) > 0: inspectcts = True else: inspectcts = False if len(configopts['stcregexes']) > 0 or len( configopts['stcfuzzpatterns']) > 0 or len( configopts['stcyararules']) > 0: inspectstc = True else: inspectstc = False keya = "%s:%s" % (src, sport) keyb = "%s:%s" % (dst, dport) key = None if keya in openudpflows: key = "%s:%s" % (src, sport) keydst = "%s:%s" % (dst, dport) direction = configopts['ctsdirectionstring'] directionflag = configopts['ctsdirectionflag'] elif keyb in openudpflows: key = "%s:%s" % (dst, dport) keydst = "%s:%s" % (src, sport) direction = configopts['stcdirectionstring'] directionflag = configopts['stcdirectionflag'] if key in openudpflows and openudpflows[key]['keydst'] == keydst: openudpflows[key]['totdatasize'] += count else: if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo( '[IP#%d.UDP#%d] %s:%s - %s:%s remains untracked { IP tracking missed this flow }' % (openudpflows[key]['ipct'], openudpflows[key]['id'], src, sport, dst, dport)) regexes = [] fuzzpatterns = [] yararuleobjects = [] timestamp = datetime.datetime.fromtimestamp( nids.get_pkt_ts()).strftime('%H:%M:%S | %Y/%m/%d') if direction == configopts['ctsdirectionstring']: openudpflows[key]['ctsdatasize'] += count if 'regex' in configopts['inspectionmodes']: for regex in configopts['ctsregexes']: regexes.append(regex) if 'fuzzy' in configopts['inspectionmodes']: for fuzzpattern in configopts['ctsfuzzpatterns']: fuzzpatterns.append(fuzzpattern) if 'yara' in configopts['inspectionmodes']: for yararuleobj in configopts['ctsyararules']: yararuleobjects.append(yararuleobj) elif direction == configopts['stcdirectionstring']: openudpflows[key]['stcdatasize'] += count if 'regex' in configopts['inspectionmodes']: for regex in configopts['stcregexes']: regexes.append(regex) if 'fuzzy' in configopts['inspectionmodes']: for fuzzpattern in configopts['stcfuzzpatterns']: fuzzpatterns.append(fuzzpattern) if 'yara' in configopts['inspectionmodes']: for yararuleobj in configopts['stcyararules']: yararuleobjects.append(yararuleobj) if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo( '[IP#%d.UDP#%d] %s %s %s [%dB] { TRACKED: %d } { CTS: %dB, STC: %dB, TOT: %dB }' % (openudpflows[key]['ipct'], openudpflows[key]['id'], key, directionflag, keydst, count, len(openudpflows), openudpflows[key]['ctsdatasize'], openudpflows[key]['stcdatasize'], openudpflows[key]['totdatasize'])) if not configopts['linemode']: if configopts['udpdone']: if configopts['tcpdone']: if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo( 'Done inspecting max packets (%d) and max streams (%d), \ preparing for exit' % (configopts['maxinsppackets'], configopts['maxinspstreams'])) exitwithstats() else: if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo( 'Ignoring packet %s:%s %s %s:%s { inspudppacketct: %d == maxinsppackets: %d }' % (src, sport, dst, dport, configopts['inspudppacketct'], configopts['maxinsppackets'])) return configopts['inspudppacketct'] += 1 if configopts['linemode']: matchstats['addr'] = addrkey matchstats['start'] = start matchstats['end'] = end matchstats['matchsize'] = matchstats['end'] - matchstats['start'] matchstats['direction'] = direction matchstats['directionflag'] = directionflag if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo( '[IP#%d.UDP#%d] Skipping inspection as linemode is enabled.' % (openudpflows[key]['ipct'], openudpflows[key]['id'])) showudpmatches(data[matchstats['start']:matchstats['end']]) if configopts['writepcap']: markmatchedippackets(addrkey) return if configopts['maxinsppackets'] != 0 and configopts[ 'inspudppacketct'] >= configopts['maxinsppackets']: configopts['udpdone'] = True if configopts['offset'] > 0 and configopts['offset'] < count: offset = configopts['offset'] else: offset = 0 if configopts['depth'] > 0 and configopts['depth'] <= (count - offset): depth = configopts['depth'] + offset else: depth = count inspdata = data[offset:depth] inspdatalen = len(inspdata) if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.UDP#%d] Initiating inspection on %s[%d:%d] - %dB' % (openudpflows[key]['ipct'], openudpflows[key]['id'], direction, offset, depth, inspdatalen)) matched = inspect('UDP', inspdata, inspdatalen, regexes, fuzzpatterns, yararuleobjects, addrkey, direction, directionflag) if matched: openudpflows[key]['matches'] += 1 if configopts['writepcap']: markmatchedippackets(addrkey) if configopts['writepcapfast']: if addrkey in ippacketsdict.keys( ) and ippacketsdict[addrkey]['proto'] == 'UDP': ippacketsdict[addrkey]['matched'] = True ippacketsdict[addrkey]['id'] = configopts['packetct'] ippacketsdict[addrkey]['matchedid'] = len( ippacketsdict[addrkey].keys()) - configopts['ipmetavars'] else: ((sip, sp), (dip, dp)) = addrkey newaddrkey = ((dip, dp), (sip, sp)) if newaddrkey in ippacketsdict.keys( ) and ippacketsdict[newaddrkey]['proto'] == 'UDP': ippacketsdict[newaddrkey]['matched'] = True ippacketsdict[newaddrkey]['id'] = configopts['packetct'] ippacketsdict[newaddrkey]['matchedid'] = len( ippacketsdict[newaddrkey].keys( )) - configopts['ipmetavars'] matchstats['start'] += offset matchstats['end'] += offset matchstats['direction'] = direction matchstats['directionflag'] = directionflag if configopts['udpmatches'] == 0: configopts['shortestmatch']['packet'] = matchstats['matchsize'] configopts['shortestmatch']['packetid'] = configopts['packetct'] configopts['longestmatch']['packet'] = matchstats['matchsize'] configopts['longestmatch']['packetid'] = configopts['packetct'] else: if matchstats['matchsize'] <= configopts['shortestmatch']['packet']: configopts['shortestmatch']['packet'] = matchstats['matchsize'] configopts['shortestmatch']['packetid'] = configopts[ 'packetct'] if matchstats['matchsize'] >= configopts['longestmatch']['packet']: configopts['longestmatch']['packet'] = matchstats['matchsize'] configopts['longestmatch']['packetid'] = configopts['packetct'] configopts['udpmatches'] += 1 matchstats['addr'] = addrkey showudpmatches(data[matchstats['start']:matchstats['end']]) del openudpflows[key]