HICyberCon CTF 2026
57th of 1,119
3,780 points
62 solves
NxT, NxD
Category
62 writeups
- OuroborosPrototype pollution to a new Function gadget web A deep-merge drops keys named __proto__ but not a nested constructor.prototype, so Object.prototype.formula can be polluted. The preview handler reads formula off a fresh object and runs it through new Function, giving code execution that echoes the flag file back.
- OvergrowthGraphQL alias batching against an OTP web Introspection is off, but error messages leak the whole schema. The rate limit counts HTTP requests, not operations, so one request packed with aliased resetPassword calls brute-forces the reset OTP and takes over the admin account.
- Orphaned ContextSealed incident record left readable web The relay keeps a sealed incident record that should only open in its original context. An orphaned-context bug lets a fresh session read /incidents/IR-7731/seal, and every independently provisioned instance returns the same 51 bytes.
- WhisperBlind regex exfil, then a forged HMAC web The token endpoint passes raw JSON into a MongoDB lookup, so a $regex on the client secret becomes a blind oracle that leaks report-signer's secret one character at a time. The export endpoint's own error spells out the string to sign, and an HMAC over it returns the report.
- Stillwell EstatesAbsolute-path read through path.resolve web The import preview reads a listing's document filename and only rejects the literal "..". path.resolve drops the base directory when the name is absolute, so /proc/self/environ leaks the flag the server deleted from process.env after startup.
- File ViewerZIP symlink to arbitrary file read web The Zip Checker extracts uploads and serves each member back by URL. A ZIP entry stored as a symlink to /app/flag.txt is followed when served, turning the viewer into an arbitrary file read.
- Titan RelayRust VM capsule to a privileged handler pwn A Rust console app runs uploaded capsules as bytecode, after XOR-decrypting them with a position key. A guarded leak plus a signed-index out-of-bounds write reaches a privileged handler that reads /flag.txt through Wine's Z: drive.
- Project MangooKeyless handshake, OOB read, stack pivot pwn The handshake token is a fixed transform of the challenge with no key involved. Query Channel only bounds the index from above, so negative indices leak memory, and the leaked pointers set up a pivot that reaches the flag without gadgets or shellcode.
- LetMeOutJinja2 sandbox escape via NFKC pwn The jail allows one template of at most 170 ASCII characters with three distinct letters. The sandbox checks the raw attribute name but fetches the NFKC-normalised one, so a filter-made Tag string smuggles blocked attributes past the guard.
- Apex EngineTwo TOCTOU races in threaded workers pwn Escrow transfers check the balance, sleep 25 ms, then deduct, so two full-balance orders underflow it into a huge number and buy VIP. Inside the vault, the file filter runs before a second 25 ms sleep, so swapping the shared path to flag.txt mid-stream prints the flag.
- Cold CircuitInvertible 20-round SPN rev The checker hex-decodes 16 bytes and runs them through 20 rounds of key add, S-box and permutation. Two anti-tamper gates can never fire, and every round inverts cleanly, so walking the target backwards gives n0_jtag_needed!!.
- EntitlementSelf-loading ELF with a bytecode VM rev A section-less self-loader decrypts its real image into a memfd and hides the serial check in a private VM whose bytecode key is a hash of the handler code, so a debugger corrupts it. Solving the serial and the activation code makes the binary print the flag after a long modular-squaring delay.
- SnapfileRebuilding a file format from a Crystal binary rev No sample .snap ships with snaptool, so the 104-byte header has to be rebuilt from the validator alone: big-endian section offsets, fixed tags and a custom 64-bit checksum. A file that passes makes the tool print its embedded label, which is the flag.
- The Inner EngineNim binary with a bytecode VM rev A stripped Nim binary XOR-hides its strings and checks a 24-byte activation key inside a custom bytecode VM. Tracing the dispatch chain and unwinding the VM program recovers the key L1c#N0d3_7mQ9f3a2b8c6d1e, which prints the flag.
- Last ExecutionEmulating a fictional core with a trapped manual rev A cold image of an EXE-9 core ships with an operator manual that lies in three places. Recovering each page rotation empirically, correcting the manual and emulating the chained HALTs reproduces the run, and the console's register dump hides one flipped bit.
- Night BatchGnuCOBOL account key rev A stripped GnuCOBOL binary checks an 18-digit account key through a ladder of 23 digit conditions. The 835-digit constant is just ln(2) as filler, and solving the conditions gives the one key that prints the flag.
- Obfuscated FlowFlattened state machine, word by word rev The passkey check is a control-flow-flattened state machine where each state is derived from 4-byte words of the input. Solving the state transitions one word at a time rebuilds the 47-character passkey, which is also the flag.
- Cold BeaconNim key validator solved with z3 rev A Nim implant checks a 24-byte key against 23 table-driven XOR, sum and product constraints plus three extra relations. Every constraint is byte-local, so z3 solves it straight to C0ldB34c0n::unl0ck::7a3f, which unseals the config.
- Epsilon DriftIEEE-754 bit fields and a signed zero rev A gfortran binary takes four doubles as hex and checks their mantissa slices and exponents against paired linear equations, which pin them to 1.1, 2.2 and 3.3000000000000003. The last double has to be a negative zero, which passes the compare but flips the output.
- CipherAndroid vault with a seeded passphrase rev The APK's vault unlocks with a PBKDF2 passphrase that is not stored anywhere. An unused legacy package generates it from a 256-word lexicon and a seed in a small window, so walking that window and checking the HMAC anchor finds the passphrase and decrypts the records.
- VaultKeeperAndroid native seal chain past the decoys rev The APK is packed with fake flags, a honeypot getFlag export and UI gates that don't matter. The real flag is computed inside the native nv_final routine, and reproducing its seal and unseal chain offline gives the 51-byte string.
- Warden's MazeSeed-derived prize token in a Rust maze rev The vault in the middle of the maze is meant to be reached through a render-code indexing bug. Strings show the prize token is derived from a seed rather than random, which explains how the token is built, while the live instance mints the real one on a genuine win.
- Signal LockInverting a BEAM token check rev A stripped Erlang BEAM module checks an 8-byte token through a multiply, rotate and add chain modulo 2^64. Disassembling it with beam_disasm and running the chain backwards gives g4m30v3r, and the module itself returns the flag.
- RocinateLCG orbit and exponent relations crypto Each public value is an LCG term times the flag raised to a known exponent. Recovering the LCG seed turns them into pure powers of the flag mod N, and since the exponents have gcd 1, an extended-Euclid combination of them gives the flag itself.
- CairnA 2^20-step isogeny walk, done fast crypto The key comes from a deterministic isogeny walk of 2^20 sequential steps over GF(p^2), with no shortcuts. Generic root finding would take days, so each step uses one exponentiation to p and a few gcds, bringing the whole walk down to under three hours on one core.
- ChronoGrindNine billion sequential squarings crypto The XOR-masked state file spells out the scheme: square a seed 9e9 times modulo a 2048-bit composite, hash it and use that as a ChaCha20-Poly1305 key. There is no shortcut, so a checkpointed gmpy2 grind runs for about two and a half hours and the tag confirms the key.
- Log Jam70-bit discrete log crypto The Diffie-Hellman group is only a 71-bit prime with a 70-bit subgroup, small enough for PARI's rho-based znlog. The recovered exponent hashes to the AES-GCM key, and the tag verifies on decryption.
- Just Give Me The Flag ManEncoding chain with an Atbash hex alphabet crypto The note is 52 two-character tokens whose letters u to z stand in for hex digits in mirrored order. Reversing the string, Atbashing the letters and hex-decoding starts a chain of base decodes that ends at the flag.
- Cipher CascadeReverse, Base64, hex, ROT13 crypto The hint gives the outer layers in order. Reversing the string, Base64-decoding and hex-decoding leaves ROT13 text, and one more rotation gives the flag.
- TycoFranklin-Reiter related messages crypto The flag and the flag plus a known offset are both encrypted under the same N and a 16-bit e. A polynomial gcd of the two degree-56263 relations over Z/N collapses to x - r, and r is the flag.
- Broken SignalsZeroed PNG signature forensics The file is a PNG whose first four signature bytes have been zeroed, while the chunks and CRCs are intact. Restoring \x89PNG makes it open, and the image shows the flag.
- Ghost in the WireOne byte per ICMP echo forensics Echo requests from 10.13.37.1 each carry a single byte of exfiltrated data. Filtering on that source and joining the payloads gives the flag.
- Memory LiarDKOM-hidden process in a memory image forensics The clean audit log and process list in the dump are bait. Grepping every .exe name in the raw image turns up winxnet.exe, which a DKOM rootkit had unlinked from the active process list, and its structure holds the flag.
- Ghost in RAMXOR-hidden flag in a 2 GB QEMU core forensics The image is a full QEMU guest core dump. The consecutive-byte XOR signature of hiCTF{ is the same for every key, so one pass finds every single-byte XOR candidate, and past two bait flags the real one sits under key 0x5a.
- Forgotten SecretsSingle-byte XOR under decoy strings forensics The 256 KiB dump is full of decoy strings and fake credentials. Brute-forcing all 256 single-byte XOR keys finds the flag under key 0x42.
- Echoes of a Forgotten CanvasFour nested stego layers forensics The PNG decodes to 500 more rows than its header claims, with half the flag in the alpha channel. A ZIP after IEND, a steghide payload keyed by the poem and an over-tall JPEG scan give up the rest.
- Roof of Africasteghide keyed by Kilimanjaro forensics The hint points to the mountain's most famous number. Kilimanjaro's height, 5895, is the steghide passphrase.
- Zanzibar Whispersteghide with an empty passphrase forensics The JPEG carries a steghide payload with no passphrase at all, so extracting with an empty password gives the flag.
- Whispers in the MarginWhitespace bit rows in a DOCX forensics The DOCX ends in paragraphs of nothing but spaces and tabs. Reading each as a 12-bit row, with space as 0 and tab as 1, gives a key that opens the second layer in the JPEG.
- Paper TrailAES hidden in invisible TJ kerning forensics Comparing the PDF with its archived original shows four new invisible-text streams whose only content is integer kerning values. The long runs are AES-128-CBC ciphertext, and the key and IV are the two halves of the trailer /ID that the author changed.
- Hall of MirrorsAudio stego, a tiny VM and a nonce lattice forensics A spectrogram in a 26-minute WAV draws a SplitMix64 key that selects the stego bits. The payload is a small VM program whose output leaks biased ECDSA nonces, and a hidden-number lattice recovers the private key that decrypts the flag.
- No Bit Sings AloneSpectrogram, matrix embedding, inverse NTT forensics The spectrogram gives an AES-GCM nonce and ciphertext. Guide tones set the step size for Hamming(31,26) matrix embedding in the left channel's LSBs, and an inverse NTT over GF(257) turns the recovered values into the AES key.
- Dead AirMorse, spectrogram glyphs and Vigenere forensics One stereo channel is Morse giving the key NIGHTJAR, and the other draws a 7z password in its spectrogram. The logbook glyphs map through the code pad to ciphertext, and Vigenere over a 37-symbol alphabet decodes the message.
- RESURRECTION (Operation Eclipse Void)Five NTFS recovery phases forensics A scorched 1 GiB NTFS image hides five payload segments behind five different recovery techniques. Each segment carries an ordinal label that is only an ordering tag, so stripping the labels and joining the payloads gives the flag.
- TESSERAUTF-16 ScriptBlock logs and NTFS metadata forensics The attacker's whole PowerShell script sits in the ScriptBlock log as mixed-endian UTF-16, which ASCII scans miss. Its three labelled parts map onto the riddle's ALPC port, Session 0 profile and reparse-point clues.
- Tasmota VaultBerry bytecode, LittleFS and MQTT forensics An ESP32 Tasmota flash image holds a LittleFS vault and a custom Berry agent. Decoding the agent's unseal routine from bytecode and replaying its KDF and AEAD with the epoch and nonce from the MQTT capture opens the sealed record.
- The Miner That Mined The Victim14-question Windows incident triage forensics A cracked crypto miner from LimeWire encrypts files and disables Defender. Answering all 14 questions takes the event logs, Sysmon, the Recycle Bin $I files and resident MFT data.
- The Quiet DivideEscrowed keylogs, QUIC and a sealed case forensics Two escrow shares in the capture XOR into TLS keylogs that decrypt two QUIC sessions. The vault API also serves its own reference SDK, and following it through evidence hashing, archive decryption and fragment unmasking opens the one committee seal that authenticates.
- Low Tide LedgerPinning an apartment from a recovered call osint Riddles about reclaimed land, an Atlantic view and a fixed UTC+1 clock lead to Eko Atlantic in Lagos. The agency comes from the original business name on an old 360 degree tour of the Eko Pearl Towers pin.
- Shadow IdentityNaming the face on a pageant poster osint The poster is clean of metadata and hidden data, so it comes down to the face. Reverse searching a crop of it with the Miss Grand Tanzania caption finds the real person behind the AI-styled poster.
- The Foxglove TraceRebuilding a lost Wi-Fi tracker's scoring osint The tracker script is gone, but its notes, config and one good run log pin down the rules: keep rows with step_delta of at least 41 and weight each AP's signal. Rescoring the scan export puts FoxgloveCoffee_Guest on top.
- LabyrinthLearning a binary protocol from its errors misc The service speaks an undocumented framed protocol, and its own error messages give away the magic, length limit and opcodes. After the nonce probe and transform challenge, the maze gate wants the shortest path back as raw bytes.
- The Collector's TrailSix paintings, six stego fragments misc Each of six museum images hides a sealed fragment in a different way. Ordering them by the artists' birth years and running them through HKDF opens the cabinet, whose stego PNG points at a GitHub release holding the final key.
- C3 VaultESP32-C3 flash and NVS decryption misc The eFuse dump holds the flash encryption key, and the decrypted NVS gives the device ID, generation and current vault seed. Rebuilding the HMAC challenge-response from the firmware lets us authenticate to the live vault as the gateway.
- Cold ChainFixing a refrigeration controller that fights back misc A forced-defrost schedule keeps six cases warm, and a macro re-enables it every 90 seconds. Authenticating with the leaked fleet key, killing the macro first and then the schedule, and holding the cases cold for 60 seconds returns the flag.
- Ground StationFirmware challenge-response, then a fix that sticks misc Reversing gsc-fw.bin gives the access routine, verified against the image signature it prints. Feeding the session nonce as the key authenticates as engineer, and the fueling fix then has to be persisted past the watchdog.
- Standing OrderReentrancy across two redemption paths misc The same committee signature is valid on both voucher paths, and disburse() pays out before marking the voucher used. A contract that re-enters disburse() from receive() drains the reserve 1 ether at a time.
- Quiet UpgradeProxy storage slot collision misc The proxy keeps its admin in slot 0, and the implementation's open registerBranch() writes slot 0 through delegatecall. Taking admin that way and upgrading to a malicious implementation lets us release the treasury's reserve.
- Hollow ReserveFlash loan against a spot-price oracle misc The credit facility prices collateral off a thin AMM pool's spot price. A flash loan skews the pool, the inflated price lets us borrow far past fair value, and the vault drops below 10 percent of its reserve.
- Pruned LedgerRebuilding a case file from a replayed chain misc Replaying the archived transactions rebuilds the pruned chain. The four case-file fields come from contract code, the only non-reverted configure() calldata, a derived storage slot and a revert that leaks the unmasked note.
- GhostBusUART nonce and a word-swapped AES record misc The secure element hands the same 16-byte nonce to every read on the UART capture. Hashed with a salt from the firmware it gives the AES key, and the sealed record in SPI flash decrypts once each 4-byte word is byte-swapped.
- Dormant SignerECDSA nonce reuse unmasks an escrow misc Two authorizers' co-signatures share an r value, which leaks the signer's private key. Re-signing the liveness digest rebuilds the escrow mask, and XORing it off the masked secret in a replayed chain's storage gives the flag.
No writeups in this category.