6. Random, Debian style
#include <stdlib.h>
#include <stdio.h>
int main() {
srand(1);
int x = rand();
srand(2);
int y = rand();
puts(x == y ? "ok" : "fail");
return !(x == y);
}
7. LD_PRELOAD explained
man ld
#define _GNU_SOURCE - This is needed to be able to use
RTLD_NEXT, see later
#include - no need to explain these
void (*orig_srand)(unsigned int seed); - we define the original
srand here so we can use it later
void srand(unsigned int seed) { - override original srand function
if(!orig_srand) { - don't depend on a constructor to resolve libc's
function, and do it on demand when it's first needed.
8. LD_PRELOAD explained
man dlsym
orig_srand = dlsym(RTLD_NEXT, "srand"); - RTLD_NEXT finds
the next occurrence of a function in the search order after the
current library
dlsym - obtain address of a symbol in a shared object or
executable
assert(orig_srand); - abort program if we don’t have the original
srand
orig_srand(0); - call original srand with a fixed seed of 0
10. Compiling and linking
gcc -Wall -fPIC -shared -o myldpreload.so ldpreload.c -ldl
-Wall – show all warnings
-fPIC – all function calls will be made via the Procedure
Linkage Table – PLT. Otherwise symbol relocations are
internally are resolved at load time, not good.
-shared – create a shared library
-ldl - tells the linker to find and link libdl.so, this is needed
by dlsym
11. Hacking vulnerable webserver
curl -X POST --data-binary @payload.so
http://<IP>/cgi-bin/cgitest?LD_PRELOAD=/proc/self/fd/0 -i
https://www.elttam.com//blog/goahead/
Because CGI was so secure back in 1999
Especially when the executable uses the LD_PRELOAD variable
and accepts it from the GET request
12. Can I privesc with LD_PRELOAD on
setuid/setgid binaries?
No *
* except if Defaults env_keep += LD_PRELOAD
#in suoders
15. Pwnadventure
sudo gdb -p $(pidof PwnAdventure3-Linux-
Shipping)
• p GameWorld
• p *GameWorld
• p *(ClientWorld *) GameWorld
16. Pwnadventure
Print class definition:
− ptype ClientWorld
− ptype Player
copy to libGameLogic.h
p *(Player*)((*(ClientWorld*)GameWorld).m_activePlayer.m_object)
set variable=value
17. Fixing things
std::string vs const char*
std::string is an object holding the string data
const char* is a pointer
health: public vs protected
-std=c++11
19. Frida vs LD_PRELOAD
When to use Frida and when to LD_PRELOAD
Frida is better for quick one-time hacks
LD_PRELOAD is nice when you want to share the
love with everyone
LD_PRELOAD is better when it is used in
production, e.g. a code is fixed
20. Bonus macOS
DYLD_INSERT_LIBRARIES is the LD_PRELOAD
By default, when System Integrity Protection is
enabled and and the program has the
CS_RESTRICT flag (Apple shipped binaries),
DYLD_INSERT_LIBRARIES will not work
Sad Panda
22. Prevent LD_PRELOAD
• statically link your program
• setuid/setgid set
• check for the LD_PRELOAD environment
variable, and complain
○ the attacker could also LD_PRELOAD the
function that lets you read environment
variables… :)
23. Prevent
DYLD_INSERT_LIBRARIES
• setuid and/or setgid bits are set
• restricted by codes signed with entitlements
• restricted segment
https://theevilbit.github.io/posts/dyld_insert_libraries_dylib_injection_in_macos_osx_deep
_dive/