int helper_pemu_trace(target_ulong pc) { target_ulong target; xed_error_enum_t xed_error = disas_one_inst(pc); if(xed_error != XED_ERROR_NONE){ return -1; } const xed_inst_t * xi = xed_decoded_inst_inst(&xedd_g); xed_iclass_enum_t opcode = xed_decoded_inst_get_iclass(&xedd_g); // char inst_str[512]; // xed_decoded_inst_dump_intel_format(&xedd_g, inst_str, // sizeof(inst_str), 0); switch(opcode){ case XED_ICLASS_JMP: target = Instrument_JMP(xi, pc); break; case XED_ICLASS_CALL_NEAR: target = Instrument_CALL_NEAR(xi,pc); break; case XED_ICLASS_RET_NEAR: target = Instrument_RET(xi); break; default: break; } PEMU_add_trace(target); return 0; }
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; }
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 xed_ast_input_enum_t classify_avx_sse(xed_decoded_inst_t* xedd) { xed_extension_enum_t ext = xed_decoded_inst_get_extension(xedd); xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(xedd); if(iclass == XED_ICLASS_VZEROALL) { return XED_AST_INPUT_VZEROALL; } else if(iclass == XED_ICLASS_VZEROUPPER) { return XED_AST_INPUT_VZEROUPPER; } else if(is_interesting_avx(ext)) { if(is_avx128(xedd)) return XED_AST_INPUT_AVX128; return XED_AST_INPUT_AVX256; } else if(is_sse(xedd)) { return XED_AST_INPUT_SSE; } else if(iclass == XED_ICLASS_XRSTOR) { return XED_AST_INPUT_XRSTOR; } return XED_AST_INPUT_NOTHING; }
xed_uint_t disas_decode_binary(const xed_state_t* dstate, const xed_uint8_t* hex_decode_text, const unsigned int bytes, xed_decoded_inst_t* xedd, xed_uint64_t runtime_address) { xed_uint64_t t1,t2; xed_error_enum_t xed_error; xed_bool_t okay; if (CLIENT_VERBOSE) { print_hex_line(hex_decode_text, bytes); } t1 = xed_get_time(); xed_error = xed_decode(xedd, hex_decode_text, bytes); t2 = xed_get_time(); okay = (xed_error == XED_ERROR_NONE); if (CLIENT_VERBOSE3) { xed_uint64_t delta = t2-t1; printf("Decode time = " XED_FMT_LU "\n", delta); } if (okay) { if (CLIENT_VERBOSE1) { char tbuf[XED_TMP_BUF_LEN]; xed_decoded_inst_dump(xedd,tbuf,XED_TMP_BUF_LEN); printf("%s\n",tbuf); } if (CLIENT_VERBOSE) { char buf[XED_TMP_BUF_LEN]; if (xed_decoded_inst_valid(xedd)) { printf( "ICLASS: %s CATEGORY: %s EXTENSION: %s IFORM: %s" " ISA_SET: %s\n", xed_iclass_enum_t2str(xed_decoded_inst_get_iclass(xedd)), xed_category_enum_t2str(xed_decoded_inst_get_category(xedd)), xed_extension_enum_t2str(xed_decoded_inst_get_extension(xedd)), xed_iform_enum_t2str(xed_decoded_inst_get_iform_enum(xedd)), xed_isa_set_enum_t2str(xed_decoded_inst_get_isa_set(xedd))); } memset(buf,0,XED_TMP_BUF_LEN); disassemble(buf,XED_TMP_BUF_LEN, xedd, runtime_address,0); printf("SHORT: %s\n", buf); } return 1; } else { xed_decode_error(0, 0, hex_decode_text, xed_error); return 0; } (void) dstate; // pacify compiler }
xed_iclass_enum_t xed_iclass(char* ins) { xed_decoded_inst_t xedd; xed_decoded_inst_t *xptr = &xedd; xed_decoded_inst_zero_set_mode(xptr, &dbg_xed_machine_state); xed_error_enum_t xed_error = xed_decode(xptr, (uint8_t*) ins, 15); if (xed_error != XED_ERROR_NONE) { fprintf(stderr, "!! XED decode failure of insruction @ %p", ins); return XED_ICLASS_INVALID; } return xed_decoded_inst_get_iclass(xptr); }
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 VariableHunter::findAbsoluteVariable(xed_decoded_inst_t &xedd) { const xed_operand_values_t* operandPtr = xed_decoded_inst_operands_const(&xedd); // we need to extract the variable from memory. xed_bool_t mark = xed_operand_values_accesses_memory(operandPtr); if(!mark){ return; } // we ignore the push or pop instruction xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xedd); if( iclass == XED_ICLASS_PUSH || iclass == XED_ICLASS_POP || iclass == XED_ICLASS_ENTER || iclass == XED_ICLASS_LEAVE || iclass == XED_ICLASS_RET_FAR || iclass == XED_ICLASS_RET_NEAR ) { return; } xed_int32_t disp = (xed_int32_t)xed_operand_values_get_memory_displacement_int64(operandPtr); xed_reg_enum_t base_reg = xed_operand_values_get_base_reg(operandPtr, 0); xed_reg_enum_t index_reg = xed_operand_values_get_index_reg(operandPtr, 0); if(base_reg == XED_REG_INVALID && index_reg == XED_REG_INVALID) { if(absolute_variable.find(disp) == absolute_variable.end()) { AbstractVariable *var = new AbstractVariable(); var -> region = Absolute; var -> offset = disp; // we can assign a size here, if the later calculation change this size, everything is OK // if this variable happen to be a boundary variable, the size of instruction will be the size of variable. var -> size = xed_operand_values_get_memory_operand_length(operandPtr, 0); absolute_variable.insert(std::make_pair<int, AbstractVariable*>(disp, var)); } } return; }
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; }
/*for userspace now*/ int disas_basic_block_ex(target_ulong pc_start, struct PEMU_BBL *bbl) { target_ulong pc; //if(pc_start > 0xc0000000) { // return -1; //} bbl->PEMU_bbl_pc = bbl->bbl->start_pc = pc_start; bbl->bbl->size = 0; bbl->bbl->inst_count = 0; pc = pc_start; while(1){ 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); switch(opcode){ //case XED_ICLASS_CALL_FAR: case XED_ICLASS_CALL_NEAR: //case XED_ICLASS_SYSCALL: //case XED_ICLASS_INT: //case XED_ICLASS_INT1: //case XED_ICLASS_INT3: case XED_ICLASS_RET_FAR: case XED_ICLASS_RET_NEAR: //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_JMP: case XED_ICLASS_JMP_FAR: 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: return pc + len; default: //TODO: return; //set_code_cache(pc, TAINTED); //printf("pc=%lu\tlen=%x\n", pc, len); } pc += len; bbl->bbl->size += len; bbl->bbl->inst_count++; } return 0; }
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); }
void OfflineX86Code::disasm(FILE* file, TCA fileStartAddr, TCA codeStartAddr, uint64_t codeLen, const PerfEventsMap<TCA>& perfEvents, BCMappingInfo bcMappingInfo, bool printAddr /* =true */, bool printBinary /* =false */) { char codeStr[MAX_INSTR_ASM_LEN]; xed_uint8_t* code = (xed_uint8_t*) alloca(codeLen); xed_uint8_t* frontier; TCA ip; TCA r10val = 0; size_t currBC = 0; if (codeLen == 0) return; auto const offset = codeStartAddr - fileStartAddr; if (fseek(file, offset, SEEK_SET)) { error("disasm error: seeking file"); } size_t readLen = fread(code, codeLen, 1, file); if (readLen != 1) { error("Failed to read {} bytes at offset {} from code file due to {}", codeLen, offset, feof(file) ? "EOF" : "read error"); } xed_decoded_inst_t xedd; // Decode and print each instruction for (frontier = code, ip = codeStartAddr; frontier < code + codeLen; ) { xed_decoded_inst_zero_set_mode(&xedd, &xed_state); xed_decoded_inst_set_input_chip(&xedd, XED_CHIP_INVALID); xed_error_enum_t xed_error = xed_decode(&xedd, frontier, 15); if (xed_error != XED_ERROR_NONE) break; // Get disassembled instruction in codeStr if (!xed_format_context(xed_syntax, &xedd, codeStr, MAX_INSTR_ASM_LEN, (uint64_t)ip, nullptr #if XED_ENCODE_ORDER_MAX_ENTRIES != 28 // Newer version of XED library , 0 #endif )) { error("disasm error: xed_format_context failed"); } // Annotate the x86 with its bytecode. currBC = printBCMapping(bcMappingInfo, currBC, (TCA)ip); if (printAddr) printf("%14p: ", ip); uint32_t instrLen = xed_decoded_inst_get_length(&xedd); if (printBinary) { uint32_t i; for (i=0; i < instrLen; i++) { printf("%02X", frontier[i]); } for (; i < 16; i++) { printf(" "); } } // For calls, we try to figure out the destination symbol name. // We look both at relative branches and the pattern: // move r10, IMMEDIATE // call r10 xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xedd); string callDest = ""; if (iclass == XED_ICLASS_CALL_NEAR || iclass == XED_ICLASS_CALL_FAR) { const xed_inst_t *xi = xed_decoded_inst_inst(&xedd); always_assert(xed_inst_noperands(xi) >= 1); const xed_operand_t *opnd = xed_inst_operand(xi, 0); xed_operand_enum_t opndName = xed_operand_name(opnd); if (opndName == XED_OPERAND_RELBR) { if (xed_decoded_inst_get_branch_displacement_width(&xedd)) { xed_int32_t disp = xed_decoded_inst_get_branch_displacement(&xedd); TCA addr = ip + instrLen + disp; callDest = getSymbolName(addr); } } else if (opndName == XED_OPERAND_REG0) { if (xed_decoded_inst_get_reg(&xedd, opndName) == XED_REG_R10) { callDest = getSymbolName(r10val); } } } else if (iclass == XED_ICLASS_MOV) { // Look for moves into r10 and keep r10val updated const xed_inst_t* xi = xed_decoded_inst_inst(&xedd); always_assert(xed_inst_noperands(xi) >= 2); const xed_operand_t *destOpnd = xed_inst_operand(xi, 0); xed_operand_enum_t destOpndName = xed_operand_name(destOpnd); if (destOpndName == XED_OPERAND_REG0 && xed_decoded_inst_get_reg(&xedd, destOpndName) == XED_REG_R10) { const xed_operand_t *srcOpnd = xed_inst_operand(xi, 1); xed_operand_enum_t srcOpndName = xed_operand_name(srcOpnd); if (srcOpndName == XED_OPERAND_IMM0) { TCA addr = (TCA)xed_decoded_inst_get_unsigned_immediate(&xedd); r10val = addr; } } } if (!perfEvents.empty()) { printEventStats((TCA)ip, instrLen, perfEvents); } else { printf("%48s", ""); } printf("%s%s\n", codeStr, callDest.c_str()); frontier += instrLen; ip += instrLen; } }
/*****************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); }
static PyObject *get_iclass(instruction_t *self) { return PyInt_FromLong(xed_decoded_inst_get_iclass(self->decoded_inst)); }
/*****************interface functions********************/ void handle_txt_rewrite(const xed_inst_t* xi) { uint32_t value = 0, taint = 0; int i = 0; const xed_operand_t *op; xed_operand_enum_t op_name; unsigned int mem_addr; if(txt_func[0] == 0){ setup_txt_taint(); } int noperands = xed_inst_noperands(xi); xed_iclass_enum_t opcode = xed_decoded_inst_get_iclass(&xedd_g); noperands = noperands > 2 ? 2 : noperands; for( i = 0; i < noperands ; i++){ /* Immediate */ op = xed_inst_operand(xi, i); op_name = xed_operand_name(op); if(opcode == XED_ICLASS_LEA)//hardcode continue; if(operand_is_imm(op_name, &value)) insert_pc_imm(g_pc, value); if(operand_is_mem4(op_name, &mem_addr, i)){ unsigned int taint; unsigned int displacement = 0; int mem_idx = op_name == XED_OPERAND_MEM1 ? 1 : 0; if(xed_operand_written(op)) insert_d_written(mem_addr); 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); displacement = (unsigned int) xed_decoded_inst_get_memory_displacement(&xedd_g, mem_idx); #if 0 if((base_regid != XED_REG_INVALID)) {//indirect mem access if((taint = t_get_reg_taint(base_regid)) && (mem_taint == 0)) {//base reg unsigned int imm = get_pc_imm(taint); //yang insert_pc_addr(taint, 1); insert_dependence_data(mem_addr, xed_decoded_inst_operand_length(&xedd_g, i)); } else if(mem_taint != 0) { //displacement insert_pc_addr(g_pc, 3); insert_dependence_data(mem_addr, xed_decoded_inst_operand_length(&xedd_g, i)); } } else if(index_regid != XED_REG_INVALID) { if((taint = t_get_reg_taint(index_regid)) && (mem_taint ==0)) { insert_pc_addr(taint, 1); insert_dependence_data(mem_addr, xed_decoded_inst_operand_length(&xedd_g, i)); } else if(mem_taint != 0) { insert_pc_addr(g_pc, 3); insert_dependence_data(mem_addr, xed_decoded_inst_operand_length(&xedd_g, i)); } } else if(displacement > 0) {//displacement insert_dependence_data(displacement, mem_addr + xed_decoded_inst_operand_length(&xedd_g, i) - displacement); insert_pc_addr(g_pc, 3); } #endif switch(find_min_dist(mem_addr, g_base, g_index, g_disp)) { case 1: if(taint = t_get_reg_taint(base_regid)) { insert_pc_addr(taint, 1); insert_dependence_data(mem_addr, xed_decoded_inst_operand_length(&xedd_g, i)); } break; case 2: if(taint = t_get_reg_taint(index_regid)) { insert_pc_addr(taint, 1); insert_dependence_data(mem_addr, xed_decoded_inst_operand_length(&xedd_g, i)); } break; case 3: insert_dependence_data(displacement, mem_addr + xed_decoded_inst_operand_length(&xedd_g, i) - displacement); insert_pc_addr(g_pc, 3); break; default: break; } } } unsigned int esp; xed_reg_enum_t dest_r; op_name = xed_operand_name(xed_inst_operand(xi, 0)); if(value != 0){//taint source switch(opcode){ case XED_ICLASS_PUSH: esp = PEMU_get_reg(XED_REG_ESP) - 4; t_set_mem_taint_bysize(esp, g_pc, 4); break; case XED_ICLASS_MOV: if(operand_is_mem4(op_name, &mem_addr, 0)){ t_set_mem_taint_bysize(mem_addr, g_pc, xed_decoded_inst_operand_length(&xedd_g, 0)); }else if(operand_is_reg(op_name, &dest_r)){ t_set_reg_taint(dest_r, g_pc); } break; defalut: break; } return; } //propagation txt_func[opcode](xi); }
void VariableHunter::findStackVariable(xed_decoded_inst_t &xedd) { //unsigned int operandNum = xed_decoded_inst_noperands(&xedd); const xed_operand_values_t* operandPtr = xed_decoded_inst_operands_const(&xedd); bool trackanswer; trackanswer = TrackState -> trackESP(xedd); ASSERT(trackanswer); // we need to extract the variable from memory. xed_bool_t mark = xed_operand_values_accesses_memory(operandPtr); if(!mark){ return; } // we ignore the push or pop instruction xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xedd); if( iclass == XED_ICLASS_PUSH || iclass == XED_ICLASS_POP || iclass == XED_ICLASS_ENTER || iclass == XED_ICLASS_LEAVE || iclass == XED_ICLASS_RET_FAR || iclass == XED_ICLASS_RET_NEAR ) { return; } xed_int32_t disp = (xed_int32_t)xed_operand_values_get_memory_displacement_int64(operandPtr); xed_reg_enum_t base_reg = xed_operand_values_get_base_reg(operandPtr, 0); //xed_reg_enum_t index_reg = xed_operand_values_get_index_reg(operandPtr, 0); //unsigned int length = xed_operand_values_get_memory_operand_length(operandPtr, 0); //unsigned int scale = xed_operand_values_get_scale(operandPtr); //xed_reg_enum_t seg_reg = xed_operand_values_get_seg_reg(operandPtr, 0); //segment reg //EBP based memory access if(base_reg == XED_REG_EBP)//&& index_reg == XED_REG_INVALID) { if(stack_variable.find(disp) == stack_variable.end()) { AbstractVariable *var = new AbstractVariable(); var -> region = Stack; var -> offset = disp; stack_variable.insert(std::make_pair<int, AbstractVariable*>(disp, var)); } } //ESP based memory access if(base_reg == XED_REG_ESP)// && index_reg == XED_REG_INVALID) { int distance = TrackState -> getESP(); disp = disp - distance; // compute the ebp based offset if(stack_variable.find(disp) == stack_variable.end()) { AbstractVariable *var = new AbstractVariable(); var -> region = Stack; var -> offset = disp; // we can assign a size here, if the later calculation change this size, everything is OK // if this variable happen to be a boundary variable, the size of this instruction will be the size of the variable var -> size = xed_operand_values_get_memory_operand_length(operandPtr, 0); // the unit is byte. stack_variable.insert(std::make_pair<int, AbstractVariable*>(disp, var)); } } return; }
OPCODE INS_Opcode (INS ins) { //return pemu_xed.PEMU_opcode; return xed_decoded_inst_get_iclass(ins); }
BOOL INS_IsSyscall (INS ins) { return xed_decoded_inst_get_iclass(ins) == XED_ICLASS_SYSENTER; }
TCA OfflineX86Code::collectJmpTargets(FILE *file, TCA fileStartAddr, TCA codeStartAddr, uint64_t codeLen, vector<TCA> *jmpTargets) { xed_uint8_t* code = (xed_uint8_t*) alloca(codeLen); xed_uint8_t* frontier; TCA ip; if (codeLen == 0) return 0; if (fseek(file, codeStartAddr - fileStartAddr, SEEK_SET)) { error("collectJmpTargets error: seeking file"); } size_t readLen = fread(code, codeLen, 1, file); if (readLen != 1) error("collectJmpTargets error: reading file"); xed_decoded_inst_t xedd; xed_iclass_enum_t iclass = XED_ICLASS_NOP; // Decode each instruction for (frontier = code, ip = codeStartAddr; frontier < code + codeLen; ) { xed_decoded_inst_zero_set_mode(&xedd, &xed_state); xed_decoded_inst_set_input_chip(&xedd, XED_CHIP_INVALID); xed_error_enum_t xed_error = xed_decode(&xedd, frontier, 15); if (xed_error != XED_ERROR_NONE) break; uint32_t instrLen = xed_decoded_inst_get_length(&xedd); iclass = xed_decoded_inst_get_iclass(&xedd); if (iclass >= XED_ICLASS_JB && iclass <= XED_ICLASS_JZ) { const xed_inst_t *xi = xed_decoded_inst_inst(&xedd); always_assert(xed_inst_noperands(xi) >= 1); const xed_operand_t *opnd = xed_inst_operand(xi, 0); xed_operand_enum_t opndName = xed_operand_name(opnd); if (opndName == XED_OPERAND_RELBR) { always_assert(xed_decoded_inst_get_branch_displacement_width(&xedd)); xed_int32_t disp = xed_decoded_inst_get_branch_displacement(&xedd); TCA addr = ip + instrLen + disp; jmpTargets->push_back(addr); } } frontier += instrLen; ip += instrLen; } // If the code sequence falls thru, then add the next instruction as a // possible target bool fallsThru = (iclass != XED_ICLASS_JMP && iclass != XED_ICLASS_JMP_FAR && iclass != XED_ICLASS_RET_NEAR && iclass != XED_ICLASS_RET_FAR); if (fallsThru) { jmpTargets->push_back(ip); return ip; } return 0; }