ARM64 Exploitation: the Link Register and ret2win
On AArch64 the return address lives in a register, not on the stack — until a non-leaf function saves it. Build the ARM ret2win in a lab and see where the saved link register sits.
Memory safety, from the defender's side
A structured reference to memory-corruption vulnerabilities in C and C++: how stack and heap overflows, use-after-free and integer bugs happen, and how compilers, sanitizers, fuzzers and safer languages stop them.
Memory map
Start with how memory is laid out, learn the classes of bugs that corrupt it, then the layers that prevent, detect, contain and triage them.
Stack, heap, ELF segments and calling conventions: the terrain every bug lives on.
Overflows, use-after-free, double free, integer and format-string bugs, and how to spot them.
Canaries, NX/DEP, ASLR/PIE, RELRO, FORTIFY_SOURCE, CFI, CET and PAC, and how to verify them.
AddressSanitizer, UBSan and coverage-guided fuzzing with libFuzzer and AFL++.
Read signals, backtraces, sanitizer reports and core dumps, and decide what to fix first.
Memory-safe languages, safer C++ and a realistic migration strategy.
A staged, legal path from C and assembly to CTF pwn challenges and security careers.
ret2win, ret2libc, ROP chains, GOT overwrites and format-string primitives, built and defeated in a lab.
AArch64 calling conventions, the link register, ROP on ARM, and the PAC and BTI defences.
Defense in depth
Every mitigation has gaps. Real resilience comes from stacking layers so a bug that slips past one is caught or contained by the next.
Memory-safe languages, bounds-checked APIs, compiler warnings and code review stop bugs from being written.
ASan, UBSan and coverage-guided fuzzing surface the bugs that were written, before an attacker does.
Canaries, NX, ASLR/PIE, RELRO, CFI and shadow stacks make the remaining bugs hard to exploit.
Crash triage, core dumps and deduplication turn field crashes into prioritised fixes.
Latest guides
On AArch64 the return address lives in a register, not on the stack — until a non-leaf function saves it. Build the ARM ret2win in a lab and see where the saved link register sits.
Pointer authentication signs return addresses so a forged one faults; BTI forces indirect branches onto landing pads. How both work, how to enable and verify them, and their limits.
AArch64 gadgets end in ret, which branches to x30 — so the chain is threaded through the link register with ldp gadgets. Build a system("/bin/sh") chain, then watch PAC and BTI break it.
Sometimes you control just one pointer. A one-gadget is a single libc address that calls execve("/bin/sh") — if its register and stack constraints hold. Find one, check the constraints, and use it.
No libc leak, no problem: forge the relocation the dynamic linker reads and make it resolve and call system for you. A pwntools walkthrough — and why Full RELRO ends it.
A seccomp policy that bans execve takes the shell off the table, so attackers switch goals: open the flag, read it, write it back. Build the ORW chain, and see what a tighter policy stops.
Glossary
Short, precise definitions of the terms you will meet in advisories, crash reports and compiler docs.
Editorial line
Understanding exploitation is what makes mitigations make sense. We teach the mechanics at the level a secure coder, reviewer or incident responder needs, and stop short of weaponisation.
What you will find
What we never publish