void dump_scopetable_entry (struct MemoryCache *mc, struct process *p, int i, address a) { bool b; struct my_SCOPETABLE_ENTRY e; b=MC_ReadBuffer (mc, a, sizeof(struct my_SCOPETABLE_ENTRY), (BYTE*)&e); if (b==false) { L ("%s() cannot read scopetable entry\n", __FUNCTION__); return; }; strbuf sb2=STRBUF_INIT; process_get_sym (p, e.handler, true /* add_module_name */, true /* add_offset */, &sb2); if (e.filter) { strbuf sb1=STRBUF_INIT; process_get_sym (p, e.filter, true /* add_module_name */, true /* add_offset */, &sb1); L ("scopetable entry[%d]. previous try level=%d, filter=0x" PRI_ADR_HEX " (%s) handler=0x" PRI_ADR_HEX " (%s)\n", i, e.previousTryLevel, e.filter, sb1.buf, e.handler, sb2.buf); strbuf_deinit(&sb1); } else L ("scopetable entry[%d]. previous try level=%d, finally=0x" PRI_ADR_HEX " (%s)\n", i, e.previousTryLevel, e.handler, sb2.buf); strbuf_deinit(&sb2); };
static void dump_stack_not_using_EBP (process *p, thread *t, CONTEXT *ctx, MemoryCache *mc) { HANDLE THDL=t->THDL; address stack_top=TIB_get_stack_top (THDL, mc); address stack_bottom=TIB_get_stack_bottom (THDL, mc); //strbuf sb=STRBUF_INIT; address SP_at_start=CONTEXT_get_SP(ctx); L ("Call stack:\n"); if (thread_c_debug) L ("SP_at_start=0x%x, stack_top=0x%x, stack_bottom=0x%x\n", SP_at_start, stack_top, stack_bottom); for (address a=SP_at_start; a<stack_top; a=a+sizeof(REG)) { REG r; if (MC_ReadREG(mc, a, &r)) { //L ("r=0x" PRI_REG_HEX "\n", r); if (adr_in_executable_section(p, r)) { strbuf sb=STRBUF_INIT; process_get_sym (p, r, true, true, &sb); L ("(SP+0x%x) return address=0x" PRI_ADR_HEX " (%s)\n", a-SP_at_start, r, sb.buf); strbuf_deinit(&sb); }; }; }; };
static void dump_stack_EBP_frame (process *p, thread *t, CONTEXT * ctx, MemoryCache *mem) { HANDLE THDL=t->THDL; address stack_top=TIB_get_stack_top (THDL, mem); address stack_bottom=TIB_get_stack_bottom (THDL, mem); strbuf sb=STRBUF_INIT; L ("Call stack:\n"); address next_BP=CONTEXT_get_BP (ctx); if (TIB_is_ptr_in_stack_limits (THDL, next_BP, mem)==false) { L ("Current frame pointer %s (0x" PRI_ADR_HEX ") is not within current stack limits (top=0x" PRI_ADR_HEX ", bottom=0x" PRI_ADR_HEX ")\n", BP_REGISTER_NAME, CONTEXT_get_BP (ctx), stack_top, stack_bottom); goto exit; }; while (next_BP<=stack_top && next_BP>=stack_bottom) { REG tmp; bool b=MC_ReadREG(mem, next_BP, &tmp); oassert (b); address ret_adr; b=MC_ReadREG(mem, next_BP+sizeof(REG), &ret_adr); oassert (b); if (ret_adr==0) break; strbuf_reinit(&sb, 0); process_get_sym (p, ret_adr, true, true, &sb); L ("return address=0x" PRI_ADR_HEX " (%s)\n", ret_adr, sb.buf); if (next_BP==tmp) break; next_BP=tmp; }; exit: strbuf_deinit (&sb); };
// returns address of next SEH frame address dump_SEH_frame (fds* s, struct process* p, struct thread* t, struct MemoryCache *mc, address a) { struct my_EXCEPTION_REGISTRATION current_SEH_frame; bool b; b=MC_ReadBuffer (mc, a, sizeof(struct my_EXCEPTION_REGISTRATION), (BYTE*)¤t_SEH_frame); if (b==false) { L ("%s() cannot read current SEH frame\n", __FUNCTION__); return REG_MAX; }; strbuf sb=STRBUF_INIT; process_get_sym (p, current_SEH_frame.handler, true /* add_module_name */, true /* add_offset */, &sb); L ("* SEH frame at 0x" PRI_ADR_HEX " prev=0x" PRI_ADR_HEX " handler=0x" PRI_ADR_HEX " (%s)\n", a, current_SEH_frame.prev, current_SEH_frame.handler, sb.buf); bool SEH3=false, SEH4=false; if (string_is_ends_with (sb.buf, "except_handler3")) SEH3=true; REG security_cookie; bool security_cookie_known=false; if (string_is_ends_with (sb.buf, "except_handler4")) { SEH4=true; struct module *m=find_module_for_address(p, current_SEH_frame.handler); if (m->security_cookie_adr_known) { b=MC_ReadREG (mc, m->security_cookie_adr, &security_cookie); if (b==false) L ("%s() can't read security_cookie at 0x" PRI_ADR_HEX " for %s\n", __FUNCTION__, m->security_cookie_adr, get_module_name (m)); else security_cookie_known=true; } else { L ("SEH4 frame is here, but address of security_cookie is not known\n"); L ("Try to place .PDB or .MAP file here with this symbol in it\n"); }; }; if (SEH3==false && SEH4==false) goto exit; struct my_VC_EXCEPTION_REGISTRATION_RECORD current_SEH3_frame; b=MC_ReadBuffer (mc, a, sizeof(struct my_VC_EXCEPTION_REGISTRATION_RECORD), (BYTE*)¤t_SEH3_frame); if (b==false) { L ("%s() cannot read current SEH3/4 frame\n", __FUNCTION__); return REG_MAX; }; int previous_trylevel=current_SEH3_frame.previous_trylevel; L ("SEH%d frame. previous trylevel=%d\n", SEH3 ? 3 : 4, previous_trylevel); address scopetable_address=current_SEH3_frame.scopetable; if (SEH4 && security_cookie_known) { scopetable_address^=security_cookie; struct my_EH4_SCOPETABLE_HEADER EH4_header; b=MC_ReadBuffer (mc, scopetable_address, sizeof(struct my_EH4_SCOPETABLE_HEADER), (BYTE*)&EH4_header); if (b==false) { L ("%s() cannot read current SEH4 frame header. scopetable_address=0x" PRI_ADR_HEX "\n", __FUNCTION__, scopetable_address); return REG_MAX; }; L ("SEH4 header:\tGSCookieOffset=0x%x GSCookieXOROffset=0x%x\n", EH4_header.GSCookieOffset, EH4_header.GSCookieXOROffset); L ("\t\tEHCookieOffset=0x%x EHCookieXOROffset=0x%x\n", EH4_header.EHCookieOffset, EH4_header.EHCookieXOROffset); unsigned adr_of_EBP=a + ((byte*)¤t_SEH3_frame.EBP - (byte*)¤t_SEH3_frame.prev); if (EH4_header.EHCookieOffset!=-2) check_SEH4_cookie (mc, adr_of_EBP, EH4_header.EHCookieOffset, EH4_header.EHCookieXOROffset, security_cookie, "EH"); if (EH4_header.GSCookieOffset!=-2) check_SEH4_cookie (mc, adr_of_EBP, EH4_header.GSCookieOffset, EH4_header.GSCookieXOROffset, security_cookie, "GS"); scopetable_address+=sizeof(struct my_EH4_SCOPETABLE_HEADER); }; if (previous_trylevel>=0 && (SEH3 || (SEH4 && security_cookie_known))) dump_scopetable(mc, p, scopetable_address, previous_trylevel+1); exit: strbuf_deinit (&sb); return current_SEH_frame.prev; };
void handle_BPM(process *p, thread *t, int bp_no, CONTEXT *ctx, MemoryCache *mc) { BP *bp=breakpoints[bp_no]; BPM *bpm=bp->u.bpm; address a=bp->a->abs_address; bool b; REG val; const char* v_type; switch (bpm->width) { case 1: { v_type="BYTE"; byte tmp; b=MC_ReadByte (mc, a, &tmp); oassert(b); val=tmp; }; break; case 2: { v_type="WORD"; wyde tmp; b=MC_ReadWyde (mc, a, &tmp); oassert(b); val=tmp; }; break; case 4: { v_type="DWORD"; DWORD tmp; b=MC_ReadTetrabyte (mc, a, &tmp); oassert(b); val=tmp; }; break; case 8: { #ifdef _WIN64 v_type="QWORD"; DWORD64 tmp; b=MC_ReadOctabyte (mc, a, &tmp); oassert(b); val=tmp; #else oassert (0); #endif }; break; default: oassert(0); fatal_error(); }; strbuf sb_sym=STRBUF_INIT, sb_bp_adr=STRBUF_INIT; address PC=CONTEXT_get_PC(ctx); process_get_sym (p, PC, true, true, &sb_sym); address_to_string(bp->a, &sb_bp_adr); dump_PID_if_need(p); dump_TID_if_need(p, t); L ("(%d) some code at %s (0x" PRI_ADR_HEX ") %s %s variable at %s (it contain 0x" PRI_REG_HEX " after execution of that instruction)\n", bp_no, sb_sym.buf, PC, bpm->t==BPM_type_RW ? "reading or writting" : "writting", v_type, sb_bp_adr.buf, val); //MC_WriteOctabyte(mc, bp->a->abs_address, 0); // can be option? strbuf_deinit(&sb_bp_adr); strbuf_deinit(&sb_sym); };