1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
| import sys import re import csv from datetime import datetime from scapy.all import rdpcap, Raw, IP, TCP, UDP
RE_NODEID_TEXT = re.compile(rb'ns=\d+;(?:s=[^\s,;\"\']+|i=\d+|g=[0-9A-Fa-f\-]+|b=[A-Za-z0-9+/=]+)')
RE_NODEID_UTF16 = re.compile(rb'(?:n\0s\0=\0\d\0+\0;\0(?:s\0=\0[^\0,;\"\']+\0|i\0=\0\d\0+|g\0=\0[0-9A-Fa-f\-\0]+|b\0=\0[A-Za-z0-9+/=\0]+))', re.IGNORECASE)
def bytes_to_printable(b): try: return b.decode('utf-8', errors='ignore') except: return str(b)
def find_matches_in_payload(payload_bytes): matches = [] for m in RE_NODEID_TEXT.finditer(payload_bytes): try: matches.append(m.group(0).decode('utf-8', errors='ignore')) except: matches.append(str(m.group(0))) for m in RE_NODEID_UTF16.finditer(payload_bytes): try: s = m.group(0).decode('utf-16le', errors='ignore') matches.append(s) except: cleaned = m.group(0).replace(b'\x00', b'').decode('utf-8', errors='ignore') matches.append(cleaned) seen = set() uniq = [] for x in matches: if x not in seen: seen.add(x) uniq.append(x) return uniq
def scan_pcap(path): print(f"[+] 读取 pcap:{path}") pkts = rdpcap(path) results = [] for idx, p in enumerate(pkts, start=1): payload = b'' ts = None src = dst = "" if Raw in p: payload = bytes(p[Raw].load) else: if TCP in p and hasattr(p[TCP], 'payload') and len(bytes(p[TCP].payload))>0: payload = bytes(p[TCP].payload) elif UDP in p and hasattr(p[UDP], 'payload') and len(bytes(p[UDP].payload))>0: payload = bytes(p[UDP].payload)
ts = getattr(p, 'time', None) if ts: timestr = datetime.utcfromtimestamp(ts).strftime('%Y-%m-%dT%H:%M:%SZ') else: timestr = ""
if IP in p: src = p[IP].src dst = p[IP].dst else: src = getattr(p, 'src', '') dst = getattr(p, 'dst', '')
if payload and len(payload) > 0: matches = find_matches_in_payload(payload) if matches: for m in matches: results.append({ 'pkt_index': idx, 'time': timestr, 'src': src, 'dst': dst, 'nodeid': m, }) return results
def print_results(results): if not results: print("[!] 未发现匹配的 NodeId(文本或 UTF-16LE)。若流量加密则需要解密后再分析。") return print(f"[+] 共发现 {len(results)} 条匹配:") for r in results: print(f"#{r['pkt_index']:6d} {r['time']} {r['src']} -> {r['dst']} {r['nodeid']}")
def save_csv(results, outpath): with open(outpath, 'w', newline='', encoding='utf-8') as f: writer = csv.DictWriter(f, fieldnames=['pkt_index','time','src','dst','nodeid']) writer.writeheader() for r in results: writer.writerow(r) print(f"[+] 已保存 CSV: {outpath}")
if __name__ == '__main__': if len(sys.argv) < 2: print("Usage: python find_nodeid_in_pcap.py traffic.pcap [-o out.csv]") sys.exit(1) pcap = sys.argv[1] out = None if len(sys.argv) >= 3 and sys.argv[2] in ('-o','--out') and len(sys.argv) >=4: out = sys.argv[3] res = scan_pcap(pcap) print_results(res) if out: save_csv(res, out)
|