Skip to content

Commit

Permalink
ld-linux hooker
Browse files Browse the repository at this point in the history
  • Loading branch information
sduverger committed Oct 28, 2011
0 parents commit 9accf90
Show file tree
Hide file tree
Showing 6 changed files with 580 additions and 0 deletions.
13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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
9 changes: 9 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -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
[...]
111 changes: 111 additions & 0 deletions hooked.s
Original file line number Diff line number Diff line change
@@ -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
58 changes: 58 additions & 0 deletions interpatch.c
Original file line number Diff line number Diff line change
@@ -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;
}
Loading

0 comments on commit 9accf90

Please sign in to comment.