u64 sub_by_debugstr(inject_ctx *ctx, char *str) { u64 lea_addr = 0, rdiff=0, rtop=0; callcache_entry *callcache, *entry; u32 callcache_total; int i; callcache = get_callcache(); callcache_total = get_callcachetotal(); lea_addr = lea_by_debugstr(ctx, LEA_RDI, str); if (lea_addr == 0) error("could not find 'lea' insn for str '%s'", str); rdiff=0x313337; rtop=0; for(i=0; i<callcache_total; i++) { entry = &callcache[i]; if (entry->dest < lea_addr) { if (lea_addr - entry->dest < rdiff) { rdiff = lea_addr - entry->dest; rtop = entry->dest; } } } return rtop; }
u64 inject_resolve_rexec(inject_ctx *ctx) { u64 rexec_flag = resolve_symbol_tab(ctx, "rexec_flag"); if (rexec_flag == 0) { u64 rexec_debug_lea = 0, rexec_test = 0; u32 rexec_flag_offset = 0; if (ctx->debug) info("could not resolve rexec_flag :(, trying alternative method.."); rexec_debug_lea = lea_by_debugstr( ctx, LEA_RDI, "Server will not fork when running in debugging mode." ); // find first call to getpid() from here u64 p_getpid = plt_by_name(ctx, "getpid"); if (ctx->debug) info("getpid@plt = 0x%lx", p_getpid); u64 adr = find_nearest_call(rexec_debug_lea, p_getpid); // next opcode is "cmp cs:???, 0 ? unsigned char opbytes[2]; _peek(ctx->pid, adr+5, opbytes, 2); if (memcmp(opbytes, "\x83\x3d", 2) == 0) { if (ctx->debug) info("found cmp:cs opcode.."); _peek(ctx->pid, adr+5+2, &rexec_flag_offset, 4); rexec_flag = adr+5+7+rexec_flag_offset; } else { // finally.. old method if (ctx->debug) info("trying final method.."); // Find the first 'test eax, eax' instruction after the debug string rexec_test = find_next_opcode(ctx, rexec_debug_lea, (u8*)"\x85\xc0", 2); // Get the rexec_flag offset from rip _peek(ctx->pid, rexec_test - 4, &rexec_flag_offset, 4); // Resolve absolute address of rip + rexec_flag_offset rexec_flag = rexec_test + rexec_flag_offset; } } return rexec_flag; }