Our WiFi keeps disconnecting. We captured wireless traffic to try and figure out what’s happening, but it’s all temporal zeros to us! I think someone is trying to exploit a WiFi vulnerability.. Can you decrypt the traffic and gain access to the flag?
The hint “temporal zeros” and the context of a WiFi vulnerability strongly suggest the KRACK (Key Reinstallation Attack), specifically CVE-2017-13077.
Vulnerability Analysis: Why “Zeros”?
In a standard WPA2 4-way handshake, the client and AP negotiate a PTK (Pairwise Transient Key). KRACK works by intercepting and replaying Message 3 of the handshake, forcing the client to reinstall an already in-use key. This resets nonces (packet numbers) and replay counters.
For certain versions of wpa_supplicant (notably 2.4 and 2.5), a critical implementation bug exists: when the key is reinstalled, the Temporal Key (TK) is not just reused, but cleared to all zeros.
The captured 802.11 CCMP packets are encrypted using a 16-byte key of \x00 values.
The WPA2 4-way Handshake & PTK
- Message 1: AP sends a random number (ANonce) to the Client.
- Message 2: Client generates its own random number (SNonce), derives the PTK using both Nonces, and sends SNonce to the AP.
- Message 3: AP derives the same PTK, sends the Group Temporal Key (GTK), and instructs the Client to install the PTK.
- Message 4: Client confirms installation with an ACK.
The KRACK attack manipulates Message 3 to trigger the “all-zero” TK bug.
Decryption Methods
Method 1: Wireshark GUI
If you prefer a visual approach, you can configure Wireshark to decrypt the traffic using the zeroed key:
- Open Preferences (
Ctrl + Shift + P). - Go to Protocols -> IEEE 802.11.
- Check “Enable decryption”.
- Click “Edit…” next to Decryption keys.
- Add a new key:
- Key type:
tk - Key:
00000000000000000000000000000000(32 zeros)
- Key type:
Method 2: Scapy Script (CLI)
The following script manually reconstructs the CCM Nonce and decrypts the packets using the zeroed Temporal Key.
import binasciifrom cryptography.hazmat.backends import default_backendfrom cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modesfrom scapy.all import rdpcapfrom scapy.layers.dot11 import Dot11, Dot11CCMP, Dot11QoS
PCAP_FILE = "~/Downloads/00ps.pcap"
def crack_temporal_zeros(pcap_file): print(f"[*] Parsing {pcap_file}...") try: packets = rdpcap(pcap_file) except Exception as e: print(f"[!] File error: {e}") return
# CVE-2017-13077 (KRACK): The bug forces the TK (Temporal Key) to all zeros. tk_all_zeros = b"\x00" * 16
for idx, pkt in enumerate(packets):44 collapsed lines
if not pkt.haslayer(Dot11CCMP): continue
ccmp = pkt[Dot11CCMP]
# 1. Extract Packet Number (PN), 6 bytes pn = bytes([ccmp.PN5, ccmp.PN4, ccmp.PN3, ccmp.PN2, ccmp.PN1, ccmp.PN0])
# 2. Extract Transmitter Address (A2), 6 bytes try: mac_a2 = binascii.unhexlify(pkt[Dot11].addr2.replace(":", "")) except AttributeError: continue
# 3. Extract QoS Priority (TID) priority = b"\x00" if pkt.haslayer(Dot11QoS): tid = pkt[Dot11QoS].TID & 0x0F priority = bytes([tid])
# 4. Construct 13-byte CCM Nonce # Nonce = Priority (1 byte) + MAC A2 (6 bytes) + PN (6 bytes) nonce = priority + mac_a2 + pn
# 5. Assemble CTR Initial Vector (16 bytes) # Flags (0x01) + Nonce (13 bytes) + Counter (0x0001) iv = b"\x01" + nonce + b"\x00\x01"
# 6. Decrypt using AES-CTR (Bypassing MIC check for speed/simplicity) cipher = Cipher( algorithms.AES(tk_all_zeros), modes.CTR(iv), backend=default_backend() ) decryptor = cipher.decryptor()
raw_data = ccmp.data if len(raw_data) <= 8: continue
ciphertext = raw_data[:-8] # Last 8 bytes are the MIC plaintext = decryptor.update(ciphertext) + decryptor.finalize()
try: decoded_text = plaintext.decode("utf-8", errors="ignore") if "247CTF" in decoded_text.upper(): print(f"\n[+] Flag found in packet #{idx + 1}:") print(f" Plaintext: {decoded_text}\n") break except Exception: pass
if __name__ == "__main__": crack_temporal_zeros(PCAP_FILE)Flag
247CTF{[flag redacted]}