From c95b8b8f04572fb3409530982451e7a5fd122673 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 24 Jan 2012 06:24:30 +0100 Subject: Add initial version of ptrace finder for x64. --- exit-ptrace-finder.c | 217 ------------------------------------------------- ptrace-offset-finder.c | 46 +++++++++++ 2 files changed, 46 insertions(+), 217 deletions(-) delete mode 100644 exit-ptrace-finder.c create mode 100644 ptrace-offset-finder.c diff --git a/exit-ptrace-finder.c b/exit-ptrace-finder.c deleted file mode 100644 index 22b719d..0000000 --- a/exit-ptrace-finder.c +++ /dev/null @@ -1,217 +0,0 @@ -/* NOTE: this code does not yet work */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Much from http://www.phrack.org/issues.html?issue=59&id=8#article - -#if defined(__i386__) -#define Elf_Dyn Elf32_Dyn -#define Elf_Ehdr Elf32_Ehdr -#define Elf_Phdr Elf32_Phdr -#define Elf_Sym Elf32_Sym -#define Elf_Word Elf32_Word -#define Elf_Start 0x08048000 -#elif defined(__x86_64__) -#define Elf_Dyn Elf64_Dyn -#define Elf_Ehdr Elf64_Ehdr -#define Elf_Phdr Elf64_Phdr -#define Elf_Sym Elf64_Sym -#define Elf_Word Elf64_Word -#define Elf_Start 0x00400000 -#else -#error "What elf arch?" -#endif - - -/* - * search locations of DT_SYMTAB and DT_STRTAB and save them into global - * variables, also save the nchains from hash table. - */ - -unsigned long symtab; -unsigned long strtab; -int nchains; - -/* attach to pid */ -void ptrace_attach(int pid) -{ - if ((ptrace(PTRACE_ATTACH, pid, NULL, NULL)) < 0) { - perror("[-] ptrace_attach"); - exit(-1); - } - waitpid(pid, NULL, WUNTRACED); -} - -/* detach process */ -void ptrace_detach(int pid) -{ - if (ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0) { - perror("[-] ptrace_detach"); - exit(-1); - } -} - -/* read data from location addr */ -void read_data(int pid, unsigned long addr, void *vptr, int len) -{ - int i, count; - long word; - unsigned long *ptr = (unsigned long *)vptr; - count = i = 0; - while (count < len) { - word = ptrace(PTRACE_PEEKTEXT, pid, addr + count, NULL); - count += 4; - ptr[i++] = word; - } -} - -/* read string from pid's memory */ -char *read_str(int pid, unsigned long addr, int len) -{ - char *ret = calloc(32, sizeof(char)); - read_data(pid, addr, ret, len); - return ret; -} - -/* write data to location addr */ -void write_data(int pid, unsigned long addr, void *vptr, int len) -{ - int i, count; - long word; - i = count = 0; - while (count < len) { - memcpy(&word, vptr + count, sizeof(word)); - word = ptrace(PTRACE_POKETEXT, pid, addr + count, word); - count += 4; - } -} - -/* locate link-map in pid's memory */ -struct link_map *locate_linkmap(int pid) -{ - Elf_Ehdr *ehdr = malloc(sizeof(Elf_Ehdr)); - Elf_Phdr *phdr = malloc(sizeof(Elf_Phdr)); - Elf_Dyn *dyn = malloc(sizeof(Elf_Dyn)); - Elf_Word got; - struct link_map *l = malloc(sizeof(struct link_map)); - unsigned long phdr_addr, dyn_addr, map_addr; - - /* - * first we check from elf header, mapped at 0x08048000, the offset - * to the program header table from where we try to locate - * PT_DYNAMIC section. - */ - - read_data(pid, Elf_Start, ehdr, sizeof(Elf_Ehdr)); - phdr_addr = Elf_Start + ehdr->e_phoff; - printf("[+] Program header at %p.\n", (void *)phdr_addr); - read_data(pid, phdr_addr, phdr, sizeof(Elf_Phdr)); - - while (phdr->p_type != PT_DYNAMIC) - read_data(pid, phdr_addr += sizeof(Elf_Phdr), phdr, sizeof(Elf_Phdr)); - - /* - * now go through dynamic section until we find address of the GOT - */ - - read_data(pid, phdr->p_vaddr, dyn, sizeof(Elf_Dyn)); - dyn_addr = phdr->p_vaddr; - - while (dyn->d_tag != DT_PLTGOT) - read_data(pid, dyn_addr += sizeof(Elf_Dyn), dyn, sizeof(Elf_Dyn)); - - got = (Elf_Word)dyn->d_un.d_ptr; - got += 4; /* second GOT entry, remember? */ - /* - * now just read first link_map item and return it - */ - read_data(pid, (unsigned long)got, &map_addr, 4); - read_data(pid, map_addr, l, sizeof(struct link_map)); - free(phdr); - free(ehdr); - free(dyn); - return l; -} - -/* resolve the tables for symbols*/ -void resolv_tables(int pid, struct link_map *map) -{ - Elf_Dyn *dyn = malloc(sizeof(Elf_Dyn)); - unsigned long addr; - addr = (unsigned long)map->l_ld; - read_data(pid, addr, dyn, sizeof(Elf_Dyn)); - while (dyn->d_tag) { - switch (dyn->d_tag) { - case DT_HASH: - read_data(pid, dyn->d_un.d_ptr + map->l_addr + 4, &nchains, sizeof(nchains)); - break; - case DT_STRTAB: - strtab = dyn->d_un.d_ptr; - break; - case DT_SYMTAB: - symtab = dyn->d_un.d_ptr; - break; - default: - break; - } - addr += sizeof(Elf_Dyn); - read_data(pid, addr, dyn, sizeof(Elf_Dyn)); - } - free(dyn); -} - -/* find symbol in DT_SYMTAB */ -unsigned long find_sym_in_tables(int pid, struct link_map *map, char *sym_name) -{ - Elf_Sym *sym = malloc(sizeof(Elf_Sym)); - char *str; - int i = 0; - while (i < nchains) { - read_data(pid, symtab + (i * sizeof(Elf_Sym)), sym, sizeof(Elf_Sym)); - i++; - if (ELF32_ST_TYPE(sym->st_info) != STT_FUNC) - continue; - - /* read symbol name from the string table */ - str = read_str(pid, strtab + sym->st_name, 32); - printf("%s\n", str); - /* compare it with our symbol*/ - if (strcmp(str, sym_name) == 0) { - printf("[+] Found symbol.\n"); - return (map->l_addr + sym->st_value); - } - } - /* no symbol found, return 0 */ - return 0; -} - -int main(int argc, char *argv[]) -{ - int child = fork(); - if (child) { - wait(NULL); - struct link_map *map = locate_linkmap(child); - printf("[+] Link map located.\n"); - resolv_tables(child, map); - char symbol[] = "exit"; - unsigned long address = find_sym_in_tables(child, map, symbol); - if (!symbol) - printf("[+] The value of %s is %lx.\n", symbol, address); - else - printf("[-] No such symbol %s.\n", symbol); - ptrace_detach(child); - } else { - ptrace(PTRACE_TRACEME, 0, NULL, NULL); - execl("/bin/su", "su", "not-a-valid-user", NULL); - } - return 0; -} diff --git a/ptrace-offset-finder.c b/ptrace-offset-finder.c new file mode 100644 index 0000000..34e5682 --- /dev/null +++ b/ptrace-offset-finder.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int fd[2]; + pipe2(fd, O_NONBLOCK); + int child = fork(); + if (child) { + close(fd[1]); + char buf; + for (;;) { + wait(NULL); + if (read(fd[0], &buf, 1) > 0) + break; + ptrace(PTRACE_SYSCALL, child, NULL, NULL); + } + + struct user_regs_struct regs; + for (;;) { + ptrace(PTRACE_SINGLESTEP, child, NULL, NULL); + wait(NULL); + ptrace(PTRACE_GETREGS, child, NULL, ®s); + if (regs.rip < 0x700000000000) { + printf("0x%lx\n", regs.rip); + break; + } + } + } else { + ptrace(PTRACE_TRACEME, 0, NULL, NULL); + close(fd[0]); + dup2(fd[1], 2); + execl("/bin/su", "su", "not-a-valid-user", NULL); + } + return 0; +} -- cgit v1.2.3-59-g8ed1b