News for hackers. Stuff that matters.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by kevingadd on Wednesday September 13, 2023 @01:40AM (#37492625)
it's a little more general, I think, since one common use case for it is to use it on your own process in order to intercept calls to stdlib/OS code from libraries you don't control.

For example, in the bad old days I used detours to virtualize the windows registry so that I could do "fake installs" of COM components inside of a VB6 app, allowing it to run without an install and without administrator permissions. This worked by detouring all the Win32 registry APIs, which was sufficient to intercept registry accesses performed by the COM infrastructure.

Re:Any sufficiently advanced uninstaller is indistinguishabl... by cornel_io on Wednesday September 13, 2023 @02:25AM (#37492900)
For those of us who don't Windows, can you explain what a detour is?
Re:Any sufficiently advanced uninstaller is indistinguishabl... by coldtea on Wednesday September 13, 2023 @02:49AM (#37493067)
Detours is a library for instrumenting arbitrary Win32 functions Windows-compatible processors. Detours intercepts Win32 functions by re-writing the in-memory code for target functions. The Detours package also contains utilities to attach arbitrary DLLs and data segments (called payloads) to any Win32 binary.

Detours preserves the un-instrumented target function (callable through a trampoline) as a subroutine for use by the instrumentation. Our trampoline design enables a large class of innovative extensions to existing binary software.

https://www.microsoft.com/en-us/research/project/detours/

Re:Any sufficiently advanced uninstaller is indistinguishabl... by IshKebab on Wednesday September 13, 2023 @04:16AM (#37493705)
Interesting. Has anyone done the same thing on Linux?
Re:Any sufficiently advanced uninstaller is indistinguishabl... by alaxapta7 on Wednesday September 13, 2023 @04:54AM (#37494050)
I use and recommend subhook[0].

[0] https://github.com/Zeex/subhook

Re:Any sufficiently advanced uninstaller is indistinguishabl... by jaclaz on Wednesday September 13, 2023 @04:43AM (#37493946)
Re:Any sufficiently advanced uninstaller is indistinguishabl... by stevemk14ebr on Friday September 15, 2023 @02:36AM (#37519302)
And my more sophisticated library, https://github.com/stevemk14ebr/PolyHook_2_0
Re:Any sufficiently advanced uninstaller is indistinguishabl... by jborean93 on Wednesday September 13, 2023 @02:51AM (#37493084)
You essentially replace a function with your own. The project is at https://github.com/microsoft/Detours.

I’ve created a PowerShell module that wraps this library to make it easier to hook functions on the fly for testing https://github.com/jborean93/PSDetour. For example I used it to capture TLS session data for decryption https://gist.github.com/jborean93/6c1f1b3130f2675f1618da5663... as well as create an strace like functionality for various Win32 APIs (still expanding as I find more use cases) https://github.com/jborean93/PSDetour-Hooks

Re:Any sufficiently advanced uninstaller is indistinguishabl... by grepfru_it on Wednesday September 13, 2023 @03:42AM (#37493449)
> as well as create an strace like functionality for various Win32 APIs

Yes please. Thank you for this

Re:Any sufficiently advanced uninstaller is indistinguishabl... by wahern on Wednesday September 13, 2023 @07:07PM (#37502852)
> it's a little more general, I think, since one common use case for it is to use it on your own process in order to intercept calls to stdlib/OS code from libraries you don't control.

This capability is intrinsic to how ELF linking works. The main application or even any library can interpose a libc function just by defining and exporting a function with the same name, and that definition will be preferentially linked in both the main application and all subsequently loaded dynamic libraries and modules. Your definition can then use dlsym(RTLD_NEXT, "foo") to obtain a function pointer to the next definition, which would normally be libc itself but may be from another library. A running application could actually have several implementations of a function, all proxying calls onward until the terminal (usually libc) implementation.

Basically, the way ELF linking works by default is that the first definition loaded is the preferred global symbol used to satisfy any symbol dependency with that name. It follows that there's normally a singular global symbol table. Though there are features and extensions that can be explicitly used to get different behaviors.

There's nothing magical about LD_PRELOAD within the context of ELF linking. LD_PRELOAD support in the linker (which is the first bit of code the kernel loads on exec(2)) is very simple; all the linker does is load the specified libraries first, even before the main application, so symbols exported therein become the initial and therefore default definition for satisfying subsequent symbol dependencies, including in the main application binary, and even if the main application binary also defines and exports those symbols.

All of this is basically the exact opposite behavior of how PE linking works on Windows, for better and worse--depending on your disposition and problems at hand.

Also note that all of this is different than so-called "weak" symbols, which is a mechanism for achieving one of the same behaviors--overriding another definition--when statically linking. Otherwise, when statically linking, multiple definitions are either an error or it's difficult (i.e. confusing, especially in complex builds) to control when and where one definition is chosen over another.

[1] Though main application symbols aren't usually exported by default, so you need to explicitly mark a definition for export or build the entire main binary with a compiler flag like `-rdynamic`, which is the main binary analog to the `-shared` flag used for building shared libraries. The Python and Perl interpreters, for example, are built with -rdynamic as the interpreter binary itself exports all the implementation symbols required by binary modules, rather than defining them in a separate shared library