diff -r 26423726a075 -r 083a0b9b734c src/arch-i386/Makefile --- a/src/arch-i386/Makefile Wed Jun 24 16:23:46 2009 +0200 +++ b/src/arch-i386/Makefile Sat Jul 25 20:01:35 2009 +0200 @@ -1,6 +1,6 @@ COMMON_OBJS = -R_CHUNK_OBJS = cp_r_regs.o cp_r_tls.o cp_r_i387.o start.o plt-resolve.o -W_CHUNK_OBJS = cp_w_regs.o cp_w_tls.o cp_w_i387.o +R_CHUNK_OBJS = cp_r_regs.o cp_r_tls.o cp_r_i387.o start.o plt-resolve.o getpid_hack_r.o +W_CHUNK_OBJS = cp_w_regs.o cp_w_tls.o cp_w_i387.o getpid_hack_w.o KERN=$(shell uname -r) diff -r 26423726a075 -r 083a0b9b734c src/arch-i386/cp_r_regs.c --- a/src/arch-i386/cp_r_regs.c Wed Jun 24 16:23:46 2009 +0200 +++ b/src/arch-i386/cp_r_regs.c Sat Jul 25 20:01:35 2009 +0200 @@ -12,6 +12,11 @@ extern int need_gtk; #endif +static struct user user; + +struct user_regs_struct* regs(void) { + return &user.regs; +} static void load_chunk_regs(struct user *user, int stopped) { @@ -94,6 +99,8 @@ *(unsigned long*)(cp) = r->eip; cp+= 4; asm("mov %%cs,%w0": "=q"(r->xcs)); /* ensure we use the right CS for the current kernel */ *(unsigned short*)(cp) = r->xcs; cp+= 2; /* jmp cs:foo */ + + /* restoring VMA previous settings */ syscall_check( (int)mprotect((void*)TRAMPOLINE_ADDR, _getpagesize, PROT_READ|PROT_EXEC), 0, "mmap"); @@ -101,7 +108,6 @@ void read_chunk_regs(void *fptr, int action) { - struct user user; int stopped; read_bit(fptr, &user, sizeof(struct user)); read_bit(fptr, &stopped, sizeof(int)); @@ -112,7 +118,7 @@ user.regs.eax, user.regs.ebx, user.regs.ecx, user.regs.edx); fprintf(stderr, "\tesi: 0x%08lx edi: 0x%08lx ebp: 0x%08lx esp: 0x%08lx\n", user.regs.esi, user.regs.edi, user.regs.ebp, user.regs.esp); - fprintf(stderr, "\t ds: 0x%08x es: 0x%08x fs: 0x%08x gs: 0x%08x\n", + fprintf(stderr, "\t ds: 0x%08lx es: 0x%08lx fs: 0x%08lx gs: 0x%08lx\n", user.regs.xds, user.regs.xes, user.regs.xfs, user.regs.xgs); fprintf(stderr, "\teip: 0x%08lx eflags: 0x%08lx", user.regs.eip, user.regs.eflags); diff -r 26423726a075 -r 083a0b9b734c src/arch-i386/cp_r_tls.c --- a/src/arch-i386/cp_r_tls.c Wed Jun 24 16:23:46 2009 +0200 +++ b/src/arch-i386/cp_r_tls.c Sat Jul 25 20:01:35 2009 +0200 @@ -33,7 +33,7 @@ return; if (action & ACTION_PRINT) - fprintf(stderr, "TLS entry (%d): base_addr = 0x%lx", + fprintf(stderr, "TLS entry (%d): base_addr = 0x%x", u.entry_number, u.base_addr); if (!(action & ACTION_LOAD)) diff -r 26423726a075 -r 083a0b9b734c src/arch-i386/cp_w_tls.c --- a/src/arch-i386/cp_w_tls.c Wed Jun 24 16:23:46 2009 +0200 +++ b/src/arch-i386/cp_w_tls.c Sat Jul 25 20:01:35 2009 +0200 @@ -31,9 +30,10 @@ } u->entry_number = i; if (ptrace(PTRACE_GET_THREAD_AREA, pid, i, u) == -1) { + debug("TLS segment #%d unfetchable", i); continue; } - + printf("[+] TLS segment #%d fetched: base address at 0x%x\n", i, u->base_addr); chunk = xmalloc(sizeof(struct cp_chunk)); chunk->type = CP_CHUNK_TLS; chunk->tls.u = u; diff -r 26423726a075 -r 083a0b9b734c src/arch-i386/cplayout.h --- a/src/arch-i386/cplayout.h Wed Jun 24 16:23:46 2009 +0200 +++ b/src/arch-i386/cplayout.h Sat Jul 25 20:01:35 2009 +0200 @@ -1,7 +1,9 @@ #ifndef _CPLAYOUT_H_ #define _CPLAYOUT_H_ -#define TRAMPOLINE_ADDR 0x00800000 /* 8MB mark */ +#define SIGNATURE_LENGTH 32 /* # of bytes of __getpid signature to extract */ +#define TRAMPOLINE_ADDR 0x00800000 /* 8MB mark */ +#define GETPID_HACK_ADDR 0x00801000 /* address for _getpid code */ #define RESUMER_START 0x00000000 /* Lowest location resumer will be at */ #define RESUMER_END 0x00800000 /* Highest location resumer will be at */ diff -r 26423726a075 -r 083a0b9b734c src/arch-i386/elfwriter.c --- a/src/arch-i386/elfwriter.c Wed Jun 24 16:23:46 2009 +0200 +++ b/src/arch-i386/elfwriter.c Sat Jul 25 20:01:35 2009 +0200 @@ -60,14 +60,14 @@ * ie, offset = offset - round_to_page(code_len) - round_to_page(data_len) */ - e = (Elf32_Ehdr*)stub_start; + e = (Elf32_Ehdr*)stub_start; /* pointer to our ELF header */ - assert(e->e_shoff != 0); - assert(e->e_shentsize == sizeof(Elf32_Shdr)); - assert(e->e_shstrndx != SHN_UNDEF); + assert(e->e_shoff != 0); /* check section header tables file offset */ + assert(e->e_shentsize == sizeof(Elf32_Shdr)); /* check section header entry size */ + assert(e->e_shstrndx != SHN_UNDEF); /* must exist a section name string table */ - s = (Elf32_Shdr*)(stub_start+(e->e_shoff+(e->e_shstrndx*e->e_shentsize))); - strtab = stub_start+s->sh_offset; /* string table start */ + s = (Elf32_Shdr*)(stub_start+(e->e_shoff+(e->e_shstrndx*e->e_shentsize))); /* Elf32_Shdr start for name string table */ + strtab = stub_start+s->sh_offset; /* string table start, from the beginning of the ELF */ /* Locate where this binary's brk would start */ for (i = 0; i < e->e_phnum; i++) { @@ -88,7 +88,7 @@ got_it = 0; for (i = 0; i < e->e_shnum; i++) { s = (Elf32_Shdr*)(stub_start+e->e_shoff+(i*e->e_shentsize)); - /* sh_addr: this member gives the address at which the sections first byte should reside in the process image */ + /* sh_addr: address at which the sections first byte should reside in the process image */ s->sh_addr += offset; if (s->sh_type != SHT_PROGBITS || s->sh_name == 0) @@ -110,6 +110,10 @@ mmap_prot = PROT_READ | PROT_WRITE; if (p->p_flags & PF_X) mmap_prot |= PROT_EXEC; + /* + p_vaddr: virtual address at which the first byte of the segment resides in memory + p_memsz: number of bytes in the memory image of the segment; it may be zero + */ mmap_addr = p->p_vaddr & ~(_getpagesize - 1); mmap_len = p->p_memsz + (p->p_vaddr - mmap_addr); mmap_len = (mmap_len + (_getpagesize - 1)) & ~(_getpagesize - 1); diff -r 26423726a075 -r 083a0b9b734c src/arch-i386/getpid_hack_r.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch-i386/getpid_hack_r.c Sat Jul 25 20:01:35 2009 +0200 @@ -0,0 +1,60 @@ +/* module to manage host libc __getpid stored in the image (ELF) file */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cpimage.h" +#include "cryopid.h" + +extern struct user_regs_struct* regs(void); + +static void libc_hack_load(char* data) +{ + char *dest = (char*)GETPID_HACK_ADDR; + struct user_regs_struct *r = regs(); + + /* Create region for __getpid refresh hack */ + syscall_check( + (int)mmap((void*)GETPID_HACK_ADDR, _getpagesize, PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0), 0, "mmap"); + + /* set up gs */ + if (!emulate_tls && r->xgs != 0) { + *dest++=0x66;*dest++=0xb8; *(short*)(dest) = r->xgs; dest+=2; /* mov foo, %eax */ + *dest++=0x8e;*dest++=0xe8; /* mov %eax, %gs */ + *dest++=0xba;*dest++=0x00;*dest++=0x00;*dest++=0x00;*dest++=0x00; /* mov $0x00, %edx */ + *dest++=0xb9;*dest++=0x00;*dest++=0x00;*dest++=0x00;*dest++=0x00; /* mov $0x00, %ecx */ + + /* insert the assembly code of __getpid */ + memcpy(dest, data, SIGNATURE_LENGTH); + } + + /* restoring VMA previous settings */ + syscall_check( + (int)mprotect((void*)GETPID_HACK_ADDR, _getpagesize, PROT_READ|PROT_EXEC), + 0, "mmap"); +} + +void read_chunk_getpid(void *fptr, int action) +{ + char* signature = (char*) xmalloc(SIGNATURE_LENGTH); + read_bit(fptr, signature, SIGNATURE_LENGTH); + if (action & ACTION_PRINT) { + int i; + /* printf out signature's bytes */ + info("__getpid hack signature:\n"); + for (i = 0; i < SIGNATURE_LENGTH; i++) { + info("[%d] byte value: 0x%02x\t", i, (unsigned char) *(signature + i)); + if ((!(i % 4) && (i != 0)) || (i == (SIGNATURE_LENGTH-1))) + info("\n"); + } + } + if (action & ACTION_LOAD) + libc_hack_load(signature); +} diff -r 26423726a075 -r 083a0b9b734c src/arch-i386/getpid_hack_w.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/arch-i386/getpid_hack_w.c Sat Jul 25 20:01:35 2009 +0200 @@ -0,0 +1,122 @@ +/* module to manage host libc __getpid: locate, fetch and store */ +#include +#include +#include +#include +#include + +#include "cpimage.h" +#include "cryopid.h" + +int libc_hack_fetch(const char* name, char** signature) +{ + Elf32_Ehdr libc_ehdr; + Elf32_Shdr libc_shdr, libc_st; + Elf32_Off libc_stoff, dynsym_off, dynstr_off; + Elf32_Word dynsym_size, dynstr_size; + Elf32_Sym libc_sym; + int libc_fd, i; + char *strtab = NULL, + *dynsym = NULL, + *dynstr = NULL; + unsigned char asmbyte; + + libc_fd = open(name, O_RDONLY); + if (libc_fd == -1) + bail("[E] failed to open %s\n", name); + + read(libc_fd, &libc_ehdr, sizeof(Elf32_Ehdr)); + + assert(libc_ehdr.e_shoff != 0); /* check section header tables file offset */ + assert(libc_ehdr.e_shentsize == sizeof(Elf32_Shdr)); /* check section header entry size */ + assert(libc_ehdr.e_shstrndx != SHN_UNDEF); /* must exist a section name string table */ + + //info("[i] section header table's offeset is: %d\n", libc_ehdr.e_shoff); + libc_stoff = libc_ehdr.e_shoff + (libc_ehdr.e_shstrndx * libc_ehdr.e_shentsize); + if (lseek(libc_fd, libc_stoff, SEEK_SET) == -1) /* seek to section name string table header */ + bail("[E] failed to seek to section name string table header"); + read(libc_fd, &libc_st, sizeof(Elf32_Shdr)); + assert(libc_st.sh_type == SHT_STRTAB); + //info("[i] string table offset from file start is: %u\n", libc_st.sh_offset); + + /* fetch string table */ + strtab = (char*) xmalloc(libc_st.sh_size); + if (lseek(libc_fd, libc_st.sh_offset, SEEK_SET) == -1) /* seek to section name string table */ + bail("[E] failed to seek to section name string table"); + if (read(libc_fd, strtab, libc_st.sh_size) != libc_st.sh_size) + info("[W] failed to read the %u bytes of string table\n", libc_st.sh_size); + + /* search .dynsym and .dynstr sections + 1- it holds the dynamic linking symbol table + 2- it holds strings needed for dynamic linking + */ + if (lseek(libc_fd, libc_ehdr.e_shoff, SEEK_SET) == -1) /* seek to section header table */ + bail("[E] failed to seek at %d bytes to section header table", libc_ehdr.e_shoff); + for (i = 0; i < libc_ehdr.e_shnum; i++) { + read(libc_fd, &libc_shdr, sizeof(Elf32_Shdr)); + if (libc_shdr.sh_type == SHT_DYNSYM) { /* libc .dynsym section */ + //info("[i] .dynsym checked as #%d section\n", i); + dynsym_off = libc_shdr.sh_offset; + dynsym_size = libc_shdr.sh_size; + dynsym = (char*) xmalloc(dynsym_size); + } + /* libc .dynstr section */ + if ((libc_shdr.sh_type == SHT_STRTAB) && !strcmp(strtab + libc_shdr.sh_name, ".dynstr")) { + //info("[i] .dynstr checked as #%d section\n", i); + dynstr_off = libc_shdr.sh_offset; + dynstr_size = libc_shdr.sh_size; + dynstr = (char*) xmalloc(dynstr_size); + } + } + + /* fetch .dynsym and .dynstr sections */ + if (lseek(libc_fd, dynsym_off, SEEK_SET) == -1) /* seek to .dynsym section */ + bail("[E] failed to seek to .dynsym section"); + if (read(libc_fd, dynsym, dynsym_size) != dynsym_size) + info("[W] failed to read the %u bytes of .dynsym section\n", dynsym_size); + if (lseek(libc_fd, dynstr_off, SEEK_SET) == -1) /* seek to .dynstr section */ + bail("[E] failed to seek to .dynstr section"); + if (read(libc_fd, dynstr, dynstr_size) != dynstr_size) + info("[W] failed to read the %u bytes of .dynstr section\n", dynstr_size); + + //info("[i] dynamic symbol elements are: %d\n", dynsym_size / sizeof(Elf32_Sym)); + /* looking for __getpid symbol */ + for (i = 0; i < (dynsym_size / sizeof(Elf32_Sym)); i++) { + memcpy(&libc_sym, dynsym + (i * sizeof(Elf32_Sym)), sizeof(Elf32_Sym)); + if ((ELF32_ST_TYPE(libc_sym.st_info) == STT_FUNC) + && strstr(dynstr + libc_sym.st_name, "__getpid")) { + info("[+] __getpid symbol found as #%d element at address 0x%x\n", i, libc_sym.st_value); + break; + } + } + /* now libc_sym keeps all __getpid symbol information */ + if (lseek(libc_fd, libc_sym.st_value, SEEK_SET) == -1) /* seek to .dynsym section */ + bail("[E] failed to seek to __getpid location at 0x%x", libc_sym.st_value); + while (1) { + if (read(libc_fd, &asmbyte, 1) == -1) + bail("[E] failde to read from __getpid"); + //info("[asmbyte] asm byte: 0x%02x\n", (unsigned char) asmbyte); + if (asmbyte == 0xb8) + break; + } + if (lseek(libc_fd, -1, SEEK_CUR) == -1) /* seek to 0xb8 */ + bail("[E] failed to seek backward to 0xb8"); + *signature = (char*) xmalloc(SIGNATURE_LENGTH); + /* fetch the signature from libc */ + memset(*signature, 0, SIGNATURE_LENGTH); + if (read(libc_fd, *signature, SIGNATURE_LENGTH) == -1) + bail("[E] unable to fetch the signature"); + info("[+] __getpid signature fetched\n"); + /* free all the memory space allacated */ + free(dynsym); + free(dynstr); + /* close libc file */ + close(libc_fd); + + return EXIT_SUCCESS; +} + +void write_chunk_getpid(void* fptr, struct cp_getpid* data) +{ + write_bit(fptr, data->asmcode, SIGNATURE_LENGTH); +} diff -r 26423726a075 -r 083a0b9b734c src/arch-i386/process.c --- a/src/arch-i386/process.c Wed Jun 24 16:23:46 2009 +0200 +++ b/src/arch-i386/process.c Sat Jul 25 20:01:35 2009 +0200 @@ -230,6 +230,7 @@ int success = 0; char* pagebackup; struct user_regs_struct r; + struct cp_chunk *libcgp; start_ptrace(pid); @@ -258,6 +259,10 @@ fetch_chunks_i387_data(pid, flags, process_image); fetch_chunks_regs(pid, flags, process_image, process_was_stopped); + /* add __getpid chunk to the image list */ + fetch_chunk_libcgp(&libcgp); + list_append(process_image, libcgp); + success = 1; restore_page(pid, (void*)scribble_zone, pagebackup); diff -r 26423726a075 -r 083a0b9b734c src/arch-i386/stub.h --- a/src/arch-i386/stub.h Wed Jun 24 16:23:46 2009 +0200 +++ b/src/arch-i386/stub.h Sat Jul 25 20:01:35 2009 +0200 @@ -4,6 +4,11 @@ #include #include "cryopid.h" +static inline void jump_to_getpid_hack() +{ + asm("call *%%eax\n" : : "a"(GETPID_HACK_ADDR)); +} + static inline void jump_to_trampoline() { asm("jmp *%%eax\n" : : "a"(TRAMPOLINE_ADDR)); @@ -38,8 +43,9 @@ 0, "mmap(newstack)"); memset(top_of_new_stack - size_of_new_stack, 0, size_of_new_stack); memcpy(top_of_new_stack - size_of_new_stack, - top_of_old_stack - size_of_new_stack, /* FIX ME */ + top_of_old_stack - size_of_new_stack, /* FIXME */ size_of_new_stack); + /* relocate %esp and %ebp value in confirmation of the new stack */ __asm__ ("addl %0, %%esp" : : "a"(top_of_new_stack - top_of_old_stack)); __asm__ ("addl %0, %%ebp" : : "a"(top_of_new_stack - top_of_old_stack)); diff -r 26423726a075 -r 083a0b9b734c src/cp_w_vma.c --- a/src/cp_w_vma.c Wed Jun 24 16:23:46 2009 +0200 +++ b/src/cp_w_vma.c Sat Jul 25 20:01:35 2009 +0200 @@ -9,6 +9,10 @@ #include "cpimage.h" #include "process.h" #include "cryopid.h" +#ifdef __i386__ +#include "getpid_hack.h" +static struct cp_chunk *gp_chunk = NULL; +#endif unsigned long scribble_zone = 0; /* somewhere to scribble on in child */ unsigned long syscall_loc = 0; /* address of a syscall instruction */ @@ -32,6 +36,13 @@ write_bit(fptr, data->data, data->length); } +#ifdef __i386__ +void fetch_chunk_libcgp(struct cp_chunk** ptr) +{ + *ptr = gp_chunk; +} +#endif + static int get_one_vma(pid_t pid, char* line, struct cp_vma *vma, int get_library_data, int vma_no, long *bin_offset) { @@ -256,7 +267,7 @@ unsigned int c; static char buf[4096]; - keep_vma_data = 1; /* Assume guiltly until proven innocent */ + keep_vma_data = 1; /* Assume guilty until proven innocent */ if ((lfd = open(vma->filename, O_RDONLY)) == -1) goto out; @@ -357,6 +368,15 @@ i = work_list.head; continue; } + #ifdef __i386__ + if (chunk->vma.filename != NULL) + if ((strstr(chunk->vma.filename, "libc") != NULL) && !gp_chunk) { + info("[+] libc mapping found: %s\n", chunk->vma.filename); + gp_chunk = xmalloc(sizeof(struct cp_chunk)); + gp_chunk->type = CP_CHUNK_GETPID; + libc_hack_fetch(chunk->vma.filename, &gp_chunk->signature.asmcode); + } + #endif vma_no++; list_append(l, chunk); chunk = NULL; diff -r 26423726a075 -r 083a0b9b734c src/cpimage.h --- a/src/cpimage.h Wed Jun 24 16:23:46 2009 +0200 +++ b/src/cpimage.h Sat Jul 25 20:01:35 2009 +0200 @@ -30,7 +30,8 @@ #define CP_CHUNK_FD 0x06 #define CP_CHUNK_VMA 0x07 #define CP_CHUNK_SIGHAND 0x08 -#define CP_CHUNK_FINAL 0x09 +#define CP_CHUNK_FINAL 0x0a +#define CP_CHUNK_GETPID 0x09 #define CP_CHUNK_MAGIC 0xC0DE @@ -58,14 +59,18 @@ }; struct cp_regs { - struct user32 *user_data; + struct user *user_data; void *opaque; /* For arch-specific data */ int stopped; }; #ifdef __i386__ +struct cp_getpid { + char* asmcode; +}; + struct cp_i387_data { - struct user_i387_ia32_struct* i387_data; + struct user_fpregs_struct* i387_data; }; struct cp_tls { @@ -158,6 +163,7 @@ #ifdef __i386__ struct cp_i387_data i387_data; struct cp_tls tls; + struct cp_getpid signature; #endif }; }; @@ -245,6 +251,9 @@ void write_chunk_fd_socket(void *fptr, struct cp_socket *socket); /* cp_vma.c */ +#ifdef __i386__ +void fetch_chunk_libcgp(struct cp_chunk** ptr); +#endif void fetch_chunks_vma(pid_t pid, int flags, struct list *l, long *bin_offset); void read_chunk_vma(void *fptr, int action); void write_chunk_vma(void *fptr, struct cp_vma *data); diff -r 26423726a075 -r 083a0b9b734c src/cpimage_r.c --- a/src/cpimage_r.c Wed Jun 24 16:23:46 2009 +0200 +++ b/src/cpimage_r.c Sat Jul 25 20:01:35 2009 +0200 @@ -5,6 +5,9 @@ #include "cpimage.h" #include "cryopid.h" #include "list.h" +#ifdef __i386__ +#include "getpid_hack.h" +#endif void read_bit(void *fptr, void *buf, int len) @@ -101,6 +104,9 @@ case CP_CHUNK_TLS: read_chunk_tls(fptr, action); break; + case CP_CHUNK_GETPID: + read_chunk_getpid(fptr, action); + break; #endif case CP_CHUNK_FINAL: if (action & ACTION_PRINT) diff -r 26423726a075 -r 083a0b9b734c src/cpimage_w.c --- a/src/cpimage_w.c Wed Jun 24 16:23:46 2009 +0200 +++ b/src/cpimage_w.c Sat Jul 25 20:01:35 2009 +0200 @@ -5,6 +5,9 @@ #include "cpimage.h" #include "cryopid.h" #include "list.h" +#ifdef __i386__ +#include "getpid_hack.h" +#endif void write_bit(void *fptr, void *buf, int len) @@ -69,6 +72,9 @@ case CP_CHUNK_TLS: write_chunk_tls(fptr, &chunk->tls); break; + case CP_CHUNK_GETPID: + write_chunk_getpid(fptr, &chunk->signature); + break; #endif default: bail("Unknown chunk type to write (0x%x)", chunk->type) diff -r 26423726a075 -r 083a0b9b734c src/getpid_hack.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/getpid_hack.h Sat Jul 25 20:01:35 2009 +0200 @@ -0,0 +1,11 @@ +#ifndef _GETPID_HACK_ +#define _GETPID_HACK_ + +/* getpid_hack_w */ +extern int libc_hack_fetch(const char* name, char** signature); +extern void write_chunk_getpid(void* fptr, struct cp_getpid* data); + +/* getpid_hack_r */ +extern void read_chunk_getpid(void *fptr, int action); + +#endif /* _GETPID_HACK_ */ diff -r 26423726a075 -r 083a0b9b734c src/stub_common.c --- a/src/stub_common.c Wed Jun 24 16:23:46 2009 +0200 +++ b/src/stub_common.c Sat Jul 25 20:01:35 2009 +0200 @@ -57,6 +57,9 @@ if (do_pause) sleep(2); + #ifdef __i386__ + jump_to_getpid_hack(); + #endif jump_to_trampoline(); } @@ -137,7 +140,7 @@ long_options, &option_index); if (c == -1) break; - switch(c) { + switch (c) { case 'd': action &= ~ACTION_LOAD; action |= ACTION_PRINT;