Return-to-PLT is the ROP variant in which the attacker redirects the saved return address to a library function’s entry in the Procedure Linkage Table (PLT) rather than to the function’s resolved runtime address. Because the PLT lives in the binary’s .plt section and is not randomised when PIE is disabled, its addresses are fixed and require no leak — the technique removes the need for a ASLR libc leak.
How It Works
The PLT is a fixed-address trampoline
The PLT is the jump table the dynamic linker uses to dispatch shared-library calls; calling e.g. system@plt lands in a stub that looks system up through the GOT and jumps to the resolved libc address. From the attacker’s perspective the PLT entry is a function pointer with a fixed address — the binary always has system@plt at the same offset.
A ret2plt chain looks like:
& (pop rdi ; ret) ← load rdi with the string address & "/bin/sh" ← argument for system & system@plt ← jump into the PLT, which dispatches to libc system
The chain achieves system("/bin/sh") without knowing libc’s base, because the attacker never names libc directly — they name system@plt, a symbol in the binary.
Limitation
PLT entries only exist for functions the binary already calls
The PLT is built only from the imported symbols the binary actually uses; the dynamic linker doesn’t populate it for every libc function. If the binary never calls system, system@plt does not exist, and ret2plt cannot call it. This narrows the technique’s reach compared to a fully-leaked ret2libc chain (which can target any symbol in libc) — but ret2plt trades that narrower reach for the convenience of needing no leak at all.