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); } }
VOID delete_int3(INS ins, VOID* v) { if (INS_Opcode(ins) == XED_ICLASS_INT3) { INS_Delete(ins); } }
// Pin calls this function every time a new instruction is encountered VOID Instruction(INS ins, VOID *v) { if (INS_IsVgather(ins)) { REG ymmDest = INS_OperandReg(ins, 0), ymmMask = INS_OperandReg(ins, 2); if (!REG_is_ymm(ymmDest)) { ymmDest = (REG)(ymmDest - REG_XMM0 + REG_YMM0); } if (!REG_is_ymm(ymmMask)) { ymmMask = (REG)(ymmMask - REG_XMM0 + REG_YMM0); } INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)EmuGather, IARG_CONTEXT, IARG_MULTI_MEMORYACCESS_EA, IARG_REG_REFERENCE, ymmDest, IARG_REG_REFERENCE, ymmMask, IARG_END); INS_InsertFillBuffer(ins, IPOINT_BEFORE, bufId, IARG_MULTI_MEMORYACCESS_EA, 0, IARG_END); INS_Delete(ins); } }
// Delete the first mov immediate static VOID deleteMov (RTN rtn) { for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { if (INS_IsMov(ins) && INS_HasImmediateOperand(ins)) { INS_Delete(ins); instrumentationCount++; return; } } }
VOID Ins( INS ins, VOID *v ) { if (KnobDetach > 0 && scount > KnobDetach) return; if (KnobLog) { void *addr = Addrint2VoidStar(INS_Address(ins)); string disasm = INS_Disassemble(ins); PrintIns(addr, disasm.c_str()); } scount++; // call and return need also stack manipulation (see emu_stack.cpp) // conditional jumps need handling the condition (not supported yet) if (INS_IsCall(ins) || INS_IsRet(ins) || INS_Category(ins) == XED_CATEGORY_COND_BR) return; if (INS_IsIndirectBranchOrCall(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuIndJmp), IARG_BRANCH_TARGET_ADDR, IARG_RETURN_REGS, scratchReg, IARG_END); INS_InsertIndirectJump(ins, IPOINT_AFTER, scratchReg); INS_Delete(ins); } else if (INS_IsDirectBranchOrCall(ins)) { ADDRINT tgt = INS_DirectBranchOrCallTargetAddress(ins); INS_InsertDirectJump(ins, IPOINT_AFTER, tgt); INS_Delete(ins); } }
VOID FirstInCC(TRACE trace, VOID * v) { if (!test) return; test = false; BBL bbl = TRACE_BblHead(trace); while (!BBL_Valid(bbl)) bbl = BBL_Next(bbl); INS_Delete(BBL_InsHead(bbl)); TEST(!TRACE_Original(trace), "TRACE_Original failed"); }
VOID EmulateLoad(INS ins, VOID* v) { if (INS_Opcode(ins) == XEDICLASS_MOV && INS_IsMemoryRead(ins) && INS_OperandIsReg(ins, 0) && INS_OperandIsMemory(ins, 1)) { // op0 <- *op1 INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(DoLoad), IARG_UINT32, REG(INS_OperandReg(ins, 0)), IARG_MEMORYREAD_EA, IARG_RETURN_REGS, INS_OperandReg(ins, 0), IARG_END); INS_Delete(ins); } }
// Pin calls this function every time a new instruction is encountered VOID Instruction(INS ins, VOID *v) { if (INS_IsVgather(ins)) { REG ymmDest = INS_OperandReg(ins, 0), ymmMask = INS_OperandReg(ins, 2); if (!REG_is_ymm(ymmDest)) { ymmDest = (REG)(ymmDest - REG_XMM0 + REG_YMM0); } if (!REG_is_ymm(ymmMask)) { ymmMask = (REG)(ymmMask - REG_XMM0 + REG_YMM0); } for (UINT32 memIndex = 0; memIndex < INS_MemoryOperandCount(ins);//each access is 1 MemoryOperand memIndex++) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuGatherMemOp), IARG_UINT32, memIndex, IARG_MEMORYOP_EA, memIndex, IARG_MEMORYOP_MASKED_ON, memIndex, IARG_UINT32, INS_MemoryOperandSize(ins, memIndex), IARG_UINT32, INS_MemoryOperandIsRead(ins, memIndex), IARG_REG_REFERENCE, ymmDest, IARG_BOOL, REG_is_ymm(INS_OperandReg(ins, 0)), IARG_END); REG scratchReg = GetScratchReg(memIndex); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(ManipulateMemAddress), IARG_MEMORYOP_EA, memIndex, IARG_RETURN_REGS, scratchReg, IARG_END); INS_RewriteMemoryOperand(ins, memIndex, scratchReg); } INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)EmuGatherFinal, IARG_REG_REFERENCE, ymmDest, IARG_REG_REFERENCE, ymmMask, IARG_END); INS_Delete(ins); } }
// Pin calls this function every time a new instruction is encountered VOID Instruction(INS ins, VOID *v) { //get the address of the current instruction ADDRINT address = INS_Address(ins); //get the string rapresentation of the address string addr = StringFromAddrint(address); //if we reach the address of the conditional jump (discover by hand with immunity) //we substitute this instruction with an uncoditional jump in order o force the execution path if(addr.compare("0x00411a10") == 0){ //get the jmp target address ADDRINT tgt = INS_DirectBranchOrCallTargetAddress(ins); string addr2 = StringFromAddrint(tgt); //insert the incoditional jmp INS_InsertDirectJump(ins, IPOINT_BEFORE, tgt); //fprintf(file, "%s\n", addr2.c_str()); //remove the conditional jmp instruction INS_Delete(ins); } }
VOID EmulateLoad(INS ins, VOID* v) { // Find the instructions that move a value from memory to a register if (INS_Opcode(ins) == XED_ICLASS_MOV && INS_IsMemoryRead(ins) && INS_OperandIsReg(ins, 0) && INS_OperandIsMemory(ins, 1)) { // op0 <- *op1 INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(DoLoad), IARG_UINT32, REG(INS_OperandReg(ins, 0)), IARG_MEMORYREAD_EA, IARG_RETURN_REGS, INS_OperandReg(ins, 0), IARG_END); // Delete the instruction INS_Delete(ins); } }
VOID HandleAccess (INS ins, BOOL isRead) { UINT32 operandCount = INS_OperandCount (ins); UINT32 i, displacement=0, scale=0; REG baseReg = REG_INVALID(), indexReg = REG_INVALID(); BOOL instrumented = FALSE; for (i=0; i<operandCount; i++) { if ( ((INS_OperandIsMemory (ins, i) && isRead && INS_OperandRead (ins, i)) || (INS_OperandIsMemory (ins, i) && !isRead && INS_OperandWritten (ins, i))) ) { displacement = INS_OperandMemoryDisplacement (ins, i); baseReg = INS_OperandMemoryBaseReg (ins, i); indexReg = INS_OperandMemoryIndexReg (ins, i); scale = INS_OperandMemoryScale (ins, i); break; } } if (baseReg != REG_INVALID()) { if (indexReg != REG_INVALID()) { if (isRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeMemAccessBaseIndexDispl, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_UINT32, BASE_INDEX_DISPLACEMENT_ADDRESSING_READ_TYPE, IARG_REG_VALUE, baseReg, IARG_REG_VALUE, indexReg, IARG_UINT32, scale, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeMemAccessBaseIndexDispl, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_UINT32, BASE_INDEX_DISPLACEMENT_ADDRESSING_WRITE_TYPE, IARG_REG_VALUE, baseReg, IARG_REG_VALUE, indexReg, IARG_UINT32, scale, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } instrumented = TRUE; } else { if (isRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeMemAccessBaseDispl, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_UINT32, BASE_DISPLACEMENT_ADDRESSING_READ_TYPE, IARG_REG_VALUE, baseReg, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeMemAccessBaseDispl, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_UINT32, BASE_DISPLACEMENT_ADDRESSING_WRITE_TYPE, IARG_REG_VALUE, baseReg, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } instrumented = TRUE; } } else { if (isRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeMemAccessDispl, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_UINT32, DISPLACEMENT_ONLY_ADDRESSING_READ_TYPE, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeMemAccessDispl, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_UINT32, DISPLACEMENT_ONLY_ADDRESSING_WRITE_TYPE, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } instrumented = TRUE; } ASSERTX (instrumented); // must delete this INS - since it's memory address is 16bit, cannot be sure // it accesses valid memory - so we are only testing the IARG_MEMORY(READ/WRITE)_EA // on these instructions INS_Delete(ins); }
VOID Emulate2Address(OPCODE opcode, INS ins, ADDRINT (*OpRM)(ADDRINT,ADDRINT*), ADDRINT (*OpRV)(ADDRINT,ADDRINT), VOID (*OpMV)(ADDRINT*,ADDRINT)) { if (INS_Opcode(ins) != opcode) return; if (INS_OperandIsMemory(ins, 0) // This will filter out segment overrides && INS_IsMemoryWrite(ins)) { if (INS_OperandIsReg(ins, 1) && REG_is_gr(INS_OperandReg(ins, 1))) { // Source register, dst memory INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(OpMV), IARG_MEMORYWRITE_EA, IARG_REG_VALUE, INS_OperandReg(ins, 1), IARG_END); INS_Delete(ins); } else { ASSERTX(!INS_OperandIsMemory(ins, 1)); } } else if (INS_OperandIsReg(ins, 0)) { REG dst = INS_OperandReg(ins, 0); if ((dst == REG_SEG_GS) || (dst == REG_SEG_FS)) return; if (INS_OperandIsReg(ins, 1)) { // Source register, dst register INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(OpRV), IARG_REG_VALUE, INS_OperandReg(ins, 0), IARG_REG_VALUE, INS_OperandReg(ins, 1), IARG_RETURN_REGS, INS_OperandReg(ins, 0), IARG_END); INS_Delete(ins); } else if (INS_OperandIsMemory(ins, 1) // This will filter out segment overrides && INS_IsMemoryRead(ins)) { // Source register, dst register INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(OpRM), IARG_REG_VALUE, INS_OperandReg(ins, 0), IARG_MEMORYREAD_EA, IARG_RETURN_REGS, INS_OperandReg(ins, 0), IARG_END); INS_Delete(ins); } } #if 0 if (KnobCount == icount) fprintf(stderr,"Last one %s\n",INS_Disassemble(ins).c_str()); else if (icount > KnobCount) return; icount++; #endif }
VOID Ins( INS ins, VOID *v ) { if (KnobDetach > 0 && scount > KnobDetach) return; if (KnobLog) { void *addr = Addrint2VoidStar(INS_Address(ins)); string disasm = INS_Disassemble(ins); PrintIns(addr, disasm.c_str()); } scount++; if (INS_Opcode(ins) == XED_ICLASS_PUSH) { if (INS_OperandIsImmediate(ins, 0)) { ADDRINT value = INS_OperandImmediate(ins, 0); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPushValue), IARG_REG_VALUE, REG_STACK_PTR, IARG_ADDRINT, value, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else if(INS_OperandIsReg(ins, 0)) { REG reg = INS_OperandReg(ins, 0); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPushValue), IARG_REG_VALUE, REG_STACK_PTR, IARG_REG_VALUE, reg, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else if(INS_OperandIsMemory(ins, 0)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPushMem), IARG_REG_VALUE, REG_STACK_PTR, IARG_MEMORYREAD_EA, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else { fprintf(stderr, "EmuPush: unsupported operand type (%p:'%s')\n", Addrint2VoidStar(INS_Address(ins)), INS_Disassemble(ins).c_str()); } } else if (INS_Opcode(ins) == XED_ICLASS_POP) { if(INS_OperandIsReg(ins, 0)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPopReg), IARG_REG_VALUE, REG_STACK_PTR, IARG_REG_REFERENCE, INS_OperandReg(ins, 0), IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else if(INS_OperandIsMemory(ins, 0)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPopMem), IARG_REG_VALUE, REG_STACK_PTR, IARG_MEMORYWRITE_EA, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else { fprintf(stderr, "EmuPop: unsupported operand type (%p:'%s')\n", Addrint2VoidStar(INS_Address(ins)), INS_Disassemble(ins).c_str()); } } else if (INS_Opcode(ins) == XED_ICLASS_LEAVE) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuLeave), IARG_REG_VALUE, REG_STACK_PTR, IARG_REG_REFERENCE, REG_GBP, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else if (INS_IsCall(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuCall), IARG_ADDRINT, INS_NextAddress(ins), IARG_BRANCH_TARGET_ADDR, IARG_REG_REFERENCE, REG_STACK_PTR, IARG_RETURN_REGS, scratchReg, IARG_END); INS_InsertIndirectJump(ins, IPOINT_AFTER, scratchReg); INS_Delete(ins); } else if (INS_IsRet(ins)) { UINT64 imm = 0; if (INS_OperandCount(ins) > 0 && INS_OperandIsImmediate(ins, 0)) { imm = INS_OperandImmediate(ins, 0); } INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuRet), IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_REG_REFERENCE, REG_STACK_PTR, IARG_ADDRINT, (ADDRINT)imm, IARG_RETURN_REGS, scratchReg, IARG_END); INS_InsertIndirectJump(ins, IPOINT_AFTER, scratchReg); INS_Delete(ins); } else if (INS_IsIndirectBranchOrCall(ins)) { // This is not a call (it was checked before) so this is indirect jump INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuIndJmp), IARG_BRANCH_TARGET_ADDR, IARG_RETURN_REGS, scratchReg, IARG_END); INS_InsertIndirectJump(ins, IPOINT_AFTER, scratchReg); INS_Delete(ins); } }