Breathing Void

Eh4x CTFby smothy

Breathing Void - EH4X CTF 2026

Category: Miscellaneous | Points: 388 | Author: N0nchalantAc1d Solved by: Smothy @ 0xN1umb


1GB of dead vacuum. Can you find any life.

We get Breathing_Void.tar.gz. I extract it and... 1.1GB PCAP. Cool. My laptop fan started screaming before Wireshark even finished loading.


Step 1: Don't Open the 1GB PCAP in Wireshark

Seriously. Don't. I did. Waited 4 minutes for it to load, scrolled through a wall of identical TCP packets, learned nothing, and closed it.

Instead, capinfos is your friend:

bash
capinfos Breathing_Void.pcap

This spit out a bunch of stats but the two things that mattered:

4,198,284 packets across two encapsulation types: Ethernet (4,198,011) and Raw IPv4 (273). And then I noticed the capture comment:

File created by merging: File1: massive.pcap File2: decoy_trap.pcap File3: covert_timing_2.pcap me: *reads "massive.pcap" and "decoy_trap.pcap"* me: so 99.99% of this file is literally filler and bait the challenge: "1GB of dead vacuum" me: yeah that tracks

So covert_timing_2.pcap is where the flag lives. The name even tells us the encoding method - covert timing channel. Thanks for the hint, N0nchalantAc1d.


Step 2: Extract the Needle from the Haystack

The 273 Raw IPv4 packets use a different encapsulation type (interface #2), so filtering them out is trivial:

bash
tshark -r Breathing_Void.pcap -Y "frame.interface_id==2" -w covert.pcap

272 packets extracted (one was probably a header). Let's see what they look like:

  • All 272 packets are identical HTTP GET requests: 10.10.10.5010.10.10.200
  • Source port 1337 (nice), destination port 80
  • Same payload every time: GET / HTTP/1.1 Host: ghost.local User-Agent: Chronos-Agent/v0.01-0.10

Every single packet is the same. Same source, same destination, same payload. So the data isn't in the content at all.

Then I looked at the User-Agent again: Chronos-Agent/v0.01-0.10. Chronos = time. v0.01-0.10 = two timing values. The flag is encoded in the delays between packets.


Step 3: Decode the Timing

Extract timestamps and compute inter-packet delays:

bash
tshark -r covert.pcap -T fields -e frame.time_epoch > timestamps.txt
python
times = [float(l.strip()) for l in open("timestamps.txt")]
deltas = [round((times[i+1] - times[i]) * 1000) for i in range(len(times)-1)]
print(sorted(set(deltas)))  # [10, 100]

Exactly two unique delays: 10ms and 100ms. Binary encoding. 0.01 and 0.10 from the User-Agent version string - it was literally telling us the two timing values in seconds.


Step 4: Bits to Flag

Map 100ms → 1 and 10ms → 0. That gives us 271 bits from 272 packets. We need 272 bits (34 bytes × 8) for a clean decode.

Since the flag starts with E (0x45 = 01000101 which starts with 0), prepend a 0 bit to align:

python
times = [float(l.strip()) for l in open("timestamps.txt")]
deltas = [round((times[i+1] - times[i]) * 1000) for i in range(len(times)-1)]

bits = '0' + ''.join(['1' if d == 100 else '0' for d in deltas])

flag = ''
for i in range(0, len(bits), 8):
    flag += chr(int(bits[i:i+8], 2))

print(flag)
EH4X{pc@p5_@re_of+en_mo5+1y_noi5e}

Decoded from leetspeak: "pcaps are often mostly noise". Yeah, 1.1GB of noise hiding 272 packets. Point taken.


What Made This Click

Honestly, the solve was fast once I stopped trying to be smart with Wireshark. The real timeline was:

  1. Extract → try to open in Wireshark → suffer (~5 min)
  2. Run capinfos → see the merge comment → realize 99% is junk (~2 min)
  3. Filter by interface ID → get 272 identical packets (~1 min)
  4. Notice User-Agent timing hint → compute delays → two values → binary (~5 min)
  5. Prepend alignment bit → decode → flag (~3 min)

Total: maybe 15 minutes of actual work. Plus 5 minutes of Wireshark loading screen.


Key Takeaways

  • capinfos before Wireshark. Always. Especially on big PCAPs. The metadata (capture comments, encapsulation types, packet counts per interface) can solve the challenge before you even look at packet data.
  • Different encapsulation types = different sources. When a PCAP has Ethernet AND Raw IPv4, those came from different capture interfaces. Easy filter target.
  • Covert timing channels encode data in the gaps between packets, not in the packets themselves. All packets can be identical - the information is in the rhythm.
  • Read the User-Agent. Chronos-Agent/v0.01-0.10 was basically a cheat code. Two timing values in the version string, named after the god of time. Subtle as a brick.

Flag: EH4X{pc@p5_@re_of+en_mo5+1y_noi5e}

1GB of noise, 272 meaningful packets, 34 bytes of flag. The void wasn't dead after all - it was just breathing very quietly.