/** * Write a breakpoint 0xCC in memory * One of the 2 breakpoint technique of e2dbg */ int e2dbg_break_amd64(elfshobj_t *f, elfshbp_t *bp) { int prot; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); #if __DEBUG_BREAKPOINTS__ fprintf(stderr, "[DEBUG_BREAKPOINTS:amd64] bp->addr %08X \n", bp->addr); #endif bp->savedinstr[0] = *(eresi_Addr *) bp->addr; prot = elfsh_munprotect(f, bp->addr, 4); if (prot == (-1)) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Munprotect failed", (-1)); #if __DEBUG_BREAKPOINTS__ fprintf(stderr, "[DEBUG_BREAKPOINTS:amd64] after munprotect\n"); #endif *(u_char *) bp->addr = 0xCC; #if __DEBUG_BREAKPOINTS__ fprintf(stderr, "[DEBUG_BREAKPOINTS:amd64] after write\n"); #endif elfsh_mprotect(f, bp->addr, 4, prot); #if __DEBUG_BREAKPOINTS__ fprintf(stderr, "[DEBUG_BREAKPOINTS:amd64] after mprotect\n"); #endif PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (0)); }
/** * Perform a raw write on the object cache data * @param file * @param foffset * @param src_buff * @param len * @return */ int elfsh_raw_write(elfshobj_t *file, u_int foffset, void *src_buff, int len) { elfshsect_t *sect; int sect_off; void *dst; int prot; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); sect = elfsh_get_parent_section_by_foffset(file, foffset, NULL); if (sect == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid virtual address", -1); sect_off = foffset - sect->shdr->sh_offset; if (sect_off + len > sect->shdr->sh_size) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Section too short", -1); dst = elfsh_get_anonymous_section(file, sect); if (dst == NULL) PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); if (elfsh_is_runtime_mode()) { prot = elfsh_munprotect(file, (eresi_Addr) dst + sect_off, len); memcpy(dst + sect_off, src_buff, len); elfsh_mprotect(file, (eresi_Addr) dst + sect_off, len, prot); } else memcpy(dst + sect_off, src_buff, len); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (len)); }
int e2dbg_break_sparc32(elfshobj_t *f, elfshbp_t *bp) { int prot; unsigned long addr; unsigned long long addr64; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); #if __DEBUG_BREAKPOINTS__ fprintf(stderr, "[DEBUG_BREAKPOINTS:sparc32] bp->addr %016x \n", bp->addr); #endif memcpy(bp->savedinstr, (u_char *) bp->addr, 8); prot = elfsh_munprotect(f, bp->addr, 8); if (prot == (-1)) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Munprotect failed", (-1)); #if __DEBUG_BREAKPOINTS__ fprintf(stderr, "[DEBUG_BREAKPOINTS:sparc32] after munprotect\n"); #endif //*(u_long *) bp->addr = 0x91d02001; /* opcode for ta 1 */ *((u_long *) bp->addr) = 0x01000000; /* put nop here */ *((u_long *) bp->addr + 1) = 0x01000000; /* put nop here */ addr = (bp->addr & (~7)); #if __DEBUG_BREAKPOINTS__ fprintf(stderr, "[DEBUG_BREAKPOINTS:sparc32] Address to be flushed: %016lx \n", addr); #endif /* FIXME: Testing .... nothing is working until now */ __asm__ __volatile__("iflush %0 + %1 \n\t" :: "r" ((unsigned long) addr), "r" (0)); __asm__ __volatile__("iflush %0 + %1 \n\t" :: "r" ((unsigned long) addr), "r" (8)); __asm__ __volatile__("iflush %0 + %1 \n\t" :: "r" ((unsigned long) addr), "r" (16)); __asm__ __volatile__("flush %0 + %1 \n\t" :: "r" ((unsigned long) addr), "r" (0)); __asm__ __volatile__("flush %0 + %1 \n\t" :: "r" ((unsigned long) addr), "r" (8)); __asm__ __volatile__("flush %0 + %1 \n\t" :: "r" ((unsigned long) addr), "r" (16)); addr64 = 0xffffffff00000000 + addr; #if __DEBUG_BREAKPOINTS__ fprintf(stderr, "[DEBUG_BREAKPOINTS:sparc32] Address64 to be flushed: %016llx \n", addr64); #endif __asm__ __volatile__("iflush %0 + %1 \n\t" :: "r" ((unsigned long) addr64), "r" (0)); __asm__ __volatile__("iflush %0 + %1 \n\t" :: "r" ((unsigned long) addr64), "r" (8)); __asm__ __volatile__("iflush %0 + %1 \n\t" :: "r" ((unsigned long) addr64), "r" (16)); __asm__ __volatile__("flush %0 + %1 \n\t" :: "r" ((unsigned long) addr64), "r" (0)); __asm__ __volatile__("flush %0 + %1 \n\t" :: "r" ((unsigned long) addr64), "r" (8)); __asm__ __volatile__("flush %0 + %1 \n\t" :: "r" ((unsigned long) addr64), "r" (16)); #if __DEBUG_BREAKPOINTS__ fprintf(stderr, "[DEBUG_BREAKPOINTS:sparc32] after sleep & write\n"); #endif elfsh_mprotect(f, bp->addr, 8, prot); sleep(2); #if __DEBUG_BREAKPOINTS__ fprintf(stderr, "[DEBUG_BREAKPOINTS:sparc32] after mprotect\n"); #endif PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (0)); }
/** * The Real routine that handles each thread-specific breakpoint state machine. * * breakpoint case: * * 0-1: restore old instr, enable step, set bp addr in ->past, reset pc to orig bp addr * 1-2: do nothing (just executed instr) * 2-3: reinstall, resetstep, thread_contall, curthread->was_step = 0, * stoppedthread->count = NONE; e2dbgworld.curbp = NULL; stoppedthread = RUNNING * * stepping case: * * 0-1: print current instr; reinstall * stoppedthread->state = BREAKING; thread_contall; * was_step = 0; count = NONE; curbp = NULL; stoppedthread->state = RUNNING */ void e2dbg_breakpoint_process() { char buf[32]; elfshbp_t *bp; int prot; char *name; elfsh_SAddr off; int ret; asm_instr ptr; char *s; eresi_Addr *pc; eresi_Addr savedpc; u_int bpsz; elfshsect_t *sect; elfshobj_t *parent; elfsh_Sym *sym; #if __DEBUG_BP__ fprintf(stderr, " [D] Entering breakpoint handler\n"); #endif /* Set all registers as variables and get PC */ e2dbg_user_hooks_install(); e2dbg_getregs(); pc = e2dbg_getpc(); parent = e2dbg_get_parent_object((eresi_Addr) *pc); bpsz = elfsh_get_breaksize(parent); /* Print variables and registers on breakpoints */ //if (!world.state.revm_quiet) //cmd_vlist(); /* Try to find the breakpoint at current instruction pointer */ #if __DEBUG_BP__ fprintf(stderr, " [D] At PC = %08X : Trying to find breakpoint at addr %08X (bpsize = %u)\n", *pc, *pc - bpsz, bpsz); #endif snprintf(buf, sizeof(buf), XFMT, *pc - bpsz); bp = hash_get(&e2dbgworld.bp, buf); #if __DEBUG_BP__ if (bp) fprintf(stderr, " [D] Saved instruction BYTE = %02X and PC-BPSZ BYTE = %02X \n", bp->savedinstr[0], *((u_char *) *pc - bpsz)); else fprintf(stderr, " [D] No BP found at %08X ! \n", *pc); #endif /* Case of processing breakpoint, or if we are single-stepping */ if (!bp || (bp->savedinstr[0] == *((u_char *) *pc - bpsz))) { /* We are single-stepping, display the instruction at $pc */ if (e2dbgworld.stoppedthread->step) { #if __DEBUG_BP__ fprintf(stderr, " [D] Single-stepping -IS- enabled \n"); #endif ret = asm_read_instr(&ptr, (u_char *) *pc, 16, world.curjob->proc); if (!ret) ret++; sect = elfsh_get_parent_section(parent, (eresi_Addr) *pc, NULL); name = revm_resolve(parent, (eresi_Addr) *pc, &off); off = 0; sym = elfsh_get_metasym_by_value(parent, (eresi_Addr) *pc, &off, ELFSH_LOWSYM); #if __DEBUG_BP__ fprintf(stderr, " [D] Found parent = %08X (%s) in step (name = %s, parentsect = %s) off = %u\n", (eresi_Addr) parent, parent->name, name, sect->name, off); #endif revm_instr_display(-1, *pc, 0, 20, name, off, (char *) *pc); e2dbg_display(e2dbgworld.displaycmd, e2dbgworld.displaynbr); if (!e2dbgworld.stoppedthread->trace) e2dbg_entry(NULL); else e2dbg_watch(); e2dbg_breakpoint_reinstall(); return; } #if __DEBUG_BP__ fprintf(stderr, " [D] Single-stepping is -NOT- enabled \n"); #endif /* Here starts the real stuff ** ** count == E2DBG_BREAK_EXEC -> execute restored instruction ** count == E2DBG_BREAK_FINISHED -> restore breakpoint ** count > E2DBG_BREAK_MAX -> e2dbg is getting debugged by a third party debugger */ e2dbgworld.stoppedthread->count++; #if __DEBUG_BP__ fprintf(stderr, " [C] Count %u -> %u for thread ID %u \n", e2dbgworld.stoppedthread->count - 1, e2dbgworld.stoppedthread->count, ((unsigned int) e2dbgworld.stoppedthread->tid)); #endif /* execute the previously restored instruction */ if (e2dbgworld.stoppedthread->count == E2DBG_BREAK_EXEC) { #if __DEBUG_BP__ printf(" [D] At PC = 0x%X : Debuggee executed restored instruction \n", *pc); #endif return; } /* Suggested by andrewg, useful when debugging valgrind */ if (e2dbgworld.stoppedthread->count > E2DBG_BREAK_MAX) { printf(".::- E2DBG WARNING -::.\n" "Breakpoint triggered at location " AFMT " which we don't know about.\n\n" "This may be an anti-debug trick or the program may be inside another\n" "debugger. Exiting (DEBUG: count = " UFMT ", step is off)\n\n", *pc - bpsz, e2dbgworld.stoppedthread->count); return; } e2dbg_breakpoint_reinstall(); /* remove trace flag */ #if __DEBUG_BP__ fprintf(stderr, " [D] At PC = " AFMT " Resetting STEP mode\n", *pc); #endif e2dbg_resetstep(); return; } /* Case of newly hit breakpoint */ else { name = revm_resolve(parent, (eresi_Addr) *pc - bpsz, &off); s = (e2dbg_is_watchpoint(bp) ? "Watch" : "Break"); #if __DEBUG_BP__ fprintf(stderr, " [C] Count set to 1 (HIT) for thread ID %u \n", (unsigned int) e2dbgworld.stoppedthread->tid); #endif if (off) printf(" [*] %spoint found at " XFMT " <%s + " DFMT "> in thread %u \n\n", s, *pc - bpsz, name, off, (unsigned int) e2dbgworld.stoppedthread->tid); else printf(" [*] %spoint found at " XFMT " <%s> in thread %u \n\n", s, *pc - bpsz, name, (unsigned int) e2dbgworld.stoppedthread->tid); revm_doswitch(parent->id); mjr_set_current_context(&world.mjr_session, parent->name); *pc -= bpsz; prot = elfsh_munprotect(bp->obj, *pc, bpsz); memcpy((u_char *) *pc, bp->savedinstr, bpsz); elfsh_mprotect(bp->obj, *pc, bpsz, prot); e2dbg_setstep(); #if __DEBUG_BP__ fprintf(stderr, " [D] Setting Step mode \n"); #endif e2dbgworld.stoppedthread->past = *pc; e2dbgworld.stoppedthread->count = E2DBG_BREAK_HIT; e2dbgworld.curbp = bp; bp->tid = (uint32_t) e2dbgworld.stoppedthread->tid; #if __DEBUG_BP__ fprintf(stderr, " [D] Reset break \n"); #endif if (bp->cmdnbr) e2dbg_display(bp->cmd, bp->cmdnbr); else e2dbg_display(e2dbgworld.displaycmd, e2dbgworld.displaynbr); #if __DEBUG_BP__ fprintf(stderr, " [D] After BP display \n"); #endif #if __DEBUG_BP__ fprintf(stderr, " [D] PC before entry is addr 0x%X \n", *pc); #endif savedpc = *pc; e2dbg_entry(NULL); *pc = savedpc; #if __DEBUG_BP__ fprintf(stderr, " [D] At PC = 0x%X : returned from BP handler with step enabled\n", *pc); #endif } }