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 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)))