Ever wondered what those very first few syscalls where all about when you watched a program starting with strace? For me it was always some kind of static noise the loader generates, so was of no real interest. But then, one day, I looked a little closer and noticed a weird line testing for the existence of a file called /etc/ld.so.preload. I haven’t yet encountered a system that had such a file. The name was promising so I was curios what that file would be all about and started looking at the glibc sources searching for the corresponding code that does this test. Found it, like expected, in the loader code (elf/rtld.c). It is testing for the existence of that file and if it does it’ll load all shared objects listed in there just like setting the environment variable LD_PRELOAD would do. But wait! LD_PRELOAD was evil when combined with suid binaries so it will be ignored by the loader. That’s because otherwise you could abuse those binaries to raise your privileges by preloading some code that spawns a shell — e.g. by hooking __libc_start_main(). However, those restrictions do not apply for this file. The loader will bravely load the shared objects listed in /etc/ld.so.preload even for suid binaries. So if someone manages to create such a file he effectively owns the system. But since only root should be able to create files under /etc it should be safe for most systems. Anyway, good to know, by using this technique, you can hook your suid programs and for example get a root shell when needed by preloading a shared library that hooks setuid() with a wrapper that tests for a trigger (e.g. an environment variable) and execve()’s /bin/sh for you. Otherwise the wrapper just forwards the setuid() syscall. Now you just have to set your trigger, ping localhost and you’re root. 🙂 On the other hand you can do serious things with it like analysing or instrumenting suid binaries you have no source code of. It’s an elegant way to dig into the program without actually touching the binary.