|
| 1 | +import time, sys, signal, psutil, pyperclip |
| 2 | +from scapy.all import sniff, UDP, IP |
| 3 | +from collections import defaultdict |
| 4 | +from colorama import init, Fore, Style |
| 5 | + |
| 6 | +init(autoreset=True) |
| 7 | + |
| 8 | +INTERVAL = 1 |
| 9 | +THRESHOLD = 250 |
| 10 | +LOG = 'udp_monitor_log.txt' |
| 11 | +TARGET_PROCS = {'cod.exe'} |
| 12 | + |
| 13 | +def cprint(msg, color='green'): |
| 14 | + colors = {'green': Fore.GREEN, 'cyan': Fore.CYAN, 'yellow': Fore.YELLOW, 'red': Fore.RED} |
| 15 | + print(f"{colors.get(color, Fore.WHITE)}{msg}{Style.RESET_ALL}") |
| 16 | + |
| 17 | +def log_line(txt): |
| 18 | + with open(LOG, 'a', encoding='utf-8') as f: |
| 19 | + f.write(txt + "\n") |
| 20 | + |
| 21 | +def run_start(): |
| 22 | + t = time.strftime("%Y-%m-%d %H:%M:%S") |
| 23 | + log_line("\n=====================================") |
| 24 | + log_line(f"=== RUN START: {t} ===") |
| 25 | + log_line("=====================================") |
| 26 | + |
| 27 | +def run_end(): |
| 28 | + t = time.strftime("%Y-%m-%d %H:%M:%S") |
| 29 | + log_line("=====================================") |
| 30 | + log_line(f"=== RUN END: {t} ===") |
| 31 | + log_line("=====================================") |
| 32 | + |
| 33 | +def sigint_handler(sig, frame): |
| 34 | + run_end() |
| 35 | + cprint("\nMonitoring canceled by user.\n", 'red') |
| 36 | + sys.exit(0) |
| 37 | + |
| 38 | +signal.signal(signal.SIGINT, sigint_handler) |
| 39 | + |
| 40 | +def get_ports(proc_names): |
| 41 | + ports = set() |
| 42 | + pnames = {n.lower() for n in proc_names} |
| 43 | + for p in psutil.process_iter(['name']): |
| 44 | + try: |
| 45 | + if p.info['name'] and p.info['name'].lower() in pnames: |
| 46 | + for c in p.net_connections(kind='udp'): |
| 47 | + if c.laddr and c.laddr.port: |
| 48 | + ports.add(c.laddr.port) |
| 49 | + except: |
| 50 | + pass |
| 51 | + return ports |
| 52 | + |
| 53 | +def get_interface(): |
| 54 | + ifaces = psutil.net_io_counters(pernic=True) |
| 55 | + if not ifaces: |
| 56 | + cprint("No network interfaces found.", 'red') |
| 57 | + sys.exit(1) |
| 58 | + return max(ifaces, key=lambda i: ifaces[i].bytes_sent + ifaces[i].bytes_recv) |
| 59 | + |
| 60 | +def sniff_udp(tports, iface, dur): |
| 61 | + data = defaultdict(int) |
| 62 | + def cb(pkt): |
| 63 | + if UDP in pkt and IP in pkt: |
| 64 | + l = len(pkt) |
| 65 | + s_ip, d_ip = pkt[IP].src, pkt[IP].dst |
| 66 | + s_pt, d_pt = pkt[UDP].sport, pkt[UDP].dport |
| 67 | + if s_pt in tports: data[(d_ip, d_pt)] += l |
| 68 | + elif d_pt in tports: data[(s_ip, s_pt)] += l |
| 69 | + flt = " or ".join(f"udp port {p}" for p in tports) if tports else "udp port 0" |
| 70 | + sniff(filter=flt, prn=cb, timeout=dur, iface=iface, store=False) |
| 71 | + return data |
| 72 | + |
| 73 | +def report(d, seen, sec, thr): |
| 74 | + for (ip, port), bcount in d.items(): |
| 75 | + rate = bcount / sec |
| 76 | + if rate >= thr and (ip, port) not in seen: |
| 77 | + t = time.strftime("%Y-%m-%d %H:%M:%S") |
| 78 | + |
| 79 | + # Copy to clipboard, e.g.,: udp 12.34.56.78 120 dport=1234 |
| 80 | + clip_text = f"udp {ip} 120 dport={port}" |
| 81 | + pyperclip.copy(clip_text) |
| 82 | + |
| 83 | + if port == 44998: |
| 84 | + cprint("=====================================", 'red') |
| 85 | + cprint("Rotating IP found", 'red') |
| 86 | + cprint(f"IP Address : {ip}", 'yellow') |
| 87 | + cprint(f"Port : {port}", 'yellow') |
| 88 | + cprint(f"Data Rate : {rate:.2f} B/s", 'green') |
| 89 | + cprint("=====================================", 'red') |
| 90 | + log_line(f"{t} | Rotating IP found | IP={ip}, Port={port}, Rate={rate:.2f} B/s") |
| 91 | + else: |
| 92 | + cprint("=====================================", 'green') |
| 93 | + cprint("=== Live Game Session Found ===", 'cyan') |
| 94 | + cprint(f"IP Address : {ip}", 'yellow') |
| 95 | + cprint(f"Port : {port}", 'yellow') |
| 96 | + cprint(f"Data Rate : {rate:.2f} B/s", 'green') |
| 97 | + cprint("=====================================", 'green') |
| 98 | + log_line(f"{t} | Live Game Session Found | IP={ip}, Port={port}, Rate={rate:.2f} B/s") |
| 99 | + |
| 100 | + seen.add((ip, port)) |
| 101 | + |
| 102 | +def main(): |
| 103 | + cprint("Starting UDP Traffic Monitor...", 'green') |
| 104 | + run_start() |
| 105 | + iface = get_interface() |
| 106 | + seen = set() |
| 107 | + while True: |
| 108 | + tports = get_ports(TARGET_PROCS) |
| 109 | + if not tports: |
| 110 | + cprint("No target UDP ports found for specified processes.", 'yellow') |
| 111 | + time.sleep(INTERVAL) |
| 112 | + continue |
| 113 | + data = sniff_udp(tports, iface, INTERVAL) |
| 114 | + report(data, seen, INTERVAL, THRESHOLD) |
| 115 | + |
| 116 | +if __name__ == "__main__": |
| 117 | + main() |
0 commit comments