cybersecurity · advanced · ~15 min · safe pentest lab
Simulate and understand how compiler and runtime stack canaries detect and trap memory corruptions.
Stack canaries are sentinel values placed immediately before stack control data to detect overflows before function return. Defensive architectures also implement manual canary verification in sensitive parser frames.
Implement:
int guarded_buffer_copy(const char *src, size_t src_len, char *dst, size_t dst_cap, uint32_t canary);
Set up a local stack frame containing canaries:
struct frame {
uint32_t head_canary;
char buffer[64];
uint32_t tail_canary;
} f;
f.head_canary = canary and f.tail_canary = canary.src == NULL, dst == NULL, or dst_cap == 0, return -1.src_len >= sizeof(f.buffer) (64 bytes), return -1 without copying (prevent overflow).src_len bytes from src into f.buffer and NUL-terminate (f.buffer[src_len] = '\0').f.head_canary != canary or f.tail_canary != canary, return -2 (canary corruption detected).src_len >= dst_cap, return -1 (dst would overflow).f.buffer to dst and return 0.src: input bytes; src_len: input length; dst: output buffer; dst_cap: destination capacity; canary: sentinel value.
Returns 0 on clean copy, -1 on bounds violation, -2 on canary corruption.
Freestanding C11. Stack canary verification pattern.
#include <stddef.h>
#include <stdint.h>
/* Safely copy src into an internal 64-byte canary-guarded frame, verify canaries,
and copy out to dst. Return 0 on success, -1 on bounds violation, or -2 on canary corruption. */
int guarded_buffer_copy(const char *src, size_t src_len, char *dst, size_t dst_cap, uint32_t canary) {
(void)src; (void)src_len; (void)dst; (void)dst_cap; (void)canary;
return -1;
}
Overwriting buffer without bounds check causing actual stack corruption; forgetting NUL byte.
src_len == 63 fits; src_len == 64 is rejected; corrupted canary returns -2.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.