Almost every pwn CTF challenge, no matter how it's dressed up, comes down to the same idea: get the program to jump to an address of your choosing instead of the one it was supposed to return to. Understanding what a return address actually is makes the rest of binary exploitation click into place.
How a normal function call works
When function A calls function B, the CPU needs to remember where to continue once B finishes — it can't just forget where it came from. Before jumping into B, the call instruction pushes the address of the instruction right after itself onto the stack. That saved address is the return address. When B finishes and executes ret, the CPU pops that address back off the stack and jumps to it — execution picks up exactly where it left off in A.
Why it sits where it does
The return address is stored on the stack, right next to the local variables of the function that's currently running. That adjacency is the whole vulnerability: a local buffer and the return address live in the same contiguous block of memory, separated only by however many bytes of padding the compiler happened to use.
What happens when it's overwritten
If a function writes past the end of one of its own local buffers — because it never checked the length of what it copied in — it can keep writing right through that padding and overwrite the return address itself with arbitrary bytes. The function's own code hasn't changed at all; only the note saying where to go next has. When it executes ret, it faithfully jumps to whatever address is now sitting there — attacker-chosen, not the real caller.
Why this is worth controlling
Redirecting execution is powerful precisely because the attacker doesn't need to inject new code to make something happen — redirecting to a function that already exists in the binary (print a flag, call a shell) is often enough. Modern defenses like stack canaries, ASLR, and non-executable stacks each target one specific part of this chain, which is why later pwn challenges stack several of these together instead of relying on just one.
Wrapping up
This is the theory behind the mechanics in our basic buffer overflow tutorial — read that for the hands-on version of overwriting one of these yourself, and see pwntools for the library that builds these payloads for you.