#!/usr/bin/env python3
"""
Parse PCAP file manually to find hidden patterns
Focus on packet lengths, ports, and sequence numbers
"""

import struct

def parse_pcap(filename):
    with open(filename, 'rb') as f:
        # Read global header (24 bytes)
        global_header = f.read(24)
        magic = struct.unpack('I', global_header[:4])[0]
        
        print(f"PCAP Magic: {hex(magic)}")
        
        packets = []
        packet_num = 0
        
        while True:
            # Read packet header (16 bytes)
            packet_header = f.read(16)
            if len(packet_header) < 16:
                break
            
            ts_sec, ts_usec, incl_len, orig_len = struct.unpack('IIII', packet_header)
            
            # Read packet data
            packet_data = f.read(incl_len)
            if len(packet_data) < incl_len:
                break
            
            packet_num += 1
            packets.append({
                'num': packet_num,
                'ts_sec': ts_sec,
                'ts_usec': ts_usec,
                'length': incl_len,
                'orig_length': orig_len,
                'data': packet_data
            })
        
        print(f"Total packets parsed: {len(packets)}\n")
        return packets

def parse_ethernet(data):
    """Parse Ethernet frame"""
    if len(data) < 14:
        return None
    
    dst_mac = data[0:6]
    src_mac = data[6:12]
    eth_type = struct.unpack('!H', data[12:14])[0]
    
    return {
        'dst_mac': dst_mac.hex(),
        'src_mac': src_mac.hex(),
        'type': hex(eth_type),
        'payload': data[14:]
    }

def parse_ip(data):
    """Parse IP packet"""
    if len(data) < 20:
        return None
    
    version_ihl = data[0]
    version = version_ihl >> 4
    ihl = (version_ihl & 0x0F) * 4
    
    total_length = struct.unpack('!H', data[2:4])[0]
    protocol = data[9]
    src_ip = '.'.join(map(str, data[12:16]))
    dst_ip = '.'.join(map(str, data[16:20]))
    
    return {
        'version': version,
        'header_len': ihl,
        'total_length': total_length,
        'protocol': protocol,
        'src_ip': src_ip,
        'dst_ip': dst_ip,
        'payload': data[ihl:]
    }

def parse_tcp(data):
    """Parse TCP segment"""
    if len(data) < 20:
        return None
    
    src_port = struct.unpack('!H', data[0:2])[0]
    dst_port = struct.unpack('!H', data[2:4])[0]
    seq_num = struct.unpack('!I', data[4:8])[0]
    ack_num = struct.unpack('!I', data[8:12])[0]
    
    return {
        'src_port': src_port,
        'dst_port': dst_port,
        'seq': seq_num,
        'ack': ack_num
    }

def parse_udp(data):
    """Parse UDP datagram"""
    if len(data) < 8:
        return None
    
    src_port = struct.unpack('!H', data[0:2])[0]
    dst_port = struct.unpack('!H', data[2:4])[0]
    length = struct.unpack('!H', data[4:6])[0]
    
    return {
        'src_port': src_port,
        'dst_port': dst_port,
        'length': length
    }

# Parse the PCAP file
packets = parse_pcap('sniffed.pcap')

print("=" * 80)
print("ANALYZING PACKETS FOR PATTERNS")
print("=" * 80)

# Collect various numeric fields
packet_lengths = []
src_ports = []
dst_ports = []
ip_lengths = []

for pkt in packets:
    eth = parse_ethernet(pkt['data'])
    if eth and eth['type'] == '0x800':  # IPv4
        ip = parse_ip(eth['payload'])
        if ip:
            ip_lengths.append(ip['total_length'])
            
            if ip['protocol'] == 6:  # TCP
                tcp = parse_tcp(ip['payload'])
                if tcp:
                    src_ports.append(tcp['src_port'])
                    dst_ports.append(tcp['dst_port'])
            elif ip['protocol'] == 17:  # UDP
                udp = parse_udp(ip['payload'])
                if udp:
                    src_ports.append(udp['src_port'])
                    dst_ports.append(udp['dst_port'])
    
    packet_lengths.append(pkt['length'])

print(f"Collected {len(packet_lengths)} packet lengths")
print(f"Collected {len(src_ports)} source ports")
print(f"Collected {len(dst_ports)} destination ports")
print(f"Collected {len(ip_lengths)} IP lengths")

# Try different numeric fields as ASCII
print("\n" + "=" * 80)
print("TRYING DESTINATION PORTS AS ASCII:")
print("=" * 80)
ascii_dst = ''.join([chr(p) if 32 <= p <= 126 else f'[{p}]' for p in dst_ports])
print(ascii_dst)

print("\n" + "=" * 80)
print("TRYING SOURCE PORTS AS ASCII:")
print("=" * 80)
ascii_src = ''.join([chr(p) if 32 <= p <= 126 else f'[{p}]' for p in src_ports])
print(ascii_src)

print("\n" + "=" * 80)
print("TRYING IP TOTAL LENGTHS AS ASCII:")
print("=" * 80)
ascii_ip_len = ''.join([chr(p) if 32 <= p <= 126 else f'[{p}]' for p in ip_lengths])
print(ascii_ip_len)

print("\n" + "=" * 80)
print("TRYING PACKET FRAME LENGTHS AS ASCII:")
print("=" * 80)
ascii_pkt_len = ''.join([chr(p) if 32 <= p <= 126 else f'[{p}]' for p in packet_lengths])
print(ascii_pkt_len)

# Show first 30 values of each
print("\n" + "=" * 80)
print("FIRST 30 VALUES:")
print("=" * 80)
print(f"Destination ports: {dst_ports[:30]}")
print(f"Source ports: {src_ports[:30]}")
print(f"IP lengths: {ip_lengths[:30]}")
print(f"Packet lengths: {packet_lengths[:30]}")

# Look for HTB flag pattern
print("\n" + "=" * 80)
print("SEARCHING FOR FLAG PATTERN (HTB{...}):")
print("=" * 80)

for name, values in [("DST_PORTS", dst_ports), ("SRC_PORTS", src_ports), 
                     ("IP_LENGTHS", ip_lengths), ("PKT_LENGTHS", packet_lengths)]:
    text = ''.join([chr(v) if 32 <= v <= 126 else '?' for v in values])
    if 'HTB{' in text:
        print(f"\n🎉 FOUND IN {name}!")
        print(text)
        # Extract flag
        start = text.find('HTB{')
        end = text.find('}', start) + 1
        print(f"\n🚩 FLAG: {text[start:end]}")
        break
else:
    print("No obvious flag found. Showing all decoded data:")
    print(f"\nDST_PORTS: {ascii_dst[:200]}")
    print(f"\nSRC_PORTS: {ascii_src[:200]}")
    print(f"\nIP_LENGTHS: {ascii_ip_len[:200]}")
    print(f"\nPKT_LENGTHS: {ascii_pkt_len[:200]}")
