First let me clarify what LD_PRELOAD is. On UNIX, ld is the program which takes care of linking executables with
their needed shared libraries, or object files when building a single executable.
ld.so or ld-linux.so, located in /lib/, takes care of loading
dynamically linked executable into memory, it contains a special section which allows us to run it as an
executable. Some environment variables tell the linker where to look for the needed libs.
This LD_PRELOAD variable is used to specify the libs which will be loaded before the others in the default
paths.
Thus, some functions in some lib can be overridden using this variable.
I think things are quite clear about our opportunities here.
We can hook some functions quite easily this way, and thus hijack a program's execution flow.
Lets build a simple program protected by a password, I call it vuln.c.
Compile this with gcc vuln.c -o vuln -s
and run it, absolutely nothing surprising:
$./vuln
Password required: dsd
Access denied
The obvious target here is the strcmp function. So lets hook it. We want the strcmp() call to succeed
even with a wrong password. So here's the code for 'hook.c':
And that's all. This strcmp() version will always return 0, and thus, password testing using it with the
LD_PRELOAD trick will always fool the target program into thinking both the password and user input match.
Now we need to compile our library with: gcc hook.c -fPIC -shared -o hook.so
.
We indicate gcc to build a shared lib using the -shared flag, -fPIC is required when building a shared lib.
Basically, it tells gcc to use
Position Independant Code (PIC): use relative addresses instead of absolute.
Let's run our vulnerable program with our hook lib:
$export LD_PRELOAD="./hook.so"
$./vuln
Password required: rekt
Access granted
Note: this trick does not work on SUID binaries, unless your library is SUID as well.