Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does LD_PRELOAD work with syscalls? ​

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.

  1. Does LD_PRELOAD work on a binary that is compiled statically? Why? In this replay https://stackoverflow.com/a/13866611 mentioned that LD PRELOAD Doesn't work on statically binary

  2. Why does LD_PRELOAD work on a binary compiled dynamically to make hooks on syscalls?

The architecture is ARM.

like image 538
yfr24493AzzrggAcom Avatar asked Mar 02 '23 18:03

yfr24493AzzrggAcom


1 Answers

The process does not search the function in the so, it goes directly to the kernel.

Wrong, 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. 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 libc functions, nothing more, nothing less.


The only way of manually calling a syscall without passing through the C library (and therefore without doing symbol resolution) other than compiling statically is to use inline assembly. You can 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.

like image 163
Marco Bonelli Avatar answered Mar 05 '23 15:03

Marco Bonelli