libfaketime can be used for nefarious things such as using software past its trial stage (same with using serials attached to MAC addresses + mac spoofing) or returning future TOTP data. Its generally useful for QA as well. It could've been used by Apple to avoid the reset bug in iOS 11.1.2
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.
> fakechroot is used when you build your own *.deb file.
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. :-(
tsocks [1] is also interesting. It lets you run a program forwarding all its network data through a SOCKS proxy. It's very useful if you want to VPN a single application over a SSH connection.
I actually had to use this trick several months ago in order to install Nessus on my Debian box. The installer was written in C and it called uname() to check if I was running a "supported kernel version" despite not actuality installing any kernel module to the system. It simply refused to install until my fake uname() returned the 3.10.x series kernel in the utsname structure...
I used the same trick to modify how X11 server sends keyboard messages. There's a boolean flag that denotes whether or not a key event is "real" or generated artificially.
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.
I did exactly the same thing in the early 2000s to get an ancient Java application working under Linux 2.4 -- it was calling some syscall via libc and getting a slightly different result than it had under Linux 2.2, and dying for no useful reason. I'm pretty sure that LD_PRELOAD hack ran in prod for years :-) Very handy trick.
It sounds like this wasn't the case in this instance, but applications could depend on kernel features without loading any kernel modules. The fact that they required 3.10 is interesting because my first example would be user namespaces, which were completed around that point (I think they were mostly done by 3.8, but IIRC there were some significant features that weren't complete until 3.9-3.10).
The problem for me is that my kernel appeared to be too "new" for Nessus since they set minimum and maximum version ranges. Oddly enough it never impacted function AFAIK.
Full sandboxing is not possible with LD_PRELOAD, because the application can still issue raw system calls (syscalls) by using the 'int 0x80' instruction, skipping any library call.
How exactly does one use seccomp to alter/intercept syscalls instead of simply blocking or allowing them? I can't find anything which uses it like that with a search.
GP is misinformed. seccomp is an optimization to ptrace-based syscall interception, when you're only interested in intercepting a subset of a process's syscalls. Instead of getting an event and processing every single syscall a process makes, you can register a seccomp filter that fires a ptrace event in only specific cases (which can be super coarse like "the syscall number is open", or more fine grained like "the syscall number is open and the file is being opened with O_WRONLY or O_RDWR"). Without something like this, ptrace based interception would be almost unusably slow for many cases.
If you also intercept the exec* family calls, you can forbid the user from running any but the trusted executables (so that will exclude e.g. anything written in Python etc).
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.
As C language teacher assistants in Uni, we used LD_PRELOAD during project defences to replace the lib standard malloc by one of our own in order to be sure that students allocated & freed memory correclty. Never saw so much Segmentation faults in such a short time window.
If you can afford rebuilding from source, using AddressSanitizer (perhaps also UndefinedBehaviorSanitizer) should be better at uncovering memory safety bugs than any LD_PRELOAD trick.
We used (and actually still use) this to override hostname lookup in an automated test scenario, where we want to run multiple test suites of the same software (consisting of several processes which all communicate with each other via networking) on the same build server in parallel. We ended up just configuring everything to bind/connect to "localhost", so it runs fine on developer machines, but when executed on the build server - which is a lot more beefier than a dev laptop - the exact same configuration can be run 20 times, executing different test suites in parallel. The trick is that there's one independent loopback network interface for each run on that server, and by overriding the hostname lookup of the software via a small library provided in LD_PRELOAD, we replace the default lookup to 127.0.0.1 with these other loopback devices' IPs.
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.
Not if there isn't an interface. If I create one, sure, but then I would have to do that on all dev computers as well and I'd have to forward the address somehow into all server and client configs and/or command-lines of tools started as part of the build process.
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).
If I'm not mistaken putting DLLs in the same directory as the executable lets you do the same on Windows. Mods and cracks for videogames usually plant a fake DirectX dll in the game folder.
Absolutely correct. Although this was intentional behaviour, it was given a security advisory[1]. In practice it allowed all sorts of exploits, including dumping packed executables for cracking, as you say.
Yeah, but UNIX developers love namespace conflicts and hardcoded paths, so something as simple as "look for libs in the directory your binary is in" either never occurred to them or was rejected under various arbitrary concerns.
Huh? It has not been rejected -- it is up to compiler/linker what to put in RPATH, and you can totally set RPATH to $ORIGIN. There is a nice tool, chrpath, to do so. For example, java sets it to:
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 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.
In order to exploit this you need to be able to write to the directory where the binary is.
"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.
This fun local hack is related to binary planting vulnerabilities, where a dynamic resource can be planted on-disk prior to program execution for later loading due to being in the load path.
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.
I don't see what the big deal is. That behavior allowed a ton of flexibility at the cost of DLL planting problems iff someone can already drop arbitrary files in the application's directory.
> It has been a while since I've used Sandboxie, but it seems like this is a behavioral oversight on it's part.
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.
The link you gave gives a single line description of the issue. It isn't very helpful in understanding what conditions were required to exploit. Is this a Sandboxie installer issue or all installers?
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 link you gave gives a single line description of the issue. It isn't very helpful in understanding what conditions were required to exploit. Is this a Sandboxie installer issue or all installers?
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.
None of that has anything to do with the discussion about binary planting, one variant of which is dll planting due to the cwd directory being used as a path component in microsoft windows versions.
GDAL has a vsipreload.so which you can preload to replace all the libc file handling functions with ones that understand special filesystem paths, like /vsizip/path/to/zipfile.zip/myfile.csv
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.
Is this possible when trying to intercept and/or otherwise mess with system calls or stdlib function calls in a language that statically links all/most of its libraries? Are Go binaries affected? Statically-linked Rust binaries? If not, this is (depending on how you look at it) either a security point in favor of those languages or a hindrance to patching/debuggability.
Colleagues of mine use LD_PRELOAD for roll-you-own profiling. They supply their own `malloc`, for example, that does the same as regular-`malloc` but also writes to a log file that can be analysed later.
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`.
This may be a good time to ask since I've been recommended to use LD_PRELOAD but it's always caused issues.
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.
I experienced something similar in my data-driven permission restriction DSO. Turns out I was calling my initialization function multiple times because the system calls I overrode were called before my attribute((constructor)) function.
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.
Why is the bootstrap.so being unloaded? It should be loaded into the process pretty permanently. If you have something calling dlopen/dlclose on it, maybe give it an extra dlopen.
That's the issue, it shouldn't be unloaded. Yet when bootstrap.so calls dlopen(other.so); bootstrap.so gets unloaded and reloaded. I'll try adding a dlopen(bootstap.so) in the callback to increase the refcount though.
Another approach is using LD_PRELOAD with Frida to be able to write the instrumentation logic in JavaScript:
https://www.frida.re/docs/gadget/
This also supports monitoring the .js file for changes and reloading the instrumentation logic live, which is great for game tweaks. Just save the file and instantly see the results.
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.
I've used LD_PRELOAD to thunk calls to glXSwapBuffers, adding a call to glFinish right afterwards. This keeps the OpenGL driver from getting too far ahead in rendering, since both the buffer swap and command queue are asynchronous, and reduces input lag somewhat.
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.
Is there a similar Java centric type override? Would it be as simple as dropping a jar in the right location or is there an environment variable that can be over written? Also it would be neat to know the java code to chain the "open" system call like he did.
Probably not with an environment variable, but you can always replace the java executable with another executable that adds an option like -Xbootclasspath.
You can write a Java agent to overwrite the classfiles as they're loaded.
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.
This is both an argument in favour of static linking, and an argument against static linking.
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.
I've used both LD_PRELOAD and Detours and I like LD_PRELOAD so much better. LD_PRELOAD just needs single standard shared library and one environment variable. With Detours you have to: inject code into executable, stop threads, worry about races, protecting/unprotecting memory. The way it's implemented also feels like a big hack. The hooks are injected into first few instructions of hooked methods. Some system functions even deliberately leave blank space there. I'm yet to encounter a use case where all this complexity is useful.
>The ELF dynamic linking mechanism is designed to emulate static linking. That's like designing cars to neigh and occasionally kick people to death with robot legs that exist only for this purpose.
https://github.com/stewartsmith/libeatmydata
https://github.com/wolfcw/libfaketime
https://cwrap.org/
https://github.com/dex4er/fakechroot
https://blitiri.com.ar/p/libfiu/
https://github.com/paultag/tmperamental