Issue
The idea of LD_PRELOAD
is to load a shared library before the original shared library, for example I can compile mylib.so
to load it before libc.so
, so when process wants to use printf
it searches in the so
that loaded one by one and finds it in mylib.so
(because this so
was loaded first) instead of libc.so
, so it uses the printf
in mylib.so
instead of printf
in libc.so
.
I understand why this works on functions that are implemented in a so
like printf
in libc.so
.
But when I want to hook on write
function or another syscall
function, why does it work? The process does not search the function in the so
, it goes directly to the kernel.
Does
LD_PRELOAD
work on a binary that is compiled statically? Why? In this replay https://stackoverflow.com/a/13866611 mentioned thatLD PRELOAD
Doesn't work on statically binaryWhy does
LD_PRELOAD
work on a binary compiled dynamically to make hooks on syscalls?
The architecture is ARM.
Solution
The process does not search the function in the
so
, it goes directly to the kernel.
It actually does search the preloaded so
! The syscall functions you use (read()
, write()
, ...) are all libc wrappers around the real syscalls, even the generic syscall()
function. Here's the code for the write()
function for example. So when you reference those, both the linker at link time, and the dynamic loader at runtime, will see a reference to an external function symbol and will need to resolve it. The only way to go directly into kernel from your program is by manually issuing a syscall (see how below).
Does
LD_PRELOAD
work on a binary that is compiled statically? Why?
No, it doesn't. A static binary has no need to resolve any symbol dynamically, and therefore the dynamic loader is not invoked to resolve the usual library function symbols.
Why does
LD_PRELOAD
work on a binary compiled dynamically to make hooks on syscalls?
Because those are just normal library functions, nothing more, nothing less.
To directly issue a syscall without passing through the C library you can use inline assembly. Take a look at man 2 syscall
to see which registers and instructions to use. On ARM AArch64 for example you can invoke a syscall by loading the syscall number in the register x8
, parameters in x0
through x5
, and then executing the svc #0
instruction.
Answered By - Marco Bonelli Answer Checked By - Pedro (WPSolving Volunteer)