Systems Security & Exploitation

a use-after-free exploit

Suppose you give a library book back to the front desk, but keep the call slip with its shelf location. Later you walk to that shelf expecting your book — but the librarian has already re-shelved a DIFFERENT book there. You read the wrong book, thinking it is yours. A use-after-free is the program version: a pointer keeps pointing at a heap object after that object has been freed, and the program later reads or writes through that stale pointer.

Here is the chain that turns a bug into an exploit. You call free(p), which returns p's chunk to the allocator but does NOT erase its contents and does NOT change p — p is now a dangling pointer (still holding the old address, still 'usable' in the sense that dereferencing it compiles and runs). The attacker then causes a NEW allocation of the same size, and modern allocators love to hand back the just-freed chunk for locality. They fill that new allocation with data they control — for example a fake object whose first field is a function pointer. Now the program follows the OLD pointer p, believing it still points at the original object, and calls through the attacker-planted function pointer. The freed-then-reclaimed slot has become a controlled read/write primitive, and often a control-flow hijack. This is why C++ objects with vtables are prime targets: the first word is a pointer to the method table.

It matters because use-after-free is, in recent years, the single most common exploited memory bug in large C/C++ codebases such as browsers and kernels — overtaking the classic stack overflow. The honest framing: the fix is not 'check for NULL', because after free() the pointer is NOT null, it is dangling; the discipline is to set the pointer to NULL right after freeing (or use ownership tools that do it for you), and remember that free() neither zeroes the memory nor invalidates other copies of the pointer.

Widget *w = make_widget(); free(w); // w is now dangling, NOT null; memory not erased /* attacker triggers a same-size malloc and fills it with a fake vtable */ w->draw(); // calls through attacker-controlled function pointer

The use happens after the free; the reclaimed slot now holds attacker data masquerading as the old object.

A DOUBLE-FREE (calling free(p) twice) is a sibling bug: the second free corrupts the allocator's free list and can also be steered to an arbitrary write — free() does not detect that p was already freed.

Also called
UAFdangling-pointer exploit釋放後使用懸置指標利用