Lukas' Notes

security memory

Definition

Return-to-libc (ret2libc)

Return-to-libc is a subset of ROP in which the attacker chains together libc functions rather than arbitrary gadgets. The target functions are high-level routines already present in the standard C library — system, open, read, write — which let a short chain perform an effect (run a shell, open a file, exfiltrate data) that would otherwise need many small gadgets.

16-byte Alignment Pitfall

GCC assumes the stack is 16-byte aligned on calls

GCC-generated code assumes that on entry to a function the stack pointer is 16-byte aligned — that rsp ends in a 0 nibble. Some SSE instructions issued inside libc enforce this: the movaps (AVX2) instruction used inside system segfaults if rsp is misaligned.

A naive ret2libc chain overwrites the saved rip and pushes an odd number of 8-byte words afterwards, so by the time system is reached rsp ends in 8 rather than 0 — and system crashes before doing anything useful. The misalignment comes from the chain’s own arithmetic, not from the bug.

Fix

Add a ret to slide the stack by 8 bytes

Insert a lone ret gadget into the chain so that one extra add rsp, 8 happens before system is reached, sliding the stack back into 16-byte alignment:

 & (pop rdi ; ret)        ← load rdi with the string address
 & "/bin/sh"              ← argument for system
 & (ret)                  ← alignment gadget
 & system                 ← system("/bin/sh") with rsp aligned

The fix is mechanical — count the pops in the chain, and if the count is odd, prepend or interpose one more ret to make it even.

Example

system("/bin/sh") via ret2libc

With libc addresses known (from a leak — see ASLR), the shortest shell-spawning chain is:

  • a pop rdi ; ret gadget to place "/bin/sh" in rdi;
  • the address of the libc string "/bin/sh" itself;
  • a ret gadget to repair alignment;
  • the address of system.

system("/bin/sh") runs under the program’s privileges, giving the attacker a shell. Contrast this with the shellcode approach — same goal, fewer gadgets, no code executed on the stack.