VOID InstrumentDivide(INS ins, VOID* v) { cout << "instruction:"<<INS_Mnemonic(ins)<<endl; if ((INS_Mnemonic(ins) == "DIV") && (INS_OperandIsReg(ins, 0))) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmulateIntDivide), IARG_REG_REFERENCE, REG_GDX, IARG_REG_REFERENCE, REG_GAX, IARG_REG_VALUE, REG(INS_OperandReg(ins, 0)), IARG_CONTEXT, IARG_THREAD_ID, IARG_END); INS_Delete(ins); } if ((INS_Mnemonic(ins) == "DIV") && (!INS_OperandIsReg(ins, 0))) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmulateMemDivide), IARG_REG_REFERENCE, REG_GDX, IARG_REG_REFERENCE, REG_GAX, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_CONTEXT, IARG_THREAD_ID, IARG_END); INS_Delete(ins); } }
/* * Instrumentation-time routine inspecting a single instruction, looking for * those with an immediate operand. */ VOID Instruction(INS ins, VOID *v) { *outFile << "Querying instruction w/opcode: " << INS_Mnemonic(ins) << endl; // Go over operands INT32 count = INS_OperandCount(ins); bool operands_reported = false; for (INT32 i = 0; i < count; i++) { if (INS_OperandIsImmediate(ins, i)) { // Get the value itself ADDRINT value = INS_OperandImmediate(ins, i); long signed_value = (long)value; // Get length information INT32 length_bits = -1; bool is_signed = false; GetOperLenAndSigned(ins, i, length_bits, is_signed); OnInstruction(value, signed_value, is_signed, length_bits); operands_reported = true; } } if (!operands_reported) { *outFile << "No immediate operands per this command" << endl; } }
static const char *INS_Mnemonic_detour(INS ins) { static char cyclic_strings[32][32]; static uint32_t cyclic_index; string s = INS_Mnemonic(ins); if(s.c_str() == NULL) return NULL; return strcpy(*CYCLIC(cyclic_strings, cyclic_index), s.c_str()); }
VOID RecordMemRead(INS ins, VOID * ip, VOID * addr) { cout<<"opcode:"<<INS_Opcode(ins)<<", mnemonic: "<<INS_Mnemonic(ins)<<endl; printf("%p: addr: %p, R %d\n", ip,addr, *(((int *)addr)+1)); /*if(*(int *)addr == 666) { cout<<"replacing"<<endl; *(int *)addr = 777; }*/ }
// This function is called before every instruction is executed VOID instrument_routine(RTN rtn, void *ip) { string name = RTN_Name(rtn); if(name == "ivan") { RTN_Open(rtn); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { int opCount = INS_OperandCount(ins); int opcode = INS_Opcode(ins); if(INS_IsMemoryRead(ins)) { for(int i = 0; i< opCount; i++) { if(INS_MemoryOperandIsRead(ins,i)) { /* INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordMemRead,IARG_PTR,ins, IARG_INST_PTR, IARG_MEMORYOP_EA, i, IARG_END); */ cout<<"opcode:"<<INS_Opcode(ins)<<", mnemonic: "<<INS_Mnemonic(ins)<<endl; if(INS_Opcode(ins)!= XED_ICLASS_RET_NEAR) { REG scratchReg = GetScratchReg(i); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(GetMemAddress), IARG_MEMORYOP_EA, i, IARG_RETURN_REGS, scratchReg, IARG_END); INS_RewriteMemoryOperand(ins, i, scratchReg); } } } } if(INS_IsMemoryWrite(ins)) { for(int i = 0; i< opCount; i++) { /* if(INS_OperandIsImmediate(ins,i)) { cout<<"immediate "<<INS_OperandImmediate(ins,i)<<endl; } */ if(INS_MemoryOperandIsWritten(ins,i) && INS_HasFallThrough(ins)) { /* INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_MEMORYOP_EA, i, IARG_END); INS_InsertCall( ins, IPOINT_AFTER, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_MEMORYOP_EA, i, IARG_END); */ if(opcode != XED_ICLASS_PUSH) { REG scratchReg = GetScratchReg(i); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(GetMemAddress), IARG_MEMORYOP_EA, i, IARG_RETURN_REGS, scratchReg, IARG_END); INS_RewriteMemoryOperand(ins, i, scratchReg); } } } } } RTN_Close(rtn); } }
/* instrumenting (instruction level) */ VOID instrument_itypes(INS ins, VOID* v){ int i,j; char cat[50]; char opcode[50]; strcpy(cat,CATEGORY_StringShort(INS_Category(ins)).c_str()); strcpy(opcode,INS_Mnemonic(ins).c_str()); BOOL categorized = false; // go over all groups, increase group count if instruction matches that group // group counts are increased at most once per instruction executed, // even if the instruction matches multiple identifiers in that group for(i=0; i < number_of_groups; i++){ for(j=0; j < group_ids_cnt[i]; j++){ if(group_identifiers[i][j].type == identifier_type::ID_TYPE_CATEGORY){ if(strcmp(group_identifiers[i][j].str, cat) == 0){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)itypes_count, IARG_UINT32, i, IARG_END); categorized = true; break; } } else{ if(group_identifiers[i][j].type == identifier_type::ID_TYPE_OPCODE){ if(strcmp(group_identifiers[i][j].str, opcode) == 0){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)itypes_count, IARG_UINT32, i, IARG_END); categorized = true; break; } } else{ if(group_identifiers[i][j].type == identifier_type::ID_TYPE_SPECIAL){ if(strcmp(group_identifiers[i][j].str, "mem_read") == 0 && INS_IsMemoryRead(ins) ){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)itypes_count, IARG_UINT32, i, IARG_END); categorized = true; break; } else{ if(strcmp(group_identifiers[i][j].str, "mem_write") == 0 && INS_IsMemoryWrite(ins) ){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)itypes_count, IARG_UINT32, i, IARG_END); categorized = true; break; } else{ } } } else{ cerr << "ERROR! Unknown identifier type specified (" << group_identifiers[i][j].type << ")." << endl; } } } } } // count instruction that don't fit in any of the specified categories in the last group if( !categorized ){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)itypes_count, IARG_UINT32, (unsigned int)number_of_groups, IARG_END); // check whether this category is already known in the 'other' group for(i=0; i < other_ids_cnt; i++){ if(strcmp(other_group_identifiers[i].str, cat) == 0) break; } // if a new instruction category is found, add it to the set if(i == other_ids_cnt){ other_group_identifiers[other_ids_cnt].type = identifier_type::ID_TYPE_CATEGORY; other_group_identifiers[other_ids_cnt].str = (char*)malloc((strlen(cat)+1)*sizeof(char)); strcpy(other_group_identifiers[other_ids_cnt].str, cat); other_ids_cnt++; } // prepare for (possible) next category if(other_ids_cnt >= other_ids_max_cnt){ other_ids_max_cnt *= 2; other_group_identifiers = (identifier*)realloc(other_group_identifiers, other_ids_max_cnt*sizeof(identifier)); } } /* inserting calls for counting instructions is done in mica.cpp */ if(interval_size != -1){ INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)itypes_instr_intervals,IARG_END); /* only called if interval is 'full' */ INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)itypes_instr_interval,IARG_END); } }