Posted onEdited onInctfDisqus: Word count in article: 259Reading time ≈1 mins.
An encryption service encrypts plaintext, but blocks encryption of
the impossible_flag_user string. Exploit the ECB mode
implementation to forge an encrypted token that decrypts to this
forbidden value.
Vulnerability
The service uses AES in ECB mode, which has critical
weakness: identical plaintext blocks produce identical ciphertext
blocks. By crafting specific payloads, we can:
Encrypt the first 16 bytes of the target string
Encrypt padding-aligned subsequent bytes
Concatenate the cipher blocks to forge a valid token
Exploit Strategy
The target user is: impossible_flag_user (23 bytes)
Block 1: Encrypt impossible_flag_ (16
bytes) → get first cipher block
Block 2: Encrypt user + PKCS#7 padding
→ get second cipher block
Combine: Concatenate blocks to form forged token →
decrypt equals target
Posted onEdited onInctfDisqus: Word count in article: 175Reading time ≈1 mins.
Socket challenge requiring automation to solve 500 arithmetic
problems programmatically. Use Python with pwntools to interface with
the remote service and automate the solution.
Key Considerations
Library: pwntools for socket communication
Custom delimiter: Uses \r\n instead of
standard \n
Approach: Parse math expressions dynamically and
compute answers
Posted onEdited onInctfDisqus: Word count in article: 118Reading time ≈1 mins.
Identify the flag hidden within error messages of ICMP traffic
captured in a PCAP file.
Vulnerability
ICMP packets (ping replies) can carry data in their payload. The flag
is exfiltrated through ICMP echo replies. ICMP is often overlooked as a
potential data exfiltration channel.
Solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#!/usr/bin/env python3 from scapy.allimport rdpcap from scapy.layers.inet import ICMP
packets = rdpcap("error_reporting.pcap") flag = b""
for p in packets: # ICMP type 0 = Echo Reply (responses to ping requests) if p.haslayer(ICMP) and p[ICMP].type == 0and p.haslayer("Raw"): flag += p["Raw"].load
withopen("flag.jpg", "wb") as f: f.write(flag)
print("[+] Extracted data saved to flag.jpg")
The extracted data is a JPG image containing the flag.
The TLS certificate is transmitted in the handshake and reveals the
public key. If the RSA modulus has been factored previously, the private
key can be recovered.
from cryptography import x509 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey from scapy import dadict from scapy.allimport * from scapy.allimport Raw, load_layer, rdpcap from scapy.layers.inet import IP, TCP from scapy.layers.tls.allimport TLS from scapy.layers.tls.cert import Cert from scapy.layers.tls.handshake import TLSCertificate
for pkt in packets: if pkt.haslayer(Raw): raw = pkt[Raw].load try: tls_parsed = TLS(raw) tls_cert_layer = tls_parsed.getlayer(TLSCertificate) if tls_cert_layer: print("[-] Found TLS Certificate.") cert = tls_cert_layer.certs for _, x509_wrapper in cert: cert_list.append(x509_wrapper) print("[-] Extracted a TLS Certificate.") else: print("[-] Found TLS packet.") except Exception as e: print(f"[-] Error: {e}") continue return cert_list
deffind_matching_private_key(target_modulus: int, keys_directory: str) -> str | None: print(f"[*] Searching for matching private key in {keys_directory} ...")
for key_file in glob(os.path.join(keys_directory, "*")): try: withopen(key_file, "rb") as f: private_key = serialization.load_pem_private_key( f.read(), password=None, backend=default_backend() )
except ValueError as e: print(f"[-] Failed to parse public key: {e}") returnNone
defcheck_pcap(pcap_path): packets = rdpcap(pcap_path) packets.show() for pkt in packets: pkt.show() if pkt.haslayer(Raw): raw = pkt[Raw].load try: print(raw.decode()) except Exception as e: print(f"[-] Error: {e}") continue
if __name__ == "__main__": cert_list = find_cert(PCAP_FILE) print(cert_list) for cert_obj in cert_list: modulus = get_modulus(cert_obj) exponent = get_exponent(cert_obj) print(modulus) print(exponent)
# if modulus: # key_path = find_matching_private_key(modulus, KEYS) # print(key_path)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
[-] Found TLS packet. [-] Found TLS Certificate. [-] Extracted a TLS Certificate. [-] Found TLS packet. [-] Found TLS packet. [-] Found TLS Certificate. [-] Extracted a TLS Certificate. [-] Found TLS packet. [-] Found TLS packet. [-] Found TLS packet. [-] Found TLS packet. [-] Found TLS packet. [[X.509 Cert. Subject:/C=AU/O=247CTF/OU=net125/CN=127.0.0.1, Issuer:/C=AU/O=247CTF/OU=net125/CN=127.0.0.1], [X.509 Cert. Subject:/C=AU/O=247CTF/OU=net125/CN=127.0.0.1, Issuer:/C=AU/O=247CTF/OU=net125/CN=127.0.0.1]] 150140677816147665104219084736753210294673482912091623639530125054379822052662632476220418069658373540642718111649733795871151252404840997598533258881471779382418788567883517594075575444723340506445280678466322096113052425236787558022472785685579744210805862764465110689084328509029822107730392445215781001579 65537 150140677816147665104219084736753210294673482912091623639530125054379822052662632476220418069658373540642718111649733795871151252404840997598533258881471779382418788567883517594075575444723340506445280678466322096113052425236787558022472785685579744210805862764465110689084328509029822107730392445215781001579 65537
try: req = urllib.request.Request(url, headers=headers) with urllib.request.urlopen(req) as response: data = json.loads(response.read().decode("utf-8"))
status = data.get("status", "Unknown") factors = data.get("factors", [])
print(f"[*] Target : {number}") print(f"[*] Status : {status}")
if factors: result = " * ".join([f"{base}^{exp}"for base, exp in factors]) print(f"[*] Factors: {result}") else: print("[!] No factors returned.")
except urllib.error.URLError as e: print(f"[!] Network Error: {e.reason}") except ValueError: print("[!] JSON parsing failed. Did FactorDB change their API?")
p = 11443069641880629381891581986018548808448150675612774441982091938562801238612124445967724562059877882869924090566492089872161438646198325341704520958011761 q = 13120664517031861557695339067275706831429518210212092859212127044658713747906482358428924486662467583986570766086011893335839637764790393666582606794678939 e = 65537
n = p * q phi = (p - 1) * (q - 1) d = pow(e, -1, phi)
key = RSA.construct((n, e, d, p, q)) withopen("private_key.pem", "wb") as f: f.write(key.export_key()) print("Key forged successfully.")
Step 4: Import and Use in Wireshark
Import the generated private key into Wireshark to decrypt the TLS
traffic and recover the flag.
Key Insight
This challenge demonstrates why factorization of RSA moduli is
critical—if a modulus can be factored, the entire RSA cryptosystem is
broken for that key pair. FactorDB maintains a public database of
previously factored numbers.
Posted onEdited onInctfDisqus: Word count in article: 135Reading time ≈1 mins.
A hidden painting is encoded as coordinates. Connect the dots to
reveal the flag.
Vulnerability
Steganography through coordinate encoding. Data is hidden in plain
sight as hex coordinates.
Solution
The challenge provides a file with hex-encoded coordinates:
1 2 3 4
0x4b 0x9d0 0x44 0x974 0x33 0x92 ...
Each line contains X and Y coordinates in hexadecimal format. Use
Python to plot them:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
import matplotlib.pyplot as plt
x_coords = [] y_coords = []
withopen("secret_map.txt", "r") as f: for line in f: line = line.strip() if line: parts = line.split() x_coords.append(int(parts[0], 16)) y_coords.append(-int(parts[1], 16))