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'] == '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 dumpopenstreams(): if len(openudpflows) > 0: print doinfo('Dumping open/tracked UDP streams: %d' % len(openudpflows)) for (key, value) in openudpflows.items(): id = value['id'] keydst = value['keydst'] matches = value['matches'] ctsdatasize = value['ctsdatasize'] stcdatasize = value['stcdatasize'] totdatasize = value['totdatasize'] doinfo('[%08d] %s - %s { CTS: %dB, STC: %dB, TOT: %dB } { matches: %d }' % ( id, key, keydst, ctsdatasize, stcdatasize, totdatasize, matches)) if len(opentcpflows) > 0: print doinfo('Dumping open/tracked TCP streams: %d' % (len(opentcpflows))) for (key, value) in opentcpflows.items(): id = value['id'] ((src, sport), (dst, dport)) = key ctsdatasize = 0 for size in value['ctspacketlendict'].values(): ctsdatasize += size stcdatasize = 0 for size in value['stcpacketlendict'].values(): stcdatasize += size totdatasize = ctsdatasize + stcdatasize doinfo('[%08d] %s:%s - %s:%s { CTS: %dB, STC: %dB, TOT: %dB }' % ( id, src, sport, dst, dport, ctsdatasize, stcdatasize, totdatasize))
def dumpopenstreams(): if len(openudpflows) > 0: print doinfo('Dumping open/tracked UDP streams: %d' % len(openudpflows)) for (key, value) in openudpflows.items(): id = value['id'] keydst = value['keydst'] matches = value['matches'] ctsdatasize = value['ctsdatasize'] stcdatasize = value['stcdatasize'] totdatasize = value['totdatasize'] doinfo( '[%08d] %s - %s { CTS: %dB, STC: %dB, TOT: %dB } { matches: %d }' % (id, key, keydst, ctsdatasize, stcdatasize, totdatasize, matches)) if len(opentcpflows) > 0: print doinfo('Dumping open/tracked TCP streams: %d' % (len(opentcpflows))) for (key, value) in opentcpflows.items(): id = value['id'] ((src, sport), (dst, dport)) = key ctsdatasize = 0 for size in value['ctspacketlendict'].values(): ctsdatasize += size stcdatasize = 0 for size in value['stcpacketlendict'].values(): stcdatasize += size totdatasize = ctsdatasize + stcdatasize doinfo('[%08d] %s:%s - %s:%s { CTS: %dB, STC: %dB, TOT: %dB }' % (id, src, sport, dst, dport, ctsdatasize, stcdatasize, totdatasize))
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 showtcpmatches(data): proto = 'TCP' if configopts['maxdispbytes'] > 0: maxdispbytes = configopts['maxdispbytes'] else: maxdispbytes = len(data) ((src, sport), (dst, dport)) = matchstats['addr'] filename = '%s/%s-%08d-%s.%s-%s.%s-%s' % (configopts['logdir'], proto, opentcpflows[matchstats['addr']]['id'], src, sport, dst, dport, matchstats['direction']) if configopts['writelogs']: writetofile(filename, data) if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] Wrote %dB to %s' % ( opentcpflows[matchstats['addr']]['ipct'], opentcpflows[matchstats['addr']]['id'], matchstats['matchsize'], filename)) if 'quite' in configopts['outmodes']: if matchstats['detectiontype'] == 'regex': pattern = getregexpattern(matchstats['regex']) elif matchstats['detectiontype'] == 'fuzzy': if matchstats['direction'] == 'CTS': pattern = configopts['ctsfuzzpatterns'] else: pattern = configopts['stcfuzzpaterns'] else: pattern = None if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] %s:%s %s %s:%s matches \'%s\' @ [%d:%d] - %dB' % ( opentcpflows[matchstats['addr']]['ipct'], opentcpflows[matchstats['addr']]['id'], src, sport, matchstats['directionflag'], dst, dport, pattern, matchstats['start'], matchstats['end'], matchstats['matchsize'])) return if configopts['maxdispstreams'] != 0 and configopts['dispstreamct'] >= configopts['maxdispstreams']: if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('Skipping outmode parsing { dispstreamct: %d == maxdispstreams: %d }' % ( configopts['dispstreamct'], configopts['maxdispstreams'])) return direction = matchstats['direction'] startpacket = 0 endpacket = 0 if 'meta' in configopts['outmodes']: if configopts['invertmatch']: invertstatus = " (invert)" else: invertstatus = "" id = opentcpflows[matchstats['addr']]['id'] if matchstats['direction'] == 'CTS': packetlendict = opentcpflows[matchstats['addr']]['ctspacketlendict'] else: packetlendict = opentcpflows[matchstats['addr']]['stcpacketlendict'] direction = matchstats['direction'] directionflag = matchstats['directionflag'] start = matchstats['start'] end = matchstats['end'] matchsize = matchstats['matchsize'] totalcount = 0 startpacket = 0 endpacket = 0 if len(packetlendict) == 1: startpacket = packetlendict.keys()[0] endpacket = startpacket else: for (pktid, pktlen) in collections.OrderedDict(sorted(packetlendict.items())).items(): totalcount += pktlen if start <= totalcount and startpacket == 0 and pktlen != 0: startpacket = pktid if end <= totalcount: endpacket = pktid if configopts['verbose'] and configopts['verboselevel'] >= 5: dodebug('(%06d:%06d) start:%d <= totalcount:%06d | end:%d <= totalcount:%06d ... %s|%-5s\t' % ( pktid, pktlen, start, totalcount, end, totalcount, (start <= totalcount), (end <= totalcount))) if endpacket != 0: if configopts['verbose'] and configopts['verboselevel'] >= 5: dodebug('startpacket: %d - endpacket: %d' % (startpacket, endpacket)) break if startpacket > endpacket: startpacket, endpacket = endpacket, startpacket if matchstats['detectiontype'] == 'regex': if direction == configopts['ctsdirectionstring']: regexpattern = configopts['ctsregexes'][matchstats['regex']]['regexpattern'] elif direction == configopts['stcdirectionstring']: regexpattern = configopts['stcregexes'][matchstats['regex']]['regexpattern'] metastr = 'matches regex%s: \'%s\'' % (invertstatus, regexpattern) elif matchstats['detectiontype'] == 'fuzzy': metastr = 'matches \'%s\' %s%s' % (matchstats['fuzzpattern'], matchstats['fuzzmatchdetails'], invertstatus) elif matchstats['detectiontype'] == 'shellcode': metastr = 'contains shellcode [Offset: %d]%s' % (matchstats['shellcodeoffset'], invertstatus) elif matchstats['detectiontype'] == 'yara': metastr = 'matches rule: \'%s\' from %s' % (matchstats['yararulename'], matchstats['yararulefilepath']) else: metastr = '' if not configopts['linemode']: packetstats = ' | packet[%d] - packet[%d]' % (startpacket, endpacket) else: packetstats = '' if configopts['verbose'] and configopts['verboselevel'] >= 1: bpfstr = generate_bpf("TCP", src, sport, directionflag, dst, dport) doinfo('[IP#%d.TCP#%d] BPF: %s' % (opentcpflows[matchstats['addr']]['ipct'], opentcpflows[matchstats['addr']]['id'], bpfstr)) print '[MATCH] (%08d/%08d) [IP#%d.TCP#%d] %s:%s %s %s:%s %s' % ( configopts['insptcppacketct'], configopts['tcpmatches'], opentcpflows[matchstats['addr']]['ipct'], opentcpflows[matchstats['addr']]['id'], src, sport, directionflag, dst, dport, metastr) print '[MATCH] (%08d/%08d) [IP#%d.TCP#%d] match @ %s[%d:%d] (%dB%s)' % ( configopts['insptcppacketct'], configopts['tcpmatches'], opentcpflows[matchstats['addr']]['ipct'], opentcpflows[matchstats['addr']]['id'], direction, start + configopts['inspoffset'], end + configopts['inspoffset'], matchsize, packetstats) if 'print' in configopts['outmodes']: if configopts['colored']: if direction == configopts['ctsdirectionstring']: printable(data[:maxdispbytes], configopts['ctsoutcolor']) elif direction == configopts['stcdirectionstring']: printable(data[:maxdispbytes], configopts['stcoutcolor']) else: printable(data[:maxdispbytes], None) if 'raw' in configopts['outmodes']: if configopts['colored']: print colored(data[:maxdispbytes]) else: print data[:maxdispbytes] if 'hex' in configopts['outmodes']: if configopts['colored']: if direction == configopts['ctsdirectionstring']: hexdump(data[:maxdispbytes], configopts['ctsoutcolor']) elif direction == configopts['stcdirectionstring']: hexdump(data[:maxdispbytes], configopts['stcoutcolor']) else: hexdump(data[:maxdispbytes], None) if configopts['asm4shellcode']: print if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.TCP#%d] Generating disassembled output for %dB of detected shellcode' % ( opentcpflows[matchstats['addr']]['ipct'], opentcpflows[matchstats['addr']]['id'], len(data))) dumpasm(data) configopts['dispstreamct'] += 1 if not configopts['colored']: print
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)))
if args.nosummary: configopts['nosummary'] = True configopts['starttime'] = starttime if not configopts['nobanner']: print '%s' % (banner) print ' %s - %s' % (configopts['name'], configopts['desc']) print ' %s' % configopts['author'] print if not configopts['inspectionmodes'] and not configopts['linemode']: configopts['linemode'] = True if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('Inspection disabled as no mode selected/available') doinfo('Fallback - linemode enabled') print if configopts['writepcapfast'] and configopts['linemode']: configopts['writepcapfast'] = False configopts['writepcap'] = True if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo( 'Fast pcap writing is incompatible with linemode. Using slow pcap writing as fallback.' ) if configopts['writepcapfast'] and configopts['tcpmultimatch']: configopts['writepcapfast'] = False configopts['writepcap'] = True if configopts['verbose'] and configopts['verboselevel'] >= 1:
if args.nosummary: configopts['nosummary'] = True configopts['starttime'] = starttime if not configopts['nobanner']: print '%s' % (banner) print ' %s - %s' % (configopts['name'], configopts['desc']) print ' %s' % configopts['author'] print if not configopts['inspectionmodes'] and not configopts['linemode']: configopts['linemode'] = True if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('Inspection disabled as no mode selected/available') doinfo('Fallback - linemode enabled') print if configopts['writepcapfast'] and configopts['linemode']: configopts['writepcapfast'] = False configopts['writepcap'] = True if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('Fast pcap writing is incompatible with linemode. Using slow pcap writing as fallback.') if configopts['writepcapfast'] and configopts['tcpmultimatch']: configopts['writepcapfast'] = False configopts['writepcap'] = True if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('Fast pcap writing is incompatible with multimatch. Using slow pcap writing as fallback.')
def showudpmatches(data): proto = 'UDP' ((src, sport), (dst, dport)) = matchstats['addr'] key = "%s:%s" % (src, sport) if key not in openudpflows: key = "%s:%s" % (dst, dport) if configopts['maxdispbytes'] > 0: maxdispbytes = configopts['maxdispbytes'] else: maxdispbytes = len(data) filename = '%s/%s-%08d-%s.%s-%s.%s-%s' % (configopts['logdir'], proto, configopts['packetct'], src, sport, dst, dport, matchstats['direction']) if configopts['writelogs']: writetofile(filename, data) if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.UDP#%d] Wrote %dB to %s/%s-%08d.%s.%s.%s.%s' % ( openudpflows[key]['ipct'], openudpflows[key]['id'], matchstats['matchsize'], configopts['logdir'], proto, configopts['packetct'], src, sport, dst, dport)) if 'quite' in configopts['outmodes']: if matchstats['regex']: pattern = getregexpattern(matchstats['regex']) else: pattern = None if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.UDP#%d] %s:%s %s %s:%s matches \'%s\' @ [%d:%d] - %dB' % ( openudpflows[key]['ipct'], openudpflows[key]['id'], src, sport, matchstats['directionflag'], dst, dport, pattern, matchstats['start'], matchstats['end'], matchstats['matchsize'])) return if configopts['maxdisppackets'] != 0 and configopts['disppacketct'] >= configopts['maxdisppackets']: if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('Skipping outmode parsing { disppacketct: %d == maxdisppackets: %d }' % ( configopts['disppacketct'], configopts['maxdisppackets'])) return direction = matchstats['direction'] directionflag = matchstats['directionflag'] if 'meta' in configopts['outmodes']: if configopts['invertmatch']: invertstatus = " (invert)" else: invertstatus = "" start = matchstats['start'] end = matchstats['end'] matchsize = matchstats['matchsize'] if matchstats['detectiontype'] == 'regex': metastr = 'matches regex%s: \'%s\'' % (invertstatus, getregexpattern(matchstats['regex'])) elif matchstats['detectiontype'] == 'shellcode': metastr = 'contains shellcode [Offset: %d]%s' % (matchstats['shellcodeoffset'], invertstatus) elif matchstats['detectiontype'] == 'yara': metastr = 'matches rule: \'%s\' from %s' % (matchstats['yararulename'], matchstats['yararulefilepath']) else: metastr = '' if configopts['verbose'] and configopts['verboselevel'] >= 1: bpfstr = generate_bpf("UDP", src, sport, directionflag, dst, dport) doinfo('[IP#%d.UDP#%d] BPF: %s' % ( openudpflows[key]['ipct'], openudpflows[key]['id'], bpfstr)) print '[MATCH] (%08d/%08d) [IP#%d.UDP#%d] %s:%s %s %s:%s %s' % ( configopts['inspudppacketct'], configopts['udpmatches'], openudpflows[key]['ipct'], openudpflows[key]['id'], src, sport, directionflag, dst, dport, metastr) print '[MATCH] (%08d/%08d) [IP#%d.UDP#%d] match @ %s[%d:%d] (%dB)' % ( configopts['inspudppacketct'], configopts['udpmatches'], openudpflows[key]['ipct'], openudpflows[key]['id'], direction, start, end, matchsize) if 'print' in configopts['outmodes']: if configopts['colored']: if direction == configopts['ctsdirectionstring']: printable(data[:maxdispbytes], configopts['ctsoutcolor']) elif direction == configopts['stcdirectionstring']: printable(data[:maxdispbytes], configopts['stcoutcolor']) else: printable(data[:maxdispbytes], None) if 'raw' in configopts['outmodes']: if configopts['colored']: print colored(data[:maxdispbytes]) else: print data[:maxdispbytes] if 'hex' in configopts['outmodes']: if configopts['colored']: if direction == configopts['ctsdirectionstring']: hexdump(data[:maxdispbytes], configopts['ctsoutcolor']) elif direction == configopts['stcdirectionstring']: hexdump(data[:maxdispbytes], configopts['stcoutcolor']) else: hexdump(data[:maxdispbytes], None) if configopts['asm4shellcode']: print if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.UDP#%d] Generating disassembled output for %dB of detected shellcode' % ( openudpflows[key]['ipct'], openudpflows[key]['id'], len(data))) dumpasm(data) configopts['dispstreamct'] += 1 if not configopts['colored']: print
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 inspect(proto, data, datalen, regexes, fuzzpatterns, yararuleobjects, addrkey, direction, directionflag): if configopts['regexengine'] == 're': import re if configopts['fuzzengine']: from fuzzywuzzy import fuzz if configopts['yaraengine']: import yara if configopts['shellcodeengine']: import pylibemu as emu skip = False matched = False ((src, sport), (dst, dport)) = addrkey if proto == 'TCP': ipct = opentcpflows[addrkey]['ipct'] id = opentcpflows[addrkey]['id'] elif proto == 'UDP': for key in openudpflows.keys(): skey = '%s:%s' % (src, sport) dkey = '%s:%s' % (dst, dport) if skey == key: ipct = openudpflows[key]['ipct'] id = openudpflows[key]['id'] addrkey = skey elif dkey == key: ipct = openudpflows[key]['ipct'] id = openudpflows[key]['id'] addrkey = dkey if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.%s#%d] Received %dB for inspection from %s:%s %s %s:%s' % ( ipct, proto, id, datalen, src, sport, directionflag, dst, dport)) if 'regex' in configopts['inspectionmodes']: for regex in regexes: matchstats['match'] = regex.search(data) if direction == configopts['ctsdirectionstring']: regexpattern = configopts['ctsregexes'][regex]['regexpattern'] elif direction == configopts['stcdirectionstring']: regexpattern = configopts['stcregexes'][regex]['regexpattern'] if matchstats['match'] and not configopts['invertmatch']: matchstats['detectiontype'] = 'regex' matchstats['regex'] = regex matchstats['start'] = matchstats['match'].start() matchstats['end'] = matchstats['match'].end() matchstats['matchsize'] = matchstats['end'] - matchstats['start'] if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.%s#%d] %s:%s %s %s:%s matches regex: \'%s\'' % ( ipct, proto, id, src, sport, directionflag, dst, dport, regexpattern)) return True if not matchstats['match'] and configopts['invertmatch']: matchstats['detectiontype'] = 'regex' matchstats['regex'] = regex matchstats['start'] = 0 matchstats['end'] = datalen matchstats['matchsize'] = matchstats['end'] - matchstats['start'] if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.%s#%d] %s:%s %s %s:%s matches regex (invert): \'%s\'' % ( ipct, proto, id, src, sport, directionflag, dst, dport, regexpattern)) return True if configopts['verbose'] and configopts['verboselevel'] >= 1: if configopts['invertmatch']: invertstatus = " (invert)" else: invertstatus = "" doinfo('[IP#%d.%s#%d] %s:%s %s %s:%s did not match regex%s: \'%s\'' % ( ipct, proto, id, src, sport, directionflag, dst, dport, invertstatus, regexpattern)) if 'fuzzy' in configopts['inspectionmodes']: for pattern in fuzzpatterns: partialratio = fuzz.partial_ratio(data, pattern) if partialratio >= configopts['fuzzminthreshold']: if not configopts['invertmatch']: matched = True matchstr = 'matches' matchreason = '>=' else: matched = False matchstr = 'doesnot match' matchreason = '|' else: if configopts['invertmatch']: matched = True matchstr = 'matches' matchreason = '|' else: matched = False matchstr = 'doesnot match' matchreason = '<' fuzzmatchdetails = "(ratio: %d %s threshold: %d)" % (partialratio, matchreason, configopts['fuzzminthreshold']) if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.%s#%d] %s:%s %s %s:%s %s \'%s\' (ratio: %d %s threshold: %d)' % ( ipct, proto, id, src, sport, directionflag, dst, dport, matchstr, pattern, partialratio, matchreason, configopts['fuzzminthreshold'])) if matched: matchstats['detectiontype'] = 'fuzzy' matchstats['fuzzpattern'] = pattern matchstats['start'] = 0 matchstats['end'] = datalen matchstats['matchsize'] = matchstats['end'] - matchstats['start'] matchstats['fuzzmatchdetails'] = fuzzmatchdetails return True if 'shellcode' in configopts['inspectionmodes']: emulator = emu.Emulator(configopts['emuprofileoutsize']) offset = emulator.shellcode_getpc_test(data) if offset < 0: offset = 0 emulator.prepare(data, offset) emulator.test() matched = False invert = False invertstatus = "" if emulator.emu_profile_output: # shellcode found! if configopts['invertmatch']: matched = True invert = False invertstatus = "" else: matched = True invert = False invertstatus = "" else: # shellcode not found! if configopts['invertmatch']: matched = True invert = True invertstatus = " (invert)" else: matched = False invert = False invertstatus = "" if matched: emulator.free() matchstats['detectiontype'] = 'shellcode' matchstats['shellcodeoffset'] = offset matchstats['start'] = offset matchstats['end'] = datalen matchstats['matchsize'] = matchstats['end'] - matchstats['start'] if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.%s#%d] %s:%s %s %s:%s contains shellcode%s' % ( ipct, proto, id, src, sport, directionflag, dst, dport, invertstatus)) if configopts['emuprofile'] and not invert: filename = '%s-%08d-%s.%s-%s.%s-%s.emuprofile' % ( proto, id, src, sport, dst, dport, direction) data = emulator.emu_profile_output.decode('utf8') if emulator.emu_profile_truncated and configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.%s#%d] Skipping emulator profile output generation as its truncated' % (ipct, proto, id)) else: fo = open(filename, 'w') fo.write(data) fo.close() if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.%s#%d] Wrote %d byte emulator profile output to %s' % (ipct, proto, id, len(data), filename)) return True if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.%s#%d] %s:%s %s %s:%s doesnot contain shellcode%s' % ( ipct, proto, id, src, sport, directionflag, dst, dport, invertstatus)) if 'yara' in configopts['inspectionmodes']: for ruleobj in yararuleobjects: matchstats['start'] = -1 matchstats['end'] = -1 matchstats['yararulenamespace'] = None matchstats['yararulename'] = None matchstats['yararulemeta'] = None matches = ruleobj.match(data=data, callback=yaramatchcallback) if matches: if not configopts['invertmatch']: matched = True else: matched = False else: if configopts['invertmatch']: matched = True else: matched = False if matched: matchstats['detectiontype'] = 'yara' for rule in configopts['ctsyararules']: if rule == ruleobj: matchstats['yararulefilepath'] = configopts['ctsyararules'][rule]['filepath'] for rule in configopts['stcyararules']: if rule == ruleobj: matchstats['yararulefilepath'] = configopts['stcyararules'][rule]['filepath'] if matchstats['start'] == -1 and matchstats['end'] == -1: matchstats['start'] = 0 matchstats['end'] = len(data) matchstats['matchsize'] = matchstats['end'] - matchstats['start'] return True if configopts['verbose'] and configopts['verboselevel'] >= 1: if ruleobj in configopts['ctsyararules']: filepath = configopts['ctsyararules'][ruleobj]['filepath'] elif ruleobj in configopts['stcyararules']: filepath = configopts['stcyararules'][ruleobj]['filepath'] doinfo('[IP#%d.%s#%d] %s:%s %s %s:%s doesnot match any rule in %s' % ( ipct, proto, id, src, sport, directionflag, dst, dport, filepath)) return False
def showudpmatches(data): proto = 'UDP' ((src, sport), (dst, dport)) = matchstats['addr'] key = "%s:%s" % (src, sport) if key not in openudpflows: key = "%s:%s" % (dst, dport) if configopts['maxdispbytes'] > 0: maxdispbytes = configopts['maxdispbytes'] else: maxdispbytes = len(data) filename = '%s/%s-%08d-%s.%s-%s.%s-%s' % ( configopts['logdir'], proto, configopts['packetct'], src, sport, dst, dport, matchstats['direction']) if configopts['writelogs']: writetofile(filename, data) if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo('[IP#%d.UDP#%d] Wrote %dB to %s/%s-%08d.%s.%s.%s.%s' % (openudpflows[key]['ipct'], openudpflows[key]['id'], matchstats['matchsize'], configopts['logdir'], proto, configopts['packetct'], src, sport, dst, dport)) if 'quite' in configopts['outmodes']: if matchstats['regex']: pattern = getregexpattern(matchstats['regex']) else: pattern = None if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo( '[IP#%d.UDP#%d] %s:%s %s %s:%s matches \'%s\' @ [%d:%d] - %dB' % (openudpflows[key]['ipct'], openudpflows[key]['id'], src, sport, matchstats['directionflag'], dst, dport, pattern, matchstats['start'], matchstats['end'], matchstats['matchsize'])) return if configopts['maxdisppackets'] != 0 and configopts[ 'disppacketct'] >= configopts['maxdisppackets']: if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo( 'Skipping outmode parsing { disppacketct: %d == maxdisppackets: %d }' % (configopts['disppacketct'], configopts['maxdisppackets'])) return direction = matchstats['direction'] directionflag = matchstats['directionflag'] if 'meta' in configopts['outmodes']: if configopts['invertmatch']: invertstatus = " (invert)" else: invertstatus = "" start = matchstats['start'] end = matchstats['end'] matchsize = matchstats['matchsize'] if matchstats['detectiontype'] == 'regex': metastr = 'matches regex%s: \'%s\'' % ( invertstatus, getregexpattern(matchstats['regex'])) elif matchstats['detectiontype'] == 'shellcode': metastr = 'contains shellcode [Offset: %d]%s' % ( matchstats['shellcodeoffset'], invertstatus) elif matchstats['detectiontype'] == 'yara': metastr = 'matches rule: \'%s\' from %s' % ( matchstats['yararulename'], matchstats['yararulefilepath']) else: metastr = '' if configopts['verbose'] and configopts['verboselevel'] >= 1: bpfstr = generate_bpf("UDP", src, sport, directionflag, dst, dport) doinfo( '[IP#%d.UDP#%d] BPF: %s' % (openudpflows[key]['ipct'], openudpflows[key]['id'], bpfstr)) print '[MATCH] (%08d/%08d) [IP#%d.UDP#%d] %s:%s %s %s:%s %s' % ( configopts['inspudppacketct'], configopts['udpmatches'], openudpflows[key]['ipct'], openudpflows[key]['id'], src, sport, directionflag, dst, dport, metastr) print '[MATCH] (%08d/%08d) [IP#%d.UDP#%d] match @ %s[%d:%d] (%dB)' % ( configopts['inspudppacketct'], configopts['udpmatches'], openudpflows[key]['ipct'], openudpflows[key]['id'], direction, start, end, matchsize) if 'print' in configopts['outmodes']: if configopts['colored']: if direction == configopts['ctsdirectionstring']: printable(data[:maxdispbytes], configopts['ctsoutcolor']) elif direction == configopts['stcdirectionstring']: printable(data[:maxdispbytes], configopts['stcoutcolor']) else: printable(data[:maxdispbytes], None) if 'raw' in configopts['outmodes']: if configopts['colored']: print colored(data[:maxdispbytes]) else: print data[:maxdispbytes] if 'hex' in configopts['outmodes']: if configopts['colored']: if direction == configopts['ctsdirectionstring']: hexdump(data[:maxdispbytes], configopts['ctsoutcolor']) elif direction == configopts['stcdirectionstring']: hexdump(data[:maxdispbytes], configopts['stcoutcolor']) else: hexdump(data[:maxdispbytes], None) if configopts['asm4shellcode']: print if configopts['verbose'] and configopts['verboselevel'] >= 1: doinfo( '[IP#%d.UDP#%d] Generating disassembled output for %dB of detected shellcode' % (openudpflows[key]['ipct'], openudpflows[key]['id'], len(data))) dumpasm(data) configopts['dispstreamct'] += 1 if not configopts['colored']: print
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]