Chaos

Bitskrieg CTFby smothy

Chaos in the Wire - Forensics

Points: 490 | Flag: BITSCTF{v0l4t1l3_junk_m4th_c4nt_h1d3_th3_trutH} | Solved by: Smothy @ 0xN1umb

hacker vibes

what we got

a single pcap file - chaos.pcap. challenge description is screaming covert channel:

"the transfer mechanism does not rely on the application layer at all" "This is the first time this has happened in 32 years"

so right away we know: data is hidden in TCP/IP headers, not payloads. and "32 years" = 32-bit fields. got it.

the solve

step 1: initial recon

open the pcap up:

bash
tshark -r chaos.pcap -q -z io,phs
frame frames:2516 ip frames:2516 tcp frames:2516 http frames:2 tls frames:2452 data frames:58

2500+ TLS packets to port 443, a couple HTTP packets, standard looking traffic. but then you look closer...

bash
tshark -r chaos.pcap -c 20

every single "TLS" packet comes from a different source IP. one packet per IP. thats not normal lmao. each source IP sends exactly 1 packet to 10.0.0.80:443 and dips. classic covert channel behavior.

step 2: the hint they left us

theres an HTTP request to /network_notes.txt in the pcap. the response says it all:

Understanding TCP Internals Sequence numbers and acknowledgements are 32-bit values. IPv4 addresses are also 32-bit integers when represented numerically. Sometimes metadata carries meaning beyond its intended purpose.

ok so the exfiltrated data is hidden in the 32-bit header fields - sequence numbers, ack numbers, and/or source IPs. the IP Identification field is incrementing (0x0000, 0x0001, 0x0002...) which gives us the packet ordering.

step 3: finding the encoding

this took a min ngl. i tried seq numbers alone, IPs alone, nothing looked right. then i tried XORing the source IP with the TCP sequence number for packet 0:

IP: 0x13EBE706 (19.235.231.6) SEQ: 0x24915BA9 XOR: 0x377ABCAF

wait... 37 7A BC AF - thats the start of a 7z file signature (37 7A BC AF 27 1C). but i only have 4 bytes. what about the ACK number?

IP: 0x13EBE706 ACK: 0x34F7E702 XOR: 0x271C0004

27 1C 00 04 - THATS THE REST OF THE 7Z HEADER

galaxy brain moment

so each packet encodes 8 bytes: XOR(src_ip, tcp_seq) || XOR(src_ip, tcp_ack). the source IP is both the XOR key AND part of the covert channel itself. wild.

step 4: extracting the 7z

python
import subprocess, struct

result = subprocess.run(
    ['tshark', '-r', 'chaos.pcap', '-Y', 'tcp.dstport==443', '-T', 'fields',
     '-e', 'ip.id', '-e', 'ip.src', '-e', 'tcp.seq_raw', '-e', 'tcp.ack_raw'],
    capture_output=True, text=True
)

lines = result.stdout.strip().split('\n')
packets = []
for line in lines:
    parts = line.split('\t')
    ip_id = int(parts[0], 16)
    ip_src = parts[1]
    seq = int(parts[2])
    ack = int(parts[3])
    packets.append((ip_id, ip_src, seq, ack))

packets.sort(key=lambda x: x[0])  # order by IP ID

def ip_to_int(ip):
    octets = ip.split('.')
    return (int(octets[0]) << 24) | (int(octets[1]) << 16) | (int(octets[2]) << 8) | int(octets[3])

data = b''
for _, ip, seq, ack in packets:
    ip_int = ip_to_int(ip)
    data += struct.pack('>I', ip_int ^ seq)
    data += struct.pack('>I', ip_int ^ ack)

with open('extracted.7z', 'wb') as f:
    f.write(data)
bash
$ file extracted.7z
extracted.7z: 7-zip archive data, version 0.4

$ 7z x extracted.7z
Folders: 1
Files: 200

step 5: 200 binaries, 1 flag

inside: a folder called chaos_source/ with 200 stripped ELF binaries. each one has a random name. running one:

bash
$ ./0B1J7ITlqorY
bo

outputs 2 characters. and in the strings of each binary theres a PDB path like C:\Builds\Secret\Target_178\link.pdb - the number gives us the ordering.

python
import subprocess, os, re

results = []
for fname in os.listdir('./extracted/chaos_source/'):
    fpath = f'./extracted/chaos_source/{fname}'

    # get target number from PDB path
    strings_out = subprocess.run(['strings', fpath], capture_output=True, text=True).stdout
    match = re.search(r'Target_(\d+)', strings_out)
    target_num = int(match.group(1))

    # run binary, get output
    result = subprocess.run([fpath], capture_output=True, text=True, timeout=5)
    results.append((target_num, result.stdout))

results.sort()
combined = ''.join([output for _, output in results])
print(combined)
Memory is a funny thing. When I was in the scene, I hardly paid it any mind. I never stopped to think of it as something that would make a lasting impression...BITSCTF{v0l4t1l3_junk_m4th_c4nt_h1d3_th3_trutH} I was thinking about myself...

flag just sitting there in the middle of a lil monologue. love it.

flag

BITSCTF{v0l4t1l3_junk_m4th_c4nt_h1d3_th3_trutH}

victory

tldr

  1. pcap has 2500+ packets each from unique source IPs - covert channel in TCP/IP headers
  2. HTTP hint confirms: data is in 32-bit fields (seq numbers, ack numbers, IPs)
  3. each packet hides 8 bytes: XOR(src_ip, seq) || XOR(src_ip, ack), ordered by IP ID field
  4. extracted data = 7z archive containing 200 ELF binaries
  5. each binary outputs 2 chars, ordered by Target_N in their PDB path
  6. concatenate all outputs = text with flag embedded

genuinely cool challenge tbh. the covert channel using XOR between IP addresses and TCP seq/ack numbers is such a clever exfiltration technique. and then nesting 200 mini-binaries inside? layers on layers fr


smothy out ✌️