static void ui_read( const pid_t child_pid, const char *line) { char *dupline = strdup(line); if (!dupline) { perror("strdup"); return; } char *saveptr; const char *dotread = strtok_r(dupline, " ", &saveptr); if (!dotread || strcasecmp(dotread, ".read")) goto bail; const char *addr_str = strtok_r(NULL, " ", &saveptr); if (!addr_str) goto bail; errno = 0; const unsigned long addr = strtoul(addr_str, NULL, 0); if (addr == ULONG_MAX && errno) { perror("strtoul"); goto bail; } const char *sz_str = strtok_r(NULL, " ", &saveptr); unsigned long sz = 0x10; if (sz_str && strlen(sz_str)) { errno = 0; sz = strtoul(sz_str, NULL, 0); if (sz == ULONG_MAX && errno) { perror("strtoul"); goto bail; } } uint8_t *buf = xmalloc(sz); if (!ptrace_read(child_pid, (void *)addr, buf, sz)) dump(buf, sz, addr); free(buf); bail: free(dupline); }
int print_sharelib_runtime (pid_t pid) { struct link_map *lm = (struct link_map *) malloc (sizeof (struct link_map)); char *str; printf ("-------- runtime process --------\n"); printf ("PROCESS ID: [%d]\n", pid); lm = get_linkmap (pid); if (!lm) return -1; #if 0 str = ptrace_readstr (pid, (unsigned long) lm->l_name); printf ("[%s]\n", str); free (str); #endif if (!lm->l_next) return -1; ptrace_read (pid, (unsigned long) lm->l_next, lm, sizeof (struct link_map)); while (lm->l_next) { ptrace_read (pid, (unsigned long) lm->l_next, lm, sizeof (struct link_map)); str = ptrace_readstr (pid, (unsigned long) lm->l_name); printf ("[%s]\n", str); free (str); } printf ("------------ end ------------\n"); return 0; }
dl_fl_t *ptrace_find_dlinfo(int pid) { Elf32_Sym sym; Elf32_Addr addr; struct soinfo lsi; #define LIBDLSO "libdl.so" Elf32_Addr base_start = 0; Elf32_Addr base_end = 0; Elf32_Addr base = get_linker_base(pid, &base_start, &base_end); if (base == 0) { printf("no linker found\n"); return NULL ; } else { printf("search libdl.so from %08u to %08u\n", base_start, base_end); } for (addr = base_start; addr < base_end; addr += 4) { char soname[strlen(LIBDLSO)]; Elf32_Addr off = 0; ptrace_read(pid, addr, soname, strlen(LIBDLSO)); if (strncmp(LIBDLSO, soname, strlen(LIBDLSO))) { continue; } printf("soinfo found at %08u\n", addr); printf("symtab: %p\n", lsi.symtab); ptrace_read(pid, addr, &lsi, sizeof(lsi)); off = (Elf32_Addr)lsi.symtab; ptrace_read(pid, off, &sym, sizeof(sym)); //just skip off += sizeof(sym); ptrace_read(pid, off, &sym, sizeof(sym)); ldl.l_dlopen = sym.st_value; off += sizeof(sym); ptrace_read(pid, off, &sym, sizeof(sym)); ldl.l_dlclose = sym.st_value; off += sizeof(sym); ptrace_read(pid, off, &sym, sizeof(sym)); ldl.l_dlsym = sym.st_value; off += sizeof(sym); printf("dlopen addr %p\n", (void*) ldl.l_dlopen); printf("dlclose addr %p\n", (void*) ldl.l_dlclose); printf("dlsym addr %p\n", (void*) ldl.l_dlsym); return &ldl; } printf("%s not found!\n", LIBDLSO); return NULL ; }
int main (int argc, char *argv[]) { int pid; struct link_map *map; char sym_name[256]; unsigned long sym_addr; unsigned long new_addr, old_addr, rel_addr; pid = atoi (argv[1]); ptrace_attach (pid); map = get_linkmap (pid); sym_addr = find_symbol (pid, map, "_dl_open"); printf ("found _dl_open at addr %p\n", sym_addr); call_dl_open (pid, sym_addr, "/home/joker/JustForFun/Injectso/passwd/so.so"); /* 找到我们的新函数newread的地址 */ strcpy (sym_name, "newread"); /* intercept */ sym_addr = find_symbol (pid, map, sym_name); printf ("%s addr\t %p\n", sym_name, sym_addr); /* 找到read的RELOCATION地址 */ strcpy (sym_name, "read"); rel_addr = find_sym_in_rel (pid, sym_name); printf ("%s rel addr\t %p\n", sym_name, rel_addr); /* 找到用于保存read地址的指针 */ strcpy (sym_name, "oldread"); old_addr = find_symbol (pid, map, sym_name); printf ("%s addr\t %p\n", sym_name, old_addr); /* 函数重定向 */ puts ("intercept..."); /* intercept */ ptrace_read (pid, rel_addr, &new_addr, sizeof (new_addr)); ptrace_write (pid, old_addr, &new_addr, sizeof (new_addr)); ptrace_write (pid, rel_addr, &sym_addr, sizeof (sym_addr)); puts ("injectso ok"); /* 脱离进程 */ ptrace_detach (pid); exit (0); }
void call_shit(struct elf_info *einfo) { unsigned long addr2 = 0; unsigned long rel_addr = find_sym_in_rel(einfo, "math_shit"); regs_t regs; ptrace_read(einfo->pid, rel_addr, &addr2, sizeof(long)); printf("math_shit rel addr\t %lx\n", rel_addr); printf("addr2 is \t %lx\n", addr2); ptrace_readreg(einfo->pid, ®s); ptrace_dump_regs(®s,"before call to call_shit\n"); #ifdef THUMB regs.ARM_lr = 1; #else regs.ARM_lr = 0; #endif regs.ARM_r0 = 5; regs.ARM_r1 = 6; regs.ARM_r2 = 7; regs.ARM_r3 = 8; { int a5 = 9; ptrace_push(einfo->pid, ®s, &a5, 4); ptrace_push(einfo->pid, ®s, &a5, 4); ptrace_push(einfo->pid, ®s, &a5, 4); ptrace_push(einfo->pid, ®s, &a5, 4); ptrace_push(einfo->pid, ®s, &a5, 4); ptrace_push(einfo->pid, ®s, &a5, 4); ptrace_push(einfo->pid, ®s, &a5, 4); ptrace_push(einfo->pid, ®s, &a5, 4); ptrace_push(einfo->pid, ®s, &a5, 4); a5 = 10; ptrace_push(einfo->pid, ®s, &a5, 4); } regs.ARM_pc = addr2; ptrace_writereg(einfo->pid, ®s); ptrace_cont(einfo->pid); printf("done %d\n", ptrace_wait_for_signal(einfo->pid,SIGSEGV)); ptrace_readreg(einfo->pid, ®s); ptrace_dump_regs(®s,"before return call_shit\n"); }
static struct link_map * get_linkmap (pid_t pid) { Elf32_Ehdr *ehdr = (Elf32_Ehdr *) malloc (sizeof (Elf32_Ehdr)); Elf32_Phdr *phdr = (Elf32_Phdr *) malloc (sizeof (Elf32_Phdr)); Elf32_Dyn *dyn = (Elf32_Dyn *) malloc (sizeof (Elf32_Dyn)); Elf32_Word got; unsigned long phdr_addr, dyn_addr, map_addr; struct link_map *map = (struct link_map *) malloc (sizeof (struct link_map)); int i = 0; ptrace_read (pid, IMAGE_ADDR, ehdr, sizeof (Elf32_Ehdr)); phdr_addr = IMAGE_ADDR + ehdr->e_phoff; ptrace_read (pid, phdr_addr, phdr, sizeof (Elf32_Phdr)); while (phdr->p_type != PT_DYNAMIC) ptrace_read (pid, phdr_addr += sizeof (Elf32_Phdr), phdr, sizeof (Elf32_Phdr)); dyn_addr = phdr->p_vaddr; ptrace_read (pid, dyn_addr, dyn, sizeof (Elf32_Dyn)); while (dyn->d_tag != DT_PLTGOT) { ptrace_read (pid, dyn_addr + i * sizeof (Elf32_Dyn), dyn, sizeof (Elf32_Dyn)); i++; } got = (Elf32_Word) dyn->d_un.d_ptr; got += 4; ptrace_read (pid, got, &map_addr, 4); ptrace_read (pid, map_addr, map, sizeof (struct link_map)); free (ehdr); free (phdr); free (dyn); return map; }
void inject_restore_socketcall(struct tracedump *td, struct pid *sp) { /* int 0x80, int3 */ unsigned char code[4] = { 0xcd, 0x80, 0xcc, 0 }; char backup[4]; struct user_regs_struct regs2; /* backup */ ptrace_read(sp, sp->regs.eip, backup, 4); /* exec */ sp->regs.eax = sp->regs.orig_eax; ptrace_setregs(sp, &sp->regs); ptrace_write(sp, sp->regs.eip, code, 4); ptrace_cont(sp, 0, true); /* read the return code */ ptrace_getregs(sp, ®s2); sp->regs.eax = regs2.eax; /* restore */ ptrace_setregs(sp, &sp->regs); ptrace_write(sp, sp->regs.eip, backup, 4); }
int32_t inject_socketcall(struct tracedump *td, struct pid *sp, uint32_t sc_code, ...) { /* int 0x80, int3 */ unsigned char code[4] = { 0xcd, 0x80, 0xcc, 0 }; char backup[4]; struct user_regs_struct regs, regs2; int ss_vals, ss_mem, ss; va_list vl; enum arg_type type; uint32_t sv; void *ptr; uint8_t *stack, *stack_mem; uint32_t *stack32; int i, j; /* * get the required amount of stack space */ ss_vals = 0; ss_mem = 0; va_start(vl, sc_code); do { type = va_arg(vl, enum arg_type); if (type == AT_LAST) break; sv = va_arg(vl, uint32_t); /* each socketcall argument takes 4 bytes */ ss_vals += 4; /* if its memory, it takes additional sv bytes */ if (type == AT_MEM_IN || type == AT_MEM_INOUT) { ss_mem += sv; ptr = va_arg(vl, void *); } } while (true); va_end(vl); ss = ss_vals + ss_mem; /* * backup */ ptrace_getregs(sp, ®s); memcpy(®s2, ®s, sizeof regs); ptrace_read(sp, regs.eip, backup, sizeof backup); /* * write the stack */ stack = mmatic_zalloc(td->mm, ss); stack32 = (uint32_t *) stack; stack_mem = stack + ss_vals; va_start(vl, sc_code); i = 0; j = 0; do { type = va_arg(vl, enum arg_type); if (type == AT_LAST) break; sv = va_arg(vl, uint32_t); if (type == AT_VALUE) { stack32[i++] = sv; } else { /* i.e. its a memory arg */ stack32[i++] = regs.esp - ss_mem + j; /* copy the memory */ ptr = va_arg(vl, void *); memcpy(stack_mem + j, ptr, sv); j += sv; } } while (true); va_end(vl); ptrace_write(sp, regs.esp - ss, stack, ss); /* * write the code and run */ regs2.eax = 102; // socketcall regs2.ebx = sc_code; regs2.ecx = regs.esp - ss; ptrace_write(sp, regs.eip, code, sizeof code); ptrace_setregs(sp, ®s2); ptrace_cont(sp, 0, true); /* * read back */ ptrace_getregs(sp, ®s2); ptrace_read(sp, regs.esp - ss_mem, stack_mem, ss_mem); va_start(vl, sc_code); do { type = va_arg(vl, enum arg_type); if (type == AT_LAST) break; sv = va_arg(vl, uint32_t); if (type == AT_VALUE) continue; ptr = va_arg(vl, void *); if (type == AT_MEM_IN) continue; memcpy(ptr, stack_mem, sv); stack_mem += sv; } while (true); va_end(vl); /* restore */ ptrace_write(sp, regs.eip, backup, sizeof backup); ptrace_setregs(sp, ®s); mmatic_free(stack); return regs2.eax; }
int32_t inject_socketcall(struct tracedump *td, struct pid *sp, uint32_t sc_code, ...) { struct user_regs_struct regs, regs2; int ss_vals, ss_mem, ss; va_list vl; enum arg_type type; uint32_t sv; void *ptr; uint8_t *stack, *stack_mem; uint32_t *stack32; int i, j; /* * get the required amount of stack space */ ss_vals = 0; // stack space for immediate values ss_mem = 0; // stack space for pointer values va_start(vl, sc_code); do { type = va_arg(vl, enum arg_type); if (type == AT_LAST) break; sv = va_arg(vl, uint32_t); /* each socketcall argument takes 4 bytes */ ss_vals += 4; /* if its memory, it takes additional sv bytes */ if (type == AT_MEM_IN || type == AT_MEM_INOUT) { ss_mem += sv; ptr = va_arg(vl, void *); } } while (true); va_end(vl); ss = ss_vals + ss_mem; /* * backup */ ptrace_getregs(sp, ®s); memcpy(®s2, ®s, sizeof regs); /* * write the stack */ stack = mmatic_zalloc(td->mm, ss); // stack area for immediate values stack32 = (uint32_t *) stack; stack_mem = stack + ss_vals; // stack area for pointer values va_start(vl, sc_code); i = 0; j = 0; do { type = va_arg(vl, enum arg_type); if (type == AT_LAST) break; sv = va_arg(vl, uint32_t); if (type == AT_VALUE) { stack32[i++] = sv; } else { /* i.e. its a memory arg */ stack32[i++] = regs.esp - ss_mem + j; /* copy the memory */ ptr = va_arg(vl, void *); memcpy(stack_mem + j, ptr, sv); j += sv; } } while (true); va_end(vl); ptrace_write(sp, regs.esp - ss, stack, ss); /* * write the code and run */ _prepare(sp); regs2.eax = 102; // socketcall regs2.ebx = sc_code; regs2.ecx = regs.esp - ss; regs2.eip = sp->vdso_addr; // gateway to int3 ptrace_setregs(sp, ®s2); ptrace_cont_syscall(sp, 0, true); // enter... ptrace_cont_syscall(sp, 0, true); // ...and exit /* * read back */ ptrace_getregs(sp, ®s2); ptrace_read(sp, regs.esp - ss_mem, stack_mem, ss_mem); va_start(vl, sc_code); do { type = va_arg(vl, enum arg_type); if (type == AT_LAST) break; sv = va_arg(vl, uint32_t); if (type == AT_VALUE) continue; ptr = va_arg(vl, void *); if (type == AT_MEM_IN) continue; memcpy(ptr, stack_mem, sv); stack_mem += sv; } while (true); va_end(vl); /* restore */ ptrace_setregs(sp, ®s); mmatic_free(stack); return regs2.eax; }
int ptrace_call(int pid, long proc, int argc, ptrace_arg *argv) { int i = 0; #define ARGS_MAX 64 regs_t regs; ptrace_readreg(pid, ®s); ptrace_dump_regs(®s, "before ptrace_call\n"); /*prepare stacks*/ for (i = 0; i < argc; i++) { ptrace_arg *arg = &argv[i]; if (arg->type == PAT_STR) { arg->_stackid = ptrace_push(pid, ®s, arg->s, strlen(arg->s) + 1); } else if (arg->type == PAT_MEM) { //LOGD("push data %p to stack[%d] :%d \n", arg->mem.addr, stackcnt, *((int*)arg->mem.addr)); arg->_stackid = ptrace_push(pid, ®s, arg->mem.addr, arg->mem.size); } } for (i = 0; (i < 4) && (i < argc); i++) { ptrace_arg *arg = &argv[i]; if (arg->type == PAT_INT) { regs.uregs[i] = arg->i; } else if (arg->type == PAT_STR) { regs.uregs[i] = arg->_stackid; } else if (arg->type == PAT_MEM) { regs.uregs[i] = arg->_stackid; } else { LOGD("unkonwn arg type\n"); } } for (i = argc - 1; i >= 4; i--) { ptrace_arg *arg = &argv[i]; if (arg->type == PAT_INT) { ptrace_push(pid, ®s, &arg->i, sizeof(int)); } else if (arg->type == PAT_STR) { ptrace_push(pid, ®s, &arg->_stackid, sizeof(unsigned long)); } else if (arg->type == PAT_MEM) { ptrace_push(pid, ®s, &arg->_stackid, sizeof(unsigned long)); } else { LOGD("unkonwn arg type\n"); } } #ifdef THUMB regs.ARM_lr = 1; #else regs.ARM_lr= 0; #endif regs.ARM_pc= proc; ptrace_writereg(pid, ®s); ptrace_cont(pid); ptrace_wait_for_signal(pid, SIGSEGV); ptrace_readreg(pid, ®s); ptrace_dump_regs(®s, "before return ptrace_call\n"); //sync memory for (i = 0; i < argc; i++) { ptrace_arg *arg = &argv[i]; if (arg->type == PAT_STR) { } else if (arg->type == PAT_MEM) { ptrace_read(pid, arg->_stackid, arg->mem.addr, arg->mem.size); } } return regs.ARM_r0; }