Home

Awesome

injectso

This is the x86-64 and x86 rewrite of Shaun Clowes' i386/SPARC injectso which he presented at Blackhat Europe 2001.

Injectso is a hot patching tool which allows to hot-patch runtime processes by injecting a DSO into the running process. There is no need to restart that process.

Lots of changes happened since 2001 to the Linux runtime environment. The x86-64 architecture and ABI required some changes, not only substituting the ELF32 by ELF64 headers. Internal dl* functions check whether they are called from ld.so or glibc, e.g. we cant just point %rip to them. Luckily a do_dlopen() wrapper is located within glibc, otherwise we'd need to setup a fake stack-frame.

Injectso allows for injecting a DSO at runtime into a process, if apropriate permissions are given. Two test-DSOs are included, one which prints out a hello-message and one wich records key-strokes into a file. If injected into a root-process it starts a logging-thread:

(output-log from older injectso (2007) but the new one works the same)

lopht:~ # uname -a
Linux lopht 2.6.18.2-34-default #1 SMP Mon Nov 27 11:46:27 UTC 2006 x86_64 x86_64 x86_64 GNU/Linux
lopht:event # ps auxH|grep nscd
root      8824  0.0  0.0 120792   624 ?        Ssl  23:08   0:00 /usr/sbin/nscd
root      8824  0.0  0.0 120792   624 ?        Ssl  23:08   0:00 /usr/sbin/nscd
root      8824  0.0  0.0 120792   624 ?        Ssl  23:08   0:00 /usr/sbin/nscd
root      8824  0.0  0.0 120792   624 ?        Ssl  23:08   0:00 /usr/sbin/nscd
root      8824  0.0  0.0 120792   624 ?        Ssl  23:08   0:00 /usr/sbin/nscd
root      8824  0.0  0.0 120792   624 ?        Ssl  23:08   0:00 /usr/sbin/nscd
root      8824  0.0  0.0 120792   624 ?        Ssl  23:08   0:00 /usr/sbin/nscd
root      8833  0.0  0.0   5000   784 tty3     S+   23:08   0:00 grep nscd
lopht:event # ls -la /tmp/logz
ls: cannot access /tmp/logz: No such file or directory

Normal nscd, no logfiles. Injecting a DSO:

lopht:event # ./inject 8824 /tmp/d.so
do_dlopen:0x2b6843415a40 do_dlopen_offset:000f2a40 daemon's dl_open:0x2b911b7fda40 daemon's libc:0x2b911b70b000
a 7fff8fbf7590
lopht:event # cat /tmp/logz
<+c>at <Shift>7t<+m>p<Shift>7logz<Return>lopht:event #

DSO successfully injected. One thread more appears in the listing:

lopht:event # ps auxH|grep nscd
root      8824  0.0  0.0 137320   948 ?        Ssl  23:08   0:00 /usr/sbin/nscd
root      8824  0.0  0.0 137320   948 ?        Ssl  23:08   0:00 /usr/sbin/nscd
root      8824  0.0  0.0 137320   948 ?        Ssl  23:08   0:00 /usr/sbin/nscd
root      8824  0.0  0.0 137320   948 ?        Ssl  23:08   0:00 /usr/sbin/nscd
root      8824  0.0  0.0 137320   948 ?        Ssl  23:08   0:00 /usr/sbin/nscd
root      8824  0.0  0.0 137320   948 ?        Ssl  23:08   0:00 /usr/sbin/nscd
root      8824  0.0  0.0 137320   948 ?        Ssl  23:08   0:00 /usr/sbin/nscd
root      8824  0.0  0.0 137320   948 ?        Ssl  23:09   0:00 /usr/sbin/nscd
root      8840  0.0  0.0   5000   788 tty3     S+   23:09   0:00 grep nscd

If you want to check for evil injects, use /proc/PID/maps. Targets are nscd, sshd, apache etc. Only reasonable libraries should appear in the output; no d.so or /tmp paths etc.

lopht:~ # cat /proc/8824/maps
40000000-40001000 ---p 40000000 00:00 0
40001000-40201000 rw-p 40001000 00:00 0
40201000-40202000 ---p 40201000 00:00 0
40202000-40402000 rw-p 40202000 00:00 0
40402000-40403000 ---p 40402000 00:00 0
40403000-40603000 rw-p 40403000 00:00 0
40603000-40604000 ---p 40603000 00:00 0
40604000-40804000 rw-p 40604000 00:00 0
40804000-40805000 ---p 40804000 00:00 0
40805000-40a05000 rw-p 40805000 00:00 0
40a05000-40a06000 ---p 40a05000 00:00 0
40a06000-40c06000 rw-p 40a06000 00:00 0
40c06000-40c07000 ---p 40c06000 00:00 0
40c07000-41407000 rw-p 40c07000 00:00 0
2aaaaaad9000-2aaaaaae0000 r-xp 00000000 08:01 5837686                    /lib64/libnss_compat-2.5.so
2aaaaaae0000-2aaaaacdf000 ---p 00007000 08:01 5837686                    /lib64/libnss_compat-2.5.so
2aaaaacdf000-2aaaaace1000 rw-p 00006000 08:01 5837686                    /lib64/libnss_compat-2.5.so
2aaaaad0e000-2aaaaad18000 r-xp 00000000 08:01 5837694                    /lib64/libnss_nis-2.5.so
2aaaaad18000-2aaaaaf17000 ---p 0000a000 08:01 5837694                    /lib64/libnss_nis-2.5.so
2aaaaaf17000-2aaaaaf19000 rw-p 00009000 08:01 5837694                    /lib64/libnss_nis-2.5.so
2aaaaaf19000-2aaaaaf23000 r-xp 00000000 08:01 5837690                    /lib64/libnss_files-2.5.so
2aaaaaf23000-2aaaab122000 ---p 0000a000 08:01 5837690                    /lib64/libnss_files-2.5.so
2aaaab122000-2aaaab124000 rw-p 00009000 08:01 5837690                    /lib64/libnss_files-2.5.so
2aaaab124000-2aaaab127000 r-xp 00000000 07:00 418032                     /tmp/d.so
2aaaab127000-2aaaab326000 ---p 00003000 07:00 418032                     /tmp/d.so
2aaaab326000-2aaaab327000 r--p 00002000 07:00 418032                     /tmp/d.so
2aaaab327000-2aaaab329000 rw-p 00003000 07:00 418032                     /tmp/d.so
2b911aeb1000-2b911aecd000 r-xp 00000000 08:01 5837666                    /lib64/ld-2.5.so
2b911aecd000-2b911aece000 rw-p 2b911aecd000 00:00 0
2b911aefb000-2b911aefc000 rw-p 2b911aefb000 00:00 0
2b911b0cd000-2b911b0cf000 rw-p 0001c000 08:01 5837666                    /lib64/ld-2.5.so
2b911b0cf000-2b911b0d7000 r-xp 00000000 08:01 5837703                    /lib64/librt-2.5.so
2b911b0d7000-2b911b2d6000 ---p 00008000 08:01 5837703                    /lib64/librt-2.5.so
2b911b2d6000-2b911b2d8000 rw-p 00007000 08:01 5837703                    /lib64/librt-2.5.so
2b911b2d8000-2b911b2ee000 r-xp 00000000 08:01 5837699                    /lib64/libpthread-2.5.so
2b911b2ee000-2b911b4ed000 ---p 00016000 08:01 5837699                    /lib64/libpthread-2.5.so
2b911b4ed000-2b911b4ef000 rw-p 00015000 08:01 5837699                    /lib64/libpthread-2.5.so
2b911b4ef000-2b911b4f3000 rw-p 2b911b4ef000 00:00 0
2b911b4f3000-2b911b507000 r-xp 00000000 08:01 5837684                    /lib64/libnsl-2.5.so
2b911b507000-2b911b706000 ---p 00014000 08:01 5837684                    /lib64/libnsl-2.5.so
2b911b706000-2b911b708000 rw-p 00013000 08:01 5837684                    /lib64/libnsl-2.5.so
2b911b708000-2b911b70b000 rw-p 2b911b708000 00:00 0
2b911b70b000-2b911b844000 r-xp 00000000 08:01 5837673                    /lib64/libc-2.5.so
2b911b844000-2b911ba43000 ---p 00139000 08:01 5837673                    /lib64/libc-2.5.so
2b911ba43000-2b911ba46000 r--p 00138000 08:01 5837673                    /lib64/libc-2.5.so
2b911ba46000-2b911ba48000 rw-p 0013b000 08:01 5837673                    /lib64/libc-2.5.so
2b911ba48000-2b911ba4f000 rw-p 2b911ba48000 00:00 0
2b911ba4f000-2b911da4f000 rw-s 00000000 08:01 5937272                    /var/run/nscd/passwd
2b911da4f000-2b911fa4f000 rw-s 00000000 08:01 5937273                    /var/run/nscd/group
2b911fa4f000-2b9121a4f000 rw-s 00000000 08:01 5937393                    /var/run/nscd/dbkwnWNO (deleted)
555555554000-55555556c000 r-xp 00000000 08:01 6132031                    /usr/sbin/nscd
55555576c000-55555576e000 rw-p 00018000 08:01 6132031                    /usr/sbin/nscd
55555576e000-55555578f000 rw-p 55555576e000 00:00 0                      [heap]
7fff8fbe4000-7fff8fbf9000 rw-p 7fff8fbe4000 00:00 0                      [stack]
ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0                  [vdso]

Hardening discussion

Some hardening mechanisms block injecting of DSO's into confined processes; out of the box.

Some systems have for example targeted SELinux configs enabled. However this does not help against local attackers injecting DSO's into sshd process space for example. Bypassing sshd target policy is as easy as copying the DSO to /lib64 to have it unconfined_u:object_r:lib_t label thus allowing the process to load it into memory. Since you'd need root anyway to ptrace sshd, this is no barrier. And there are places which is sshd allowed to write to, /var/log for example. So at the end you won nothing with the policy. If someone gained root, he won. You'd need full blown strict policy or RBAC system to forbid that. On the other hand, targeted policy already prevented me writing some local root exploit using sshd as exploitation vector, so its not so useless you may think. injectso may be used to test policy configs by injecting DSO's to create/read/etc. files on behalf of confined processes.

Since version 0.5 injectso supports three different ways to find out the address of the targets dlopen address. Since then it also works on debian based systems which make /proc/pid/maps unavailable by default.

As of version 0.52 injectso also supprts ARM and Android. Thanks to Luis Miras who sent me a patch for the ARM architecture. For Android, the -P switch requires the full pathname since bionic's realpath() is fscked.