unsigned int disas_get_target(unsigned int start_pc, struct PEMU_INST *inst) { PEMU_read_mem(start_pc, 15, inst->PEMU_inst_buf); xed_decoded_inst_zero_set_mode(&inst->PEMU_xedd_g, &inst->PEMU_dstate); xed_error_enum_t xed_error = xed_decode(&inst->PEMU_xedd_g, XED_STATIC_CAST(const xed_uint8_t *, inst->PEMU_inst_buf), 15); if (xed_error != XED_ERROR_NONE) { fprintf(stderr, "error in disas_get_target\n"); exit(0); } const xed_inst_t *xi = xed_decoded_inst_inst(&inst->PEMU_xedd_g); if(xed_decoded_inst_get_iclass(&inst->PEMU_xedd_g) != XED_ICLASS_CALL_NEAR) { return 0; } const xed_operand_t *op = xed_inst_operand(xi, 0); xed_reg_enum_t reg_id; xed_operand_enum_t op_name = xed_operand_name(op); unsigned int dest, tmp; if(operand_is_relbr(op_name, &dest)){ dest += (start_pc + xed_decoded_inst_get_length(&inst->PEMU_xedd_g)); }else if(operand_is_reg(op_name, ®_id)){ dest = PEMU_get_reg(reg_id); }else if(operand_is_mem4(op_name, &dest,0)){ PEMU_read_mem(dest, 4, &tmp); dest = tmp; } return dest; }
static void format_jmp(const xed_inst_t *xi) { uint32_t dest; const xed_operand_t *op = xed_inst_operand(xi, 0); xed_operand_enum_t op_name = xed_operand_name(op); xed_reg_enum_t reg_id; #ifdef STATISTICS g_symbol_nums++; fprintf(stderr, "jmp at pc\t%x\n", g_pc); g_jmp_num++; #endif INST* inst = get_inst(g_pc); if(inst->type == TAIL){//jmp to plt #ifdef DEBUG fprintf(stdout, "TAIL:\t%p\n", inst); #endif sprintf(inst_buffer, "%s %s", "jmp", inst->api_call.fname); return; } if(operand_is_relbr(op_name, &dest)){ dest += g_pc + xed_decoded_inst_get_length(&xedd_g); sprintf(inst_buffer, "%s L_0x%x", "jmp", dest); }else{ fprintf(stderr, "error in format_jmp\n"); } }
static void format_direct_call(const xed_inst_t *xi) { uint32_t dest; const xed_operand_t *op = xed_inst_operand(xi, 0); xed_operand_enum_t op_name = xed_operand_name(op); xed_reg_enum_t reg_id; #ifdef STATISTICS fprintf(stderr, "call at pc\t%x\n", g_pc); g_symbol_nums++; g_call_num++; #endif INST* inst = get_inst(g_pc); if(operand_is_relbr(op_name, &dest)){ if(inst->api_call.fname){ if(inst->api_call.type == API_IMP) sprintf(inst_buffer, "call %s", inst->api_call.fname); else sprintf(inst_buffer, "call dword ptr %s", inst->api_call.fname); return; } dest += g_pc + xed_decoded_inst_get_length(&xedd_g); sprintf(inst_buffer, "call func_0x%x", dest); }else{ fprintf(stderr, "error in format_jmp\n"); } }
static int format_jcc(const xed_inst_t *xi) { uint32_t dest, next; char opcode[20], jmp_dst[20]; const xed_operand_t *op = xed_inst_operand(xi, 0); xed_operand_enum_t op_name = xed_operand_name(op); xed_reg_enum_t reg_id; strcpy(opcode, xed_iclass_enum_t2str(xed_decoded_inst_get_iclass(&xedd_g))); INST* inst = get_inst(g_pc); if(operand_is_relbr(op_name, &dest)){ next = g_pc + xed_decoded_inst_get_length(&xedd_g); dest += next;//TODO: handle two branch #ifdef DEBUG fprintf(stdout, "format:%x\t%s\n", g_pc, g_inst_str); #endif #ifdef STATISTICS g_symbol_nums++; g_jcc_num++; #endif if(get_inst(dest)) sprintf(inst_buffer, "%s L_0x%x", opcode, dest); else{ sprintf(inst_buffer, "%s L_ERROR_0x%x", opcode, g_current_func->begin()->first); #ifdef STATISTICS g_check_nums += 1; fprintf(stderr, "check at pc\t%x\n", g_pc); #endif } if(get_inst(next)) memset(safety_guard, 0, sizeof(safety_guard)); else{ sprintf(safety_guard, "jmp L_ERROR_0x%x", g_current_func->begin()->first); #ifdef STATISTICS fprintf(stderr, "check at pc\t%x\n", g_pc); g_check_nums += 1; #endif } }else{ fprintf(stderr, "error in format_jcc\n"); } }
int PEMU_disas_handle_branch(target_ulong pc) { xed_error_enum_t xed_error = disas_one_inst(pc); if(xed_error != XED_ERROR_NONE){ return 0; } xed_iclass_enum_t opcode = xed_decoded_inst_get_iclass(&xedd_g); switch(opcode){ case XED_ICLASS_JMP: case XED_ICLASS_CALL_NEAR: { const xed_inst_t * ins = xed_decoded_inst_inst(&xedd_g); const xed_operand_t *op = xed_inst_operand(ins, 0); xed_operand_enum_t op_name = xed_operand_name(op); int len = xed_decoded_inst_get_length(&xedd_g); unsigned int rel; if(operand_is_relbr(op_name, &rel)) { unsigned long target = pc + len + rel; PEMU_add_trace(target); return 0; } return 1; } break; case XED_ICLASS_RET_NEAR: return 1; default: break; } return 0; }
static void Instrument_CALL(const xed_inst_t* xi) { #ifdef DEBUG fprintf(stdout, "data:instrument_call\n"); #endif xed_reg_enum_t reg_id; uint32_t buf; unsigned int value = 0, dest = 0; const xed_operand_t *op = xed_inst_operand(xi, 0); xed_operand_enum_t op_name = xed_operand_name(op); char *fname = 0; unsigned int taint = 0; API_TYPE type; //TODO: value may be plt call if(operand_is_mem4(op_name, &dest, 0)){ int mem_idx = op_name == XED_OPERAND_MEM1 ? 1 : 0; xed_reg_enum_t base_regid = xed_decoded_inst_get_base_reg(&xedd_g, mem_idx); PEMU_read_mem(dest, 4, &buf); dest = buf; if(taint = d_get_reg_taint(base_regid)){ if(type = is_api_call(dest, &fname)){ // update_mem_val_type(taint, 2, type, fname); goto API_CALL; }else{ update_mem_val_type(taint, 2, API_NONE, 0); } }else if(taint = d_get_mem_taint(dest)){ if(type = is_api_call(dest, &fname)){ // update_mem_val_type(taint, 2, type, fname); goto API_CALL; }else{ update_mem_val_type(taint, 2, API_NONE, 0); } } /* else if(taint = t_get_reg_taint(base_regid)) { uint32_t mem_addr=dest; PEMU_read_mem(dest, 4, buf); dest = *(unsigned int*)buf; insert_mem_val(mem_addr, dest); if(type = is_api_call(dest, &fname)){ update_mem_val_type(mem_addr, 2, type, fname); }else{ update_mem_val_type(mem_addr, 2, API_NONE, 0); } }else if(base_regid==XED_REG_INVALID) { uint32_t mem_addr=dest; PEMU_read_mem(dest, 4, buf); dest = *(unsigned int*)buf; insert_mem_val(mem_addr, dest); if(type = is_api_call(dest, &fname)){ update_mem_val_type(mem_addr, 2, type, fname); }else{ update_mem_val_type(mem_addr, 2, API_NONE, 0); } }*/ return; }else if(operand_is_reg(op_name, ®_id)){ if(taint = d_get_reg_taint(reg_id)){ dest = PEMU_get_reg(reg_id); if(type = is_api_call(dest, &fname)){ // update_mem_val_type(taint, 2, type, fname); goto API_CALL; }else{ update_mem_val_type(taint, 2, API_NONE, 0); } } return; }else if(operand_is_relbr(op_name, &dest)){ dest += (g_pc + xed_decoded_inst_get_length(&xedd_g)); if(type = is_api_call(dest, &fname)){ #ifdef DEBUG fprintf(stdout, "is_api_call\t%x\t%x\n", dest, type); #endif goto REST; } return; } API_CALL: update_mem_val_type(taint, 2, type, fname); //api_copy(&inst->api_call, get_api_call(dest)); REST: handle_api_issues(get_api_call(dest), 1); }
static void Instrument_CALL(const xed_inst_t* xi) { #ifdef DEBUG fprintf(stdout, "txt:instrument_call\n"); #endif xed_reg_enum_t reg_id; unsigned int dest = 0, taint = 0; uint32_t buf; char *fname; const xed_operand_t *op = xed_inst_operand(xi, 0); xed_operand_enum_t op_name = xed_operand_name(op); API_TYPE type; INST *inst; if(operand_is_mem4(op_name, &dest, 0)){ int mem_idx = op_name == XED_OPERAND_MEM1 ? 1 : 0; xed_reg_enum_t base_regid = xed_decoded_inst_get_base_reg(&xedd_g, mem_idx); PEMU_read_mem(dest, 4, &buf); dest = buf; if(taint = t_get_reg_taint(base_regid)){ #ifdef DEBUG fprintf(stdout, "txt: indirect call1\n"); #endif if(type = is_api_call(dest, &fname)){ goto API_CALL; }else{ insert_pc_addr(taint, 2); } }else if(taint = t_get_mem_taint(dest)){ #ifdef DEBUG fprintf(stdout, "txt: indirect call2\n"); #endif if(type = is_api_call(dest, &fname)){ goto API_CALL; }else{ insert_pc_addr(taint, 2); } } return; }else if(operand_is_reg(op_name, ®_id)){ #ifdef DEBUG fprintf(stdout, "txt: indirect call3\n"); #endif if(taint = t_get_reg_taint(reg_id)){ insert_pc_addr(taint, 2); dest = PEMU_get_reg(reg_id); if(type = is_api_call(dest, &fname)){ goto API_CALL; }else{ insert_pc_addr(taint, 2); } } return; }else if(operand_is_relbr(op_name, &dest)){ dest += (g_pc + xed_decoded_inst_get_length(&xedd_g)); if(type = is_api_call(dest, &fname)){ #ifdef DEBUG fprintf(stdout, "is_api_call\t%x\t%x\n", dest, type); #endif goto REST; } return; } API_CALL: inst = get_inst(taint); // api_copy(&inst->api_call, get_api_call(dest)); REST: #ifdef DEBUG fprintf(stdout, "taint:\t%x\t%x\n", taint, dest); #endif t_set_reg_taint(XED_REG_EAX, 0); handle_api_issues(get_api_call(dest), 0); }