Using LD_PRELOAD to cheat, inject features and investigate programs (2013)
rafalcieslak.wordpress.com
rafalcieslak.wordpress.com
fakechroot is used when you build your own *.deb file.
libeatmydata can be used in environments where you'd destroy the data afterwards anyway, or where you don't need logging or keep state after a reboot. You can also mount a bunch of filesystems such as /tmp and /var/log as tmpfs though.
That's "fakeroot", a different program, which is used for simulating superuser privileges.
I was going to mention fakeroot, too, but it doesn't seem have a useful homepage. https://fakeroot.alioth.debian.org/ looks very much uninviting.
fakeroot was written for Debian, and it's still developed by Debian developers, although there's nothing Debian-specific about it. Debian has giving back to the free software community in their Social Contract¹, but in practice there's no culture of making Debian software easily accessible to outsiders. :-(
Also uses LD_PRELOAD.
https://github.com/DavidBuchanan314/TARDIS
It isn't intended for any kind of serious usage, I mainly just wanted to understand ptrace and LD_PRELOAD.
For some !@$!@'d up reason, 99% of apps actually discard all synthetic keyboard events. So doing something as innocent as mapping joystick to keyboard commands fails. It also took HOURS to find out why my keyboard generating test code wouldn't work until I piped it to an Ubuntu postit note program and hazzah... it worked with no code changes. Every other app was just blocking the events.
Edit - Here's some details about Chromium's dependency on these features: https://chromium.googlesource.com/chromium/src/+/lkcr/docs/l...
It does get tricky since you are depending on glibc internals to find out what symbols to override. IIRC some of the exec* functions called each other internally without going through the symbol table, so you cannot override just execve which corresponds to the system call, as execvp will not call the execve function.
Then there's a whole ton of new secure Linux system calls that instead of a full path name take a directory file descriptor + name in that directory. E.g. execveat, openat etc.
So I wouldn't recommend it in a fully hostile (secure) environment.
You could of course achieve the same thing (and even more, like filesystem isolation) in a way more elegant and better-understandable way via Docker containers, but we started doing this in 2011 - there was no Docker back then, so we built our own ultra-low-overhead network virtualization. It'll probably be replaced by Docker someday, but for the moment it's still being used as it "just works" and requires practically no maintenance after being set up once.
Just overriding "localhost" spares me from both (the address to resolve is provided as an env variable, just like LD_PRELOAD itself - and env variables are inherited by child processes, which is great in my scenario).
Only advantage I can see is if localhost is hardcoded everywhere.
[1]: https://docs.microsoft.com/en-us/security-updates/SecurityAd...
"Security" is trotted out as an arbitrary concern quite often because a lot of security people don't have any concept of risk analysis or cost/benefit. If it was up to them no one would ever do anything because that way they can't make a mistake.
gcc -Wl,-rpath,'$ORIGIN/../lib'
See http://man7.org/linux/man-pages/man8/ld.so.8.html /usr/bin/java: RPATH=$ORIGIN/../lib/amd64/jli:$ORIGIN/../lib/amd64
I believe the reason it does not happen by default is that binaries go to /usr/bin, and no .so files should appear there. Also it breaks when hardlinks are involved.I other words, nobody uses it. So many conflicts could be easily solved if applications dropped this retarded insistence on spreading files over the hierarchy by type, but they just keep doing it because they mistake tradition for wisdom.
Binary planting, incidentally, was one of those persistent bugs in all Windows versions, since the local directory in Windows generally is in the beginning of the path. That variant is called DLL planting or a DLL loading vulnerability.
That single design decision to execute from the local folder has caused untold havoc, including half a dozen APIs for how to handle DLL loading.
your email program downloads files
you go to a network share and click
java loads the configuration from the current directory
or, or, or
You're absolutely right :(
Let's say that a Windows user wants to use sandboxie to isolate web components when browsing, until Aug of this year.
You're Pwned: https://nvd.nist.gov/vuln/detail/CVE-2017-12480
What do you mean by a behavioral oversight?
The installer loaded a non-existent dll from the temp folder. Any DLL of the same name would get executed upon installation of Sandboxie. That's why DLL hijacking is an issue.
If the latter, yeah that's a problem, but there are a lot of ways to fix it that don't involve crippling the flexibility.
Edit: ok, read the medium link at the bottom. This is an issue with Sandboxie's installer behavior, for which I think it is unfair to blame the way Windows searches for and loads DLLs.
The single line description is literally an answer to both of those questions, "Sandboxie installer 5071703 has a DLL Hijacking or Unsafe DLL Loading Vulnerability via a Trojan horse dwmapi.dll or profapi.dll file in an AppData\Local\Temp directory."
> Edit: ok, read the medium link at the bottom. This is an issue with Sandboxie's installer behavior, for which I think it is unfair to blame the way Windows searches for and loads DLLs.
The vulnerability is literally caused by the dll load path containing the cwd. That is the subject of this entire thread.
But hey, fuck it, let's throw the baby out with the bathwater and have namespace conflicts because now all DLLs must be in system32 or some bullshit.
For that matter, let's just not use computers at all! That's where vulnerabilities come from after all.
This should be fixed all at once, by stopping treating empty string as cwd. People who actually need to have cwd in *PATH can add it explicitly.
We used it for years to do remote inspection of zip files without downloading the whole thing. Now there's a proper API for virtual filesystems in GDAL and we don't have to preload any more.
There are other interception techniques that work against any binaries, even fully static ones:
I've used it in the past to get an overview of what gets passed to SSL_write, SSL_read: https://github.com/sebcat/openssl-hook
It also uses `LD_PRELOAD` to overwrite a function in gcov and hash a filename to prevent exceeding a limit. Even more interesting, it comes with a stand-alone binary. The shared library is copied into the binary and when the binary runs, it extracts the shared library and runs the real gcov and injects the shared library using `LD_PRELOAD`.
I had fun :)
Imagine this, a 'Bootstrap.so' is injected into a process via LD_PRELOAD. This bootstrapper places a jump on the programs entrypoint that jumps to a bootstrap::callback function. This function wants to load other shared libraries though. So when it starts loading another library the bootstrapper gets unloaded and reloaded, which ofcourse breaks execution.
Would anyone know how to properly deal with this?
I'd recommend running your program under gdb with a breakpoint in your function and checking out what the stack is like. Maybe your function is getting called from an unexpected place.
In my case I was overriding fopen64 but glibc wanted to open some NSS related files before my init function was called.
A project that injects via LD_PRELOAD into a game called Neverwinter Nights (now Enhanced Edition). It lets content authors/admins add things like database support, more scripting languages, extensive ruleset changes, and whatever else you want to the game.
https://gist.github.com/przemoc/571086
Don't know if it still builds and works flawlessly.
For some reason my card/driver combo creates a huge output lag when it can't keep up with with framerate cap. I'd like to try if something like this would help with it.
On topic of things that use LD_PRELOAD, there's this fps capper (not my work): https://github.com/torkel104/libstrangle
At startup, you can use the `-javaagent:<path/to/jar>` option, and you can also bind an agent to other JVMs, programmatically, at runtime with a bit of hackery.
Rust and go programmers will claim this is an attack they are not vulnerable to it, and other people will say this is an useful feature and static linking prevents its use.
Used it while working on Azure Security Forensics team, however sometimes we also used EasyHook for C#
That comment wins thread.