static void Instrument_MOV(const xed_inst_t* xi) { xed_reg_enum_t reg_id_0, reg_id_1; unsigned int mem_addr, imm; const xed_operand_t *op_0 = xed_inst_operand(xi, 0); const xed_operand_t *op_1 = xed_inst_operand(xi, 1); xed_operand_enum_t op_name_0 = xed_operand_name(op_0); xed_operand_enum_t op_name_1 = xed_operand_name(op_1); if(operand_is_mem4(op_name_0, &mem_addr, 0)){ if (operand_is_reg(op_name_1, ®_id_1)){ d_set_mem_taint_bysize(mem_addr, d_get_reg_taint(reg_id_1), xed_decoded_inst_operand_length(&xedd_g, 0)); }else if(operand_is_imm(op_name_1, &imm)){ d_set_mem_taint_bysize(mem_addr, xed_decoded_inst_operand_length(&xedd_g, 0), 0); } }else if(operand_is_reg(op_name_0, ®_id_0)){ if(operand_is_mem4(op_name_1, &mem_addr, 1)){ d_set_reg_taint(reg_id_0, d_get_mem_taint(mem_addr)); }else if(operand_is_reg(op_name_1, ®_id_1)){ d_set_reg_taint(reg_id_0, d_get_reg_taint(reg_id_1)); }else if(operand_is_imm(op_name_1, &imm)){ d_set_reg_taint(reg_id_0, 0); } } }
static void Instrument_LEA(const xed_inst_t* xi) { xed_reg_enum_t reg_id; unsigned int mem_addr, imm; const xed_operand_t *op_0 = xed_inst_operand(xi, 0); const xed_operand_t *op_1 = xed_inst_operand(xi, 1); xed_operand_enum_t op_name_0 = xed_operand_name(op_0); xed_operand_enum_t op_name_1 = xed_operand_name(op_1); if(operand_is_mem4(op_name_1, &mem_addr, 1)){ if (operand_is_reg(op_name_0, ®_id)){ int mem_idx = 0; if (op_name_1 == XED_OPERAND_MEM1) mem_idx = 1; xed_reg_enum_t base_regid = xed_decoded_inst_get_base_reg(&xedd_g, mem_idx); d_set_reg_taint(reg_id, d_get_reg_taint(base_regid)); }else{ fprintf(stderr, "error in Instrument_LEA\n"); exit(0); } }else{ fprintf(stderr, "error in Instrument_LEA\n"); exit(0); } }
static void Instrument_ADD(const xed_inst_t* xi) { xed_reg_enum_t reg_id_0, reg_id_1; unsigned int imm = 0; unsigned int mem_addr, taint_s = 0, taint_d = 0; const xed_operand_t *op_0 = xed_inst_operand(xi, 0); const xed_operand_t *op_1 = xed_inst_operand(xi, 1); xed_operand_enum_t op_name_0 = xed_operand_name(op_0); xed_operand_enum_t op_name_1 = xed_operand_name(op_1); if(operand_is_mem4(op_name_0, &mem_addr, 0)){ if(operand_is_imm(op_name_1, &imm)) return; taint_d = t_get_mem_taint(mem_addr); //yang int a, b; PEMU_read_mem(mem_addr, 4, &a); if (operand_is_reg(op_name_1, ®_id_1)){ taint_s = t_get_reg_taint(reg_id_1); b = PEMU_get_reg(reg_id_1); } if(b<a) // if((int)get_pc_imm(taint_s) < (int)get_pc_imm(taint_d)) taint_s = taint_d; t_set_mem_taint_bysize(mem_addr, taint_s, xed_decoded_inst_operand_length(&xedd_g, 0)); }else if(operand_is_reg(op_name_0, ®_id_0)){ if(operand_is_imm(op_name_1, &imm)) return; //yang int a, b; a = PEMU_get_reg(reg_id_0); taint_d = t_get_reg_taint(reg_id_0); if(operand_is_mem4(op_name_1, &mem_addr, 1)){ taint_s = t_get_mem_taint(mem_addr); PEMU_read_mem(mem_addr, 4, &b); }else if(operand_is_reg(op_name_1, ®_id_1)){ taint_s = t_get_reg_taint(reg_id_1); b = PEMU_get_reg(reg_id_1); } // if((int)get_pc_imm(taint_s) < (int)get_pc_imm(taint_d)) if(b<a) taint_s = taint_d; t_set_reg_taint(reg_id_0, taint_s); } }
static void add_write_operands(xed_dot_graph_supp_t* gg, xed_decoded_inst_t* xedd, xed_dot_node_t* n) { xed_uint_t i, noperands; xed_reg_enum_t r, r_enclosing; const xed_inst_t* xi = 0; xi = xed_decoded_inst_inst(xedd); noperands = xed_inst_noperands(xi); for( i=0; i < noperands ; i++) { const xed_operand_t* op = xed_inst_operand(xi,i); xed_operand_enum_t opname = xed_operand_name(op); if (xed_operand_is_register(opname) || xed_operand_is_memory_addressing_register(opname)) { if (xed_operand_written(op)) { /* set n as the source of the value. */ /* ignoring partial writes */ r = xed_decoded_inst_get_reg(xedd, opname); r_enclosing = xed_get_largest_enclosing_register(r); gg->xed_reg_to_node[r_enclosing] = n; } } } /* for */ }
bool IsRegisterOperand(xed_decoded_inst_t &xedd, int index) { const xed_inst_t* inst = xed_decoded_inst_inst(&xedd); const xed_operand_t* operand = xed_inst_operand(inst, index); //the first operand is the destination. xed_operand_enum_t oper_type = xed_operand_name(operand); switch(oper_type) { case XED_OPERAND_REG0: case XED_OPERAND_REG1: case XED_OPERAND_REG2: case XED_OPERAND_REG3: case XED_OPERAND_REG4: case XED_OPERAND_REG5: case XED_OPERAND_REG6: case XED_OPERAND_REG7: case XED_OPERAND_REG8: case XED_OPERAND_REG9: case XED_OPERAND_REG10: case XED_OPERAND_REG11: case XED_OPERAND_REG12: case XED_OPERAND_REG13: case XED_OPERAND_REG14: case XED_OPERAND_REG15: return true; break; default: break; } return false; }
unwind_interval * process_lea(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iarg) { highwatermark_t *hw_tmp = &(iarg->highwatermark); unwind_interval *next = iarg->current; const xed_operand_t *op0 = xed_inst_operand(xi, 0); xed_operand_enum_t op0_name = xed_operand_name(op0); if ((op0_name == XED_OPERAND_REG0)) { xed_reg_enum_t regname = xed_decoded_inst_get_reg(xptr, op0_name); if (x86_isReg_BP(regname)) { //======================================================================= // action: clobbering the base pointer; begin a new SP_RELATIVE interval // note: we don't check that BP is BP_SAVED; we might have to //======================================================================= next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), RA_SP_RELATIVE, iarg->current->sp_ra_pos, iarg->current->bp_ra_pos, BP_HOSED, iarg->current->sp_bp_pos, iarg->current->bp_bp_pos, iarg->current); if (HW_TEST_STATE(hw_tmp->state, HW_BP_SAVED, HW_BP_OVERWRITTEN) && (hw_tmp->uwi->sp_ra_pos == next->sp_ra_pos)) { hw_tmp->uwi = next; hw_tmp->state = HW_NEW_STATE(hw_tmp->state, HW_BP_OVERWRITTEN); } } } return next; }
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 target_ulong Instrument_CALL_NEAR(target_ulong pc) { uint32_t mem_addr; xed_reg_enum_t reg_id; target_ulong target; PEMU_read_mem(pc, 15, pemu_inst.PEMU_inst_buf); xed_decoded_inst_zero_set_mode(&pemu_inst.PEMU_xedd_g, &pemu_inst.PEMU_dstate); xed_error_enum_t xed_error = xed_decode(&pemu_inst.PEMU_xedd_g, XED_STATIC_CAST(const xed_uint8_t *, pemu_inst.PEMU_inst_buf), 15); const xed_inst_t * ins = xed_decoded_inst_inst(&pemu_inst.PEMU_xedd_g); const xed_operand_t *op = xed_inst_operand(ins, 0); xed_operand_enum_t op_name = xed_operand_name(op); if (operand_is_mem(op_name, &mem_addr, 0)) { PEMU_read_mem(mem_addr,sizeof(target) , &target); } else if (operand_is_reg(op_name, ®_id)){ target = PEMU_get_reg(reg_id); } else{ int len = xed_decoded_inst_get_length(&pemu_inst.PEMU_xedd_g); target = xed_decoded_inst_get_branch_displacement(&pemu_inst.PEMU_xedd_g) + pc + len; } return target; }
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"); } }
int RegisterOperandSize(xed_decoded_inst_t &xedd, int index) { ASSERT(IsRegisterOperand(xedd, index)); const xed_inst_t* inst = xed_decoded_inst_inst(&xedd); const xed_operand_t* operand = xed_inst_operand(inst, index); //the first operand is the destination. xed_operand_enum_t oper_type = xed_operand_name(operand); xed_reg_enum_t reg = xed_decoded_inst_get_reg(&xedd, oper_type); int size = 0; switch(reg) { case XED_REG_AH: case XED_REG_AL: case XED_REG_BH: case XED_REG_BL: case XED_REG_CH: case XED_REG_CL: case XED_REG_DH: case XED_REG_DL: size = 8; break; case XED_REG_AX: case XED_REG_BX: case XED_REG_CX: case XED_REG_DX: size = 16; break; default: size = 32; break; } ASSERT(size != 0); return size; }
static void Instrument_JMP(const xed_inst_t* xi) { xed_reg_enum_t reg_id; char buf[4]; 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); unsigned int taint = 0; #ifdef DEBUG fprintf(stdout, "in data_rewrite:\tInstrument_JMP\n"); #endif 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); if(taint = d_get_reg_taint(base_regid)){ update_mem_val_type(taint, 2, API_NONE, 0); } }else if(operand_is_reg(op_name, ®_id)){ if(taint = d_get_reg_taint(reg_id)){ update_mem_val_type(taint, 2, API_NONE, 0); } } }
// Return the destination register of one instruction xed_reg_enum_t DestRegister(xed_decoded_inst_t &xedd) { const xed_inst_t* inst = xed_decoded_inst_inst(&xedd); unsigned int operandNum = xed_inst_noperands(inst); // get the number of the operands // if the instruction has no operands, return invalid if(operandNum == 0) return XED_REG_INVALID; const xed_operand_t* operand = xed_inst_operand(inst, 0); //the first operand is the destination. xed_operand_enum_t oper_type = xed_operand_name(operand); xed_uint_t mark = xed_operand_is_register(oper_type); // check whether the operand is a register operand if(mark == 1) { xed_reg_enum_t reg = xed_decoded_inst_get_reg(&xedd, oper_type); ASSERT(reg != XED_REG_INVALID); return reg; } return XED_REG_INVALID; }
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"); } }
void check_for_mov_to_cr3(xed_decoded_inst_t* xedd) { if (xed_decoded_inst_get_iclass(xedd) == XED_ICLASS_MOV_CR) { // we know mov_cr has 2 operands so we do not check // xed_inst_noperands. // get the skeleton (static info) const xed_inst_t* xi = xed_decoded_inst_inst(xedd); // get the dest operand (operand 0) const xed_operand_t* op = xed_inst_operand(xi,0); xed_operand_enum_t op_name = xed_operand_name(op); if (op_name == XED_OPERAND_REG0) { xed_reg_enum_t r = xed_decoded_inst_get_reg(xedd, op_name); if (r == XED_REG_CR3) { printf("Found a mov to CR3\n"); } } } }
static void Instrument_LEA(const xed_inst_t* xi) { xed_reg_enum_t reg_id; unsigned int mem_addr, imm; const xed_operand_t *op_0 = xed_inst_operand(xi, 0); const xed_operand_t *op_1 = xed_inst_operand(xi, 1); xed_operand_enum_t op_name_0 = xed_operand_name(op_0); xed_operand_enum_t op_name_1 = xed_operand_name(op_1); if(operand_is_mem4(op_name_1, &mem_addr, 1)){ if (operand_is_reg(op_name_0, ®_id)){ int mem_idx = 0; if (op_name_1 == XED_OPERAND_MEM1) mem_idx = 1; xed_reg_enum_t base_regid = xed_decoded_inst_get_base_reg(&xedd_g, mem_idx); xed_reg_enum_t index_regid = xed_decoded_inst_get_index_reg(&xedd_g, mem_idx); //if(index_regid == XED_REG_INVALID && mem_taint == 0) // t_set_reg_taint(reg_id, t_get_reg_taint(base_regid)); if(index_regid == XED_REG_INVALID) { if(find_min_dist(mem_addr, g_base, g_index, g_disp) != 3) { t_set_reg_taint(reg_id, t_get_reg_taint(base_regid)); } } else { unsigned int a=0, b=0; if(base_regid != XED_REG_INVALID) a = PEMU_get_reg(base_regid); b = PEMU_get_reg(index_regid); if( a < b) t_set_reg_taint(reg_id, t_get_reg_taint(index_regid)); else t_set_reg_taint(reg_id, t_get_reg_taint(base_regid)); } }else{ fprintf(stderr, "error in Instrument_LEA\n"); exit(0); } }else{ fprintf(stderr, "error in Instrument_LEA\n"); exit(0); } }
static void Instrument_XOR(const xed_inst_t* xi) { xed_reg_enum_t reg_id_0, reg_id_1; const xed_operand_t *op_0 = xed_inst_operand(xi, 0); const xed_operand_t *op_1 = xed_inst_operand(xi, 1); xed_operand_enum_t op_name_0 = xed_operand_name(op_0); xed_operand_enum_t op_name_1 = xed_operand_name(op_1); if (operand_is_reg(op_name_0, ®_id_0) && (operand_is_reg(op_name_1, ®_id_1))){ if(reg_id_0 == reg_id_1) d_set_reg_taint(reg_id_0, 0); return; } Instrument_ADD(xi); }
//yang.new static void Instrument_XCHG(const xed_inst_t *xi) { xed_reg_enum_t reg0, reg1; unsigned int mem_addr; unsigned int taint = 0; const xed_operand_t *op_0 = xed_inst_operand(xi, 0); const xed_operand_t *op_1 = xed_inst_operand(xi, 1); xed_operand_enum_t op_name_0 = xed_operand_name(op_0); xed_operand_enum_t op_name_1 = xed_operand_name(op_1); if(operand_is_mem4(op_name_0, &mem_addr, 0)) { if(operand_is_reg(op_name_1, ®1)) { taint = d_get_reg_taint(reg1); d_set_reg_taint(reg1, d_get_mem_taint(mem_addr)); d_set_mem_taint(mem_addr, taint); } }else if (operand_is_reg(op_name_0, ®0)) { if(operand_is_reg(op_name_1, ®1)) { taint = d_get_reg_taint(reg1); d_set_reg_taint(reg1, d_get_reg_taint(reg0)); d_set_reg_taint(reg0, taint); }else if(operand_is_mem4(op_name_1, &mem_addr,1)) { taint = d_get_reg_taint(reg0); d_set_reg_taint(reg0, d_get_mem_taint(mem_addr)); d_set_mem_taint(mem_addr, taint); } } }
void dump_operand(const xed_operand_t* op) { printf("%s ", xed_operand_enum_t2str(xed_operand_name(op))); printf("%s ", xed_operand_visibility_enum_t2str(xed_operand_operand_visibility(op))); printf("%s ", xed_operand_action_enum_t2str(xed_operand_rw(op))); printf("%s ", xed_operand_type_enum_t2str(xed_operand_type(op))); printf("%s ", xed_operand_element_xtype_enum_t2str(xed_operand_xtype(op))); if (xed_operand_type(op) == XED_OPERAND_TYPE_NT_LOOKUP_FN) printf("%s ", xed_nonterminal_enum_t2str(xed_operand_nonterminal_name(op))); if (xed_operand_type(op) == XED_OPERAND_TYPE_REG) printf("%s ", xed_reg_enum_t2str(xed_operand_reg(op))); }
static void add_read_operands(xed_dot_graph_supp_t* gg, xed_decoded_inst_t* xedd, xed_dot_node_t* n) { xed_uint_t i, noperands; xed_reg_enum_t r; const xed_inst_t* xi = 0; xed_bool_t found = 0; xi = xed_decoded_inst_inst(xedd); noperands = xed_inst_noperands(xi); for( i=0; i < noperands ; i++) { int memop = -1; const xed_operand_t* op = xed_inst_operand(xi,i); xed_operand_enum_t opname = xed_operand_name(op); if (xed_operand_is_register(opname) || xed_operand_is_memory_addressing_register(opname)) { if (xed_operand_read(op)) { /* add edge to n */ r = xed_decoded_inst_get_reg(xedd, opname); found |= add_edge(gg, n, r); } continue; } if (opname == XED_OPERAND_MEM0) memop = 0; else if (opname == XED_OPERAND_MEM1 ) memop = 1; if (memop != -1) { /* get reads of base/index regs, if any */ xed_reg_enum_t base, indx; base = xed_decoded_inst_get_base_reg(xedd,memop); indx = xed_decoded_inst_get_index_reg(xedd,memop); if (base != XED_REG_INVALID) found |= add_edge(gg, n, base); indx = xed_decoded_inst_get_index_reg(xedd,memop); if (indx != XED_REG_INVALID) found |= add_edge(gg, n, indx); } } /* for */ if (!found) { /* add an edge from start */ xed_dot_edge(gg->g, gg->start, n); } }
static void Instrument_PUSH(const xed_inst_t* xi) { 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; unsigned int taint = 0, mem_addr; if(operand_is_mem4(op_name, &mem_addr, 0)){ taint = d_get_mem_taint(mem_addr); }else if(operand_is_reg(op_name, ®_id)){ taint = d_get_reg_taint(reg_id); } unsigned int esp = PEMU_get_reg(XED_REG_ESP) - 4; d_set_mem_taint_bysize(esp, taint, 4); }
bool IsImmediateOperand(xed_decoded_inst_t &xedd, int index) { const xed_inst_t* inst = xed_decoded_inst_inst(&xedd); const xed_operand_t* operand = xed_inst_operand(inst, index); //the first operand is the destination. xed_operand_enum_t oper_type = xed_operand_name(operand); switch(oper_type) { case XED_OPERAND_IMM0: return true; default: break; } return false; }
static void Instrument_POP(const xed_inst_t* xi) { uint32_t mem_addr; xed_reg_enum_t reg_id; const xed_operand_t *op = xed_inst_operand(xi, 0); xed_operand_enum_t op_name = xed_operand_name(op); uint32_t esp = PEMU_get_reg(XED_REG_ESP); uint32_t taint = d_get_mem_taint(esp); if(operand_is_mem4(op_name, &mem_addr, 0)){ d_set_mem_taint_bysize(mem_addr, taint, 4); }else if(operand_is_reg(op_name, ®_id)){ d_set_reg_taint(reg_id, taint); } d_set_mem_taint_bysize(esp, 0, 4); }
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"); } }
void print_operands(xed_decoded_inst_t* xedd) { unsigned int i = 0; xed_inst_t const* const xi = xed_decoded_inst_inst(xedd); const unsigned int noperands = xed_inst_noperands(xi); for( i=0; i < noperands ; i++) { xed_operand_t const* op = xed_inst_operand(xi,i); xed_operand_enum_t op_name = xed_operand_name(op); if (xed_operand_is_register(op_name)) { xed_reg_enum_t reg = xed_decoded_inst_get_reg(xedd,op_name); xed_operand_action_enum_t rw = xed_operand_rw(op); printf("%2d: %5s %5s\n", i, xed_reg_enum_t2str(reg), xed_operand_action_enum_t2str(rw)); } } }
static target_ulong Instrument_CALL_NEAR( const xed_inst_t * ins, target_ulong pc) { uint32_t mem_addr; xed_reg_enum_t reg_id; target_ulong target; const xed_operand_t *op = xed_inst_operand(ins, 0); xed_operand_enum_t op_name = xed_operand_name(op); if (operand_is_mem(op_name, &mem_addr, 0)) { PEMU_read_mem(mem_addr,sizeof(target) , &target); } else if (operand_is_reg(op_name, ®_id)){ target = PEMU_get_reg(reg_id); } else{ int len = xed_decoded_inst_get_length(&xedd_g); target = xed_decoded_inst_get_branch_displacement(&xedd_g) + pc + len; } return target; }
unwind_interval * process_and(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iarg, mem_alloc m_alloc) { unwind_interval *next = iarg->current; const xed_operand_t* op0 = xed_inst_operand(xi,0); xed_operand_enum_t op0_name = xed_operand_name(op0); if (op0_name == XED_OPERAND_REG0) { xed_reg_enum_t reg0 = xed_decoded_inst_get_reg(xptr, op0_name); if (x86_isReg_SP(reg0) && UWI_RECIPE(iarg->current)->bp_status != BP_UNCHANGED) { //----------------------------------------------------------------------- // we are adjusting the stack pointer via 'and' instruction //----------------------------------------------------------------------- next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), RA_BP_FRAME, UWI_RECIPE(iarg->current)->sp_ra_pos, UWI_RECIPE(iarg->current)->bp_ra_pos, UWI_RECIPE(iarg->current)->bp_status, UWI_RECIPE(iarg->current)->sp_bp_pos, UWI_RECIPE(iarg->current)->bp_bp_pos, iarg->current, m_alloc); } } return next; }
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; }
/*****************interface functions********************/ void handle_data_rewrite(const xed_inst_t* xi) { unsigned int value = 0, mem_addr = 0, begin = 0, end = 0; xed_reg_enum_t reg_id_0; if(data_func[0] == 0){ setup_data_taint(); } xed_iclass_enum_t opcode = xed_decoded_inst_get_iclass(&xedd_g); const xed_operand_t *op1 = xed_inst_operand(xi, 1); xed_operand_enum_t op_name1 = xed_operand_name(op1); const xed_operand_t *op0 = xed_inst_operand(xi, 0); xed_operand_enum_t op_name0 = xed_operand_name(op0); //dependence data store data addresses unsigned int taint = 0; int mem_idx; if(opcode != XED_ICLASS_LEA){ if(operand_is_mem4(op_name0, &mem_addr, 0)){ mem_idx = op_name0 == XED_OPERAND_MEM1 ? 1 : 0; xed_reg_enum_t base_regid = xed_decoded_inst_get_base_reg(&xedd_g, mem_idx); if((base_regid != XED_REG_INVALID)){ if(taint = d_get_reg_taint(base_regid)){ update_mem_val_type(taint, 1, API_NONE, 0); value = get_mem_val(taint)->val; insert_dependence_data(mem_addr,xed_decoded_inst_operand_length(&xedd_g, 0)); /* if(value < mem_addr)//value is root insert_dependence_data(value, mem_addr + xed_decoded_inst_operand_length(&xedd_g, 0) - value); else{ insert_dependence_data(mem_addr, value > mem_addr + xed_decoded_inst_operand_length(&xedd_g, 0) ? value : mem_addr + xed_decoded_inst_operand_length(&xedd_g, 0) - mem_addr); }*/ } } }else if(operand_is_mem4(op_name1, &mem_addr, 1)){ mem_idx = op_name1 == XED_OPERAND_MEM1 ? 1 : 0; xed_reg_enum_t base_regid = xed_decoded_inst_get_base_reg(&xedd_g, mem_idx); xed_reg_enum_t index_regid = xed_decoded_inst_get_index_reg(&xedd_g, mem_idx); if((base_regid != XED_REG_INVALID)){ int a = 0,b = 0; a = PEMU_get_reg(base_regid); b = PEMU_get_reg(index_regid); if(index_regid!=XED_REG_INVALID && b>a){ if((taint = d_get_reg_taint(index_regid))&&mem_taint==0) { update_mem_val_type(taint, 1, API_NONE, 0); value = get_mem_val(taint)->val; insert_dependence_data(mem_addr,xed_decoded_inst_operand_length(&xedd_g, 0)); } }else if((taint = d_get_reg_taint(base_regid))&&mem_taint==0){ update_mem_val_type(taint, 1, API_NONE, 0); value = get_mem_val(taint)->val; insert_dependence_data(mem_addr,xed_decoded_inst_operand_length(&xedd_g, 0)); } } } } //taint source: if(opcode == XED_ICLASS_PUSH ){ if(operand_is_mem4(op_name0, &mem_addr, 0)){ if(is_dependence_addr(mem_addr) && !is_d_written(mem_addr)){ unsigned int esp = PEMU_get_reg(XED_REG_ESP) - 4; #ifdef DEBUG fprintf(stdout, "taint source:\t%x\n", mem_addr); #endif d_set_mem_taint_bysize(esp, mem_addr, 4); PEMU_read_mem(mem_addr, 4, &value); insert_mem_val(mem_addr, value); } } }else if(opcode == XED_ICLASS_JMP || opcode == XED_ICLASS_CALL_NEAR) { if(operand_is_mem4(op_name0, &mem_addr, 0)){ if(is_dependence_addr(mem_addr) && !is_d_written(mem_addr)){ #ifdef DEBUG fprintf(stdout, "taint source:\t%x\n", mem_addr); #endif d_set_mem_taint_bysize(mem_addr, mem_addr, 4); PEMU_read_mem(mem_addr, 4, &value); insert_mem_val(mem_addr, value); } } }else{ if(opcode != XED_ICLASS_LEA && operand_is_mem4(op_name1, &mem_addr, 1)){ if(is_dependence_addr(mem_addr) && !is_d_written(mem_addr)){ if(operand_is_reg(op_name0, ®_id_0)){ #ifdef DEBUG fprintf(stdout, "taint source:\t%x\n", mem_addr); #endif d_set_reg_taint(reg_id_0, mem_addr); PEMU_read_mem(mem_addr, 4, &value); insert_mem_val(mem_addr, value); }else{ fprintf(stderr, "error in handle_data_rewrite\n"); exit(0); } return; } } } //propagation data_func[opcode](xi); }
int disas_trace_ex(target_ulong pc_start, TRACE trace) { //#define PEMU_DEBUG #ifdef PEMU_DEBUG printf("New trace %x\n", pc_start); #endif target_ulong pc; char inst_str[256]; int newtrace = 0; pc = pc_start; trace->trace_start = pc_start; BBL bbl= get_BBL(pc); trace->head = bbl; INS ins = NULL; #ifdef PEMU_DEBUG printf("New BBL %x\n", pc_start); #endif while(!newtrace){ xed_error_enum_t xed_error = disas_one_inst(pc); if(xed_error != XED_ERROR_NONE){ return -1; } xed_decoded_inst_dump_intel_format(&xedd_g, inst_str, sizeof(inst_str), 0); xed_iclass_enum_t opcode = xed_decoded_inst_get_iclass(&xedd_g); int len = xed_decoded_inst_get_length(&xedd_g); #ifdef PEMU_DEBUG printf("New INS %x %s\n", pc, inst_str); #endif if(!ins){ ins = get_INS(pc); bbl->head = ins; }else{ ins->next = get_INS(pc); ins = ins->next; } if(pemu_hook_funcs.inst_hook != 0) { pemu_inst.PEMU_inst_pc = pc; pemu_hook_funcs.inst_hook(ins, 0); } bbl->inst_count ++; bbl-> size += len; switch(opcode){ //case XED_ICLASS_CALL_FAR: case XED_ICLASS_CALL_NEAR: case XED_ICLASS_SYSENTER: case XED_ICLASS_INT: case XED_ICLASS_INT1: case XED_ICLASS_INT3: case XED_ICLASS_HLT: case XED_ICLASS_RET_FAR: case XED_ICLASS_RET_NEAR: case XED_ICLASS_JMP: case XED_ICLASS_JMP_FAR: newtrace = 1; break; //case XED_ICLASS_IRET: //case XED_ICLASS_IRETD: //case XED_ICLASS_IRETQ: case XED_ICLASS_JB: case XED_ICLASS_JBE: case XED_ICLASS_JL: case XED_ICLASS_JLE: case XED_ICLASS_JNB: case XED_ICLASS_JNBE: case XED_ICLASS_JNL: case XED_ICLASS_JNLE: case XED_ICLASS_JNO: case XED_ICLASS_JNP: case XED_ICLASS_JNS: case XED_ICLASS_JNZ: case XED_ICLASS_JO: case XED_ICLASS_JP: case XED_ICLASS_JRCXZ: case XED_ICLASS_JS: case XED_ICLASS_JZ: { //add new trace target const xed_inst_t * xi = xed_decoded_inst_inst(&xedd_g); const xed_operand_t *op = xed_inst_operand(xi,0); xed_operand_enum_t opname = xed_operand_name(op); target_ulong rel; target_ulong target; rel = xed_decoded_inst_get_branch_displacement(&xedd_g); target = pc + rel + len; PEMU_add_trace(target); #ifdef PEMU_DEBUG printf("New target %x %d\n", target, bbl->inst_count); #endif bbl->next = get_BBL(pc+len); bbl = bbl->next; ins = NULL; #ifdef PEMU_DEBUG printf("New BBL %x\n", pc + len); #endif break; } default: //TODO: break; //set_code_cache(pc, TAINTED); //printf("pc=%lu\tlen=%x\n", pc, len); } pc = pc + len; } if(pemu_hook_funcs.trace_hook != 0) pemu_hook_funcs.trace_hook(trace, 0); BBL bblnext = trace->head; do{ bbl = bblnext; bblnext = bbl->next; INS ins; INS insnext = bbl->head; do{ ins = insnext; insnext = ins->next; free(ins); }while(insnext!=NULL); free(bbl); }while(bblnext!=NULL); free(trace); }
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); }