cybersecurity · advanced · ~15 min · safe pentest lab
Recognise the ECB-mode ciphertext fingerprint (repeated plaintext -> repeated ciphertext blocks) and write a bounds-safe detector that validates attacker-controlled length and block-size arguments before indexing, denying malformed input by default.
AES in ECB mode encrypts every plaintext block independently, so identical plaintext blocks always produce identical ciphertext blocks. That determinism is a leak: an attacker who can see the ciphertext learns which plaintext regions repeat (the classic "ECB penguin"). During a defensive assessment you want a detector that flags this fingerprint in captured ciphertext so you can tell a developer their crypto is broken.
Asset: a fixed buffer of captured ciphertext baked into the test harness. Threat: confidentiality loss from block-level plaintext structure leaking through ECB. Your detector only reads that in-memory array — never a live target, socket, or file.
Implement has_ecb_repeats(ct, n, block). Return 1 if any two whole block-sized chunks of ct are byte-for-byte identical, otherwise 0.
The dangerous, insecure assumption to avoid is trusting the caller's sizes. You must deny by default: reject block == 0 and a NULL pointer, and only ever read bytes inside [0, (n / block) * block). A trailing partial block (fewer than block bytes) is ignored, never compared.
block == 0 → return 0 (never divide or index by it).ct == NULL → return 0.n / block < 2) → return 0.n.has_ecb_repeats(repeat, 16, 4) -> 1 /* blocks 0 and 2 are identical */
has_ecb_repeats(distinct, 16, 4) -> 0 /* every block differs */
A pointer ct to n bytes of ciphertext, and a chunk size block. All three are supplied by the (untrusted) caller; sizes may be zero or larger than the buffer's usable region.
Return int 1 if at least two whole block-sized chunks of ct are identical, else 0. Invalid inputs (block==0, NULL) return 0.
ct is ciphertext buffer of n bytes; block is cipher block size.
int has_ecb_repeats(const unsigned char *ct, size_t n, size_t block)
{
/* TODO: detect two identical `block`-sized chunks in ct.
This insecure stub trusts the input and reports nothing. */
(void)ct; (void)n; (void)block;
return -1;
}Division by zero when block is 0 or reading partial trailing blocks.
ct == NULL, block == 0, n < block * 2 (cannot have repeats).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.