Atexit hardening
As said in its manpage:
The
atexit()
function registers the given function to be called at program exit, whether viaexit(3)
or via return from the program’smain()
. Functions so registered are called in reverse order; no arguments are passed. At least 32 functions can always be registered, and more are allowed as long as sufficient memory can be allocated.
In the glibc, the
pointers to the function are obfuscated with a rol
+xor
via the PTR_MANGLE
macro against a secret, which is roughly equivalent to what Windows is
doing.
This mitigation is completely bypassed with an
arbitrary read: get the secret, obfuscate the pointer to your payload, done.
On OpenBSD,
the pointers are stored in a read-only memory zone, only made writeable when
__cxa_atexit
is called. To bypass this, an attacker would need to get code
execution to modify the permissions of the memory zone.
It was added in 2002 by Daniel Hartmeier, with help for Theo de Raadt. It’s a pretty cool mitigation, completely killing this vector.