Tool for injecting a shared object into a Linux process, shared library substitution, and runtime plt function hook
-
the original idea is inspired by linux-inject, but more than injection. Except for shared library runtime injection, plt-hook also support runtime plt function hook and shared library substitution.
-
Performs injection using
ptrace()
rather thanLD_PRELOAD
, since the target process is already running at the time of injection -
Supports x86_64
-
Does not require the target process to have been built with
-ldl
flag, because it loads the shared object using__libc_dlopen_mode()
from libc rather thandlopen()
from libdl
-
On many Linux distributions, the kernel is configured by default to prevent any process from calling
ptrace()
on another process that it did not create (e.g. viafork()
). -
This is a security feature meant to prevent exactly the kind of mischief that this tool causes.
-
You can temporarily disable it until the next reboot using the following command:
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
-
Simply running
make
should automatically select and build for the correct architecture, but if this fails (or you would like to select the target manually), run one of the following make commands:-
x86_64:
make x86_64
-
./inject [-n process-name] [-p pid] [original-library] [library-to-inject]
-
Creates the necessary links and cache to libsample.so
$ mkdir /usr/lib64/plt-hook $ cp libsample.so /usr/lib64/plt-hook/ $ touch /etc/ld.so.conf.d/test.conf /usr/lib64/plt-hook $ ldconfig -v | grep sample libsample.so -> libsample.so
-
In one terminal, start up the sample target app, which simply outputs:
./sample-target call the addition: 7 main thread: result = 7 call the addition: 7 child thread: result = 7 call the addition: 7 main thread: result = 7 call the addition: 7 child thread: result = 7 call the addition: 7 main thread: result = 7
-
Creates the necessary links and cache to libsampleupdate.so
$ cp libsampleupdate.so /usr/lib64/plt-hook/ $ ldconfig -v | grep sample libsample.so -> libsample.so libsampleupdate.so -> libsampleupdate.so
-
In another terminal, inject sample-library.so into the target app:
./inject -n sample-target libsample.so /usr/lib64/plt-hook/libsampleupdate.so
-
The output should look something like this:
-
On second terminal:
$ ./inject -n sample-target libsample.so libsampleupdate.so targeting process "sample-target" with pid 3267 symbol need to be replaced: libsample process 3267 has 2 tasks attached to all threads. "libsampleupdate.so" successfully injected libsample is substituted detached from all threads. $
-
On first terminal, it start printing out the changed function result.
... child thread: result = 7 call the addition: 7 main thread: result = 7 call the addition: 7 main thread: result = 7 call the multiplication: 8 child thread: result = 8 call the multiplication: 8 main thread: result = 8 call the multiplication: 8 main thread: result = 8 ...
-
If the injection fails, make sure your machine is configured to allow processes to
ptrace()
other processes that they did not create. See the "Caveat aboutptrace()
" section above. -
Please check 'ldconfig -v' result, your target process should be able to recognize the to-be-injected library path you specified.
-
You can verify that the injection was successful by checking
/proc/[pid]/maps
:$ cat /proc/$(pgrep sample-target)/maps [...] 7f2c95901000-7f2c95902000 r-xp 00000000 08:12 47196963 /data/home/zhuozh/plt-hook/libsampleupdate.so 7f2c95902000-7f2c95b01000 ---p 00001000 08:12 47196963 /data/home/zhuozh/plt-hook/libsampleupdate.so 7f2c95b01000-7f2c95b02000 r--p 00000000 08:12 47196963 /data/home/zhuozh/plt-hook/libsampleupdate.so 7f2c95b02000-7f2c95b03000 rw-p 00001000 08:12 47196963 /data/home/zhuozh/plt-hook/libsampleupdate.so [...]
-
You can also attach
gdb
to the target app and runinfo sharedlibrary
to see what shared libraries the process currently has loaded:$ gdb -p $(pgrep sample-target) [...] (gdb) info sharedlibrary From To Syms Read Shared Object Library 0x00007fed695ba5e0 0x00007fed695ba708 Yes ./libsample.so 0x00007fed693a38a0 0x00007fed693ae784 Yes /lib64/libpthread.so.0 0x00007fed68ffc3b0 0x00007fed6914111f Yes /lib64/libc.so.6 0x00007fed697bcaf0 0x00007fed697d6520 Yes /lib64/ld-linux-x86-64.so.2 0x00007fed685da5e0 0x00007fed685da704 Yes /data/home/zhuozh/plt-hook/libsampleupdate.so (gdb)
-
You can also restore the original library, in case you regret the substitution.
$ ./inject -n sample-target libsampleupdate.so /usr/lib64/plt-hook/libsample.so
-
On first terminal:
... main thread: result = 8 call the multiplication: 8 child thread: result = 8 call the multiplication: 8 main thread: result = 8 call the multiplication: 8 main thread: result = 8 call the addition: 7 child thread: result = 7 call the addition: 7 main thread: result = 7 call the addition: 7 main thread: result = 7
-
-
Unload original library will cause ld.so crash, just leave original library in the memory as a workaround.
-
Support only X86_64 version
-
Support more distros
-
Only tested on Centos 7.2
-
Possibly support more architectures?