Permalink
Browse files

ld-linux hooker

  • Loading branch information...
0 parents commit 9accf90a6340ee516126e93ff2492e4c7a32b1d1 @sduverger committed with Oct 28, 2011
Showing with 580 additions and 0 deletions.
  1. +13 −0 Makefile
  2. +9 −0 README
  3. +111 −0 hooked.s
  4. +58 −0 interpatch.c
  5. +363 −0 ld-shatner.c
  6. +26 −0 obj.c
@@ -0,0 +1,13 @@
+all: ld-shatner interpatch
+
+obj.elf: obj.c
+ gcc -fpie -c obj.c -o obj.o
+ ld -pie obj.o -o $@ -e func
+
+ld-shatner: hooked.s ld-shatner.c obj.elf
+ gcc hooked.s ld-shatner.c -o $@
+
+interpatch: interpatch.o
+
+clean:
+ rm -f ld-shatner interpatch ld-hook.so obj.elf *.o
@@ -0,0 +1,9 @@
+$ make clean all
+$ cp /lib/ld-linux.so.2 .
+$ cp /bin/ls .
+$ ./ld-shatner ld-linux.so.2 obj.elf
+$ sudo cp ld-hook.so /lib/
+$ ./interpatch ls
+$ ./ls
+ld-hook <---------------------- output of obj.elf
+[...]
@@ -0,0 +1,111 @@
+.text
+.globl shatner, payload
+.type shatner,"function"
+.type payload,"function"
+
+shatner:
+ jmp 1f
+__old_ld:
+ .long 0 /* ld original entry point (from 0) */
+__old_user:
+ .long 0 /* location to store original user entry point (from 0) */
+__inject_entry: /* entry point of injected code (from 0) */
+ .long 0
+1:
+ pushl $0
+ push %eax
+ lea 8(%esp), %eax
+ push %edx
+ push %ecx
+ call __get_pc
+__get_pc:
+ pop %edx
+ mov %edx, %ecx
+ add $(payload_caller - __get_pc), %edx
+ sub $(__get_pc - __old_user), %ecx
+ push %ebx
+ push %edi
+ xor %edi, %edi
+fix_auxv: /* walk stack to find 2 NULL words (one ending argv, one ending envp) */
+ mov (%eax), %ebx
+ test %ebx, %ebx
+ jnz next_word
+ inc %edi
+ cmp $2, %edi
+ je auxv_found
+next_word:
+ add $4, %eax
+ jmp fix_auxv
+
+auxv_found: /* found second NULL word, start lokking for AUX_TYPE==ENTRY (9) */
+ add $4, %eax
+next_tag:
+ cmp $9, (%eax)
+ je auxv_entry_tag_found
+ add $8, %eax
+ jmp next_tag
+
+auxv_entry_tag_found:
+ add $4, %eax
+ mov (%eax), %edi
+ mov (%ecx), %ecx
+ push %esi
+ call __get_pc2
+__get_pc2:
+ pop %esi
+ sub $((__get_pc2 - shatner)+52), %esi /* base address of ld in memory */
+ add %esi, %ecx
+ mov %edi, (%ecx) /* save user entry */
+ mov %edx, (%eax) /* install new one */
+
+resume_ld:
+ sub $(payload_caller - __old_ld), %edx
+ mov (%edx), %edx
+ add %esi, %edx /* base + ld original entry */
+ pop %esi
+ pop %edi
+ pop %ebx
+ pop %ecx
+ mov %edx, 8(%esp)
+ pop %edx
+ pop %eax
+ ret
+
+payload_caller:
+ call real_payload_caller
+ push $0
+ push %eax
+ call __get_pc3
+__get_pc3:
+ pop %eax
+ push %edx
+ mov %eax, %edx
+ sub $((__get_pc3 - shatner)+52), %eax /* base address of ld in memory */
+ sub $(__get_pc3 - __old_user), %edx /* user offset */
+ mov (%edx), %edx
+ add %eax, %edx
+ mov (%edx), %eax /* original user entry */
+ movl $0, (%edx) /* clear place */
+ mov %eax, 8(%esp)
+ pop %edx
+ pop %eax
+ ret
+real_payload_caller:
+ push %eax
+ call __get_pc4
+__get_pc4:
+ pop %eax
+ push %edx
+ mov %eax, %edx
+ add $(payload - __get_pc4), %eax
+ sub $(__get_pc4 - __inject_entry), %edx /* injected entry offset */
+ mov (%edx), %edx
+ add %edx, %eax
+ call *%eax
+ pop %edx
+ pop %eax
+ ret
+
+ .align 4
+payload:
+ nop
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <elf.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <fcntl.h>
+
+#define LDNAME "/lib/ld-hook.so"
+
+int main(int argc, char **argv)
+{
+ Elf32_Ehdr *e_hdr;
+ Elf32_Phdr *p_hdr;
+ int fd, i;
+ off_t fd_sz;
+ uint32_t len, old;
+
+ if (argc != 2)
+ {
+ printf("usage: %s <elf>\n", argv[0]);
+ return -1;
+ }
+
+ if ((fd = open(argv[1], O_RDWR)) == -1)
+ {
+ printf("can't open file %s\n", argv[1]);
+ return -1;
+ }
+
+ fd_sz = lseek(fd, 0, SEEK_END);
+ lseek(fd, 0, SEEK_SET);
+ e_hdr = (Elf32_Ehdr*)mmap(NULL, fd_sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ p_hdr = (Elf32_Phdr*)((uint32_t)e_hdr + e_hdr->e_phoff);
+
+ len = strlen(LDNAME)+1;
+
+ for (i=0 ; i<e_hdr->e_phnum ; i++, p_hdr++)
+ if (p_hdr->p_type == PT_INTERP)
+ {
+ if (p_hdr->p_filesz < len)
+ {
+ printf("not enough space to fix interp name (%d)\n", p_hdr->p_filesz);
+ return -1;
+ }
+
+ old = p_hdr->p_filesz;
+ p_hdr->p_filesz = p_hdr->p_memsz = len;
+ memcpy((void*)((uint32_t)e_hdr+p_hdr->p_offset), LDNAME, len-1);
+ memset((void*)((uint32_t)e_hdr+p_hdr->p_offset+len-1), 0, old-len);
+
+ /* XXX: should also fix section header ... */
+ }
+
+ munmap((void*)e_hdr, fd_sz);
+ close(fd);
+ return 0;
+}
Oops, something went wrong.

0 comments on commit 9accf90

Please sign in to comment.