Files
ctf/2025/byuctf/forensics/mine_over_matter/find_miners.py
2025-06-06 03:13:31 +02:00

53 lines
1.9 KiB
Python

#!/usr/bin/env python3
from collections import defaultdict
def parse_log(file_path):
syn_counts = defaultdict(int)
dest_ips = defaultdict(set)
dest_ports = defaultdict(set)
with open(file_path) as f:
for line in f:
parts = line.strip().split(None, 1)
if len(parts) < 2:
continue
_, rest = parts
fields = rest.split(',')
if len(fields) < 23:
continue
proto = fields[16].lower()
if proto != 'tcp':
continue
flags = fields[22]
# Count only SYN packets (new connection attempts)
if 'S' not in flags:
continue
src_ip = fields[18]
dst_ip = fields[19]
dst_port = fields[21]
syn_counts[src_ip] += 1
dest_ips[src_ip].add(dst_ip)
dest_ports[src_ip].add(dst_port)
return syn_counts, dest_ips, dest_ports
def main():
import argparse
parser = argparse.ArgumentParser(description="Detect hosts with high outbound TCP SYN rates")
parser.add_argument("logfile", help="Path to the router log file")
parser.add_argument("--top", type=int, default=10, help="Number of top hosts to display")
parser.add_argument("--min-conns", type=int, default=5, help="Minimum SYN connections to include")
args = parser.parse_args()
syn_counts, dest_ips, dest_ports = parse_log(args.logfile)
# Sort by SYN count descending
top = sorted(syn_counts.items(), key=lambda x: x[1], reverse=True)
print(f"{'Source IP':<15} {'SYNs':<5} {'Unique Dest IPs':<15} {'Dest Ports'}")
print("-" * 60)
for ip, count in top[:args.top]:
if count < args.min_conns:
continue
print(f"{ip:<15} {count:<5} {len(dest_ips[ip]):<15} {','.join(sorted(dest_ports[ip]))}")
if __name__ == "__main__":
main()