// 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); } }
void SEMAPHORE::cXADD(INS &ins) { // pointeur vers fonction à appeler void (*callback)() = nullptr; // XADD : opérande 0 est soit mémoire, soit registre, opérande 1 tjs registre REG regSrc = INS_OperandReg(ins, 1); UINT32 regSrcSize = getRegSize(regSrc); if (!regSrcSize) return; // registre non géré en marquage else if (INS_OperandIsMemory(ins, 0)) // XADD_M (opérande 0 = mémoire) { switch (regSrcSize) { case 1: callback = (AFUNPTR) sXADD_M<8>; break; case 2: callback = (AFUNPTR) sXADD_M<16>; break; case 4: callback = (AFUNPTR) sXADD_M<32>; break; #if TARGET_IA32E case 8: callback = (AFUNPTR) sXADD_M<64>; break; #endif } INS_InsertCall (ins, IPOINT_BEFORE, callback, IARG_THREAD_ID, IARG_UINT32, regSrc, IARG_REG_VALUE, regSrc, IARG_MEMORYWRITE_EA, IARG_INST_PTR, IARG_END); } else // XADD_R (opérande 0 = registre) { REG regDest = INS_OperandReg(ins, 0); switch (getRegSize(regDest)) { case 1: callback = (AFUNPTR) sXADD_R<8>; break; case 2: callback = (AFUNPTR) sXADD_R<16>; break; case 4: callback = (AFUNPTR) sXADD_R<32>; break; #if TARGET_IA32E case 8: callback = (AFUNPTR) sXADD_R<64>; break; #endif } INS_InsertCall (ins, IPOINT_BEFORE, callback, IARG_THREAD_ID, IARG_UINT32, regSrc, IARG_REG_VALUE, regSrc, IARG_UINT32, regDest, IARG_REG_VALUE, regDest, IARG_INST_PTR, IARG_END); } } // cXADD
static VOID Instrument(INS ins) { UINT32 op = INS_Opcode(ins); switch (op) { case XED_ICLASS_BT: case XED_ICLASS_BTC: case XED_ICLASS_BTR: case XED_ICLASS_BTS: // Filter out the BTs we want to look at, we don't expect any in system libraries, // but we have seen a bt reg,reg on FC12 if (INS_IsMemoryRead(ins) && !INS_OperandIsImmediate(ins,1)) break; // Fall through and ignore non mem,reg operations. default: return; } INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(ProcessAddress), IARG_ADDRINT, ADDRINT (formatInstruction(ins)), IARG_MEMORYREAD_SIZE, IARG_MEMORYOP_EA, 0, IARG_REG_VALUE, INS_OperandReg(ins, 1), IARG_END); }
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); } }
/****************************************************************** Title:movRMHandler Function:Handler to handle instruction "mov REG [mem addr]" Input: INS ins:Instruction to be handled. int srcA:The 1st src operand. int srcB:The 2nd src operand. int srcC:The 3rd src operand. int dstA:The 1st dst operand. int dstB:The 2nd dst operand. int dstC:The 3rd dst operand. Output: int Return value:-1 means unable to handle the instruction ******************************************************************/ int movRMHandler(INS ins,int srcA,int srcB,int srcC,int dstA,int dstB,int dstC) { REG baseReg = INS_OperandMemoryBaseReg(ins,1); INT64 displacement = INS_OperandMemoryDisplacement(ins,1); REG indexReg = INS_OperandMemoryIndexReg(ins,1); UINT32 scale = INS_OperandMemoryScale(ins,1); if(REG_valid(baseReg)){ INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)getRegisterValue, IARG_REG_VALUE,baseReg, IARG_END); } int valueBaseReg = regValue; if(REG_valid(indexReg)){ INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)getRegisterValue, IARG_REG_VALUE,indexReg, IARG_END); } int valueIndexReg = regValue; unsigned int realAddress = displacement+valueBaseReg+valueIndexReg*scale; if(INS_IsMemoryRead(ins)){ INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(movRMHook), IARG_UINT32, REG(INS_OperandReg(ins, 0)), IARG_MEMORYREAD_EA, IARG_END); }else{ fprintf(log,"Error at reading memory\n"); return -1; } countAllIns++; countHandledIns++; return 0; }
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); } }
VOID Instruction(INS ins, VOID *v) { if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsRead(ins, 0) && INS_OperandIsReg(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)ReadMem, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_UINT32, INS_OperandCount(ins), IARG_UINT32, INS_OperandReg(ins, 0), IARG_MEMORYOP_EA, 0, IARG_REG_VALUE, REG_STACK_PTR, IARG_END); } else if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_UINT32, INS_OperandCount(ins), IARG_UINT32, INS_OperandReg(ins, 1), IARG_MEMORYOP_EA, 0, IARG_REG_VALUE, REG_STACK_PTR, IARG_END); } else if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)spreadRegTaint, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_UINT32, INS_OperandCount(ins), IARG_UINT32, INS_RegR(ins, 0), IARG_UINT32, INS_RegW(ins, 0), IARG_END); } if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)followData, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_UINT32, INS_RegR(ins, 0), IARG_END); } }
// 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); } }
// returns the full name of the first register operand read REG INS_get_read_reg(INS ins) { for (unsigned int i = 0; i < INS_OperandCount(ins); i++) { if (INS_OperandIsReg(ins, i) && INS_OperandRead(ins, i)) { return REG_FullRegName(INS_OperandReg(ins, i)); } } return REG_INVALID(); }
/** * This function is called **/ void traceInst(INS ins, VOID*) { ADDRINT address = INS_Address(ins); std::string mod_name = getModule( address ); RegList regs; for ( UINT32 i = 0; i < INS_OperandCount(ins); i++ ) { if ( INS_OperandIsReg(ins, i) ) { REG x = INS_OperandReg(ins, i); if ( x != REG_INVALID() ) regs.push_back( x ); } } if (isUnknownAddress(address)) { // The address is an address that does not belong to any loaded module. // This is potential shellcode. For these instructions a callback // function is inserted that dumps information to the trace file when // the instruction is actually executed. INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(dump_shellcode), IARG_PTR, new std::string(dumpInstruction(ins)), IARG_PTR, ®s, IARG_CONTEXT, IARG_END ); } else { if ( !modlist.empty() && (modlist.find(mod_name) == modlist.end()) ) // not concerned return; // The address is a legit address, meaning it is probably not part of // any shellcode. In this case we just log the instruction to dump it // later to show when control flow was transfered from legit code to // shellcode. legitInstructions.push_back(dumpInstruction(ins)); if (legitInstructions.size() > KnobMaxLegitInsLogSize.Value()) { // Log only up to KnobMaxLegitInsLogSize.Value() instructions or the whole // program before the shellcode will be dumped. legitInstructions.pop_front(); } } }
/****************************************************************** Title:movRRHandler Function:Handler to handle instruction "mov REG REG" Input: INS ins:Instruction to be handled. int srcA:The 1st src operand. int srcB:The 2nd src operand. int srcC:The 3rd src operand. int dstA:The 1st dst operand. int dstB:The 2nd dst operand. int dstC:The 3rd dst operand. Output: int Return value:-1 means unable to handle the instruction ******************************************************************/ int movRRHandler(INS ins,int srcA,int srcB,int srcC,int dstA,int dstB,int dstC) { REG dstReg = INS_OperandMemoryBaseReg(ins,0); REG srcReg = INS_OperandReg(ins,1); int state = regState[srcReg]; if(state==1){ regState[dstReg]=1; }else{ regState[dstReg]=0; } countAllIns++; countHandledIns++; return 0; }
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); } }
/****************************************************************** Title:movzxRMHandler Function:Handler to handle instruction "movzx reg,[mem addr]" Input: INS ins:Instruction to be handled. int srcA:The 1st src operand. int srcB:The 2nd src operand. int srcC:The 3rd src operand. int dstA:The 1st dst operand. int dstB:The 2nd dst operand. int dstC:The 3rd dst operand. Output: int Return value:-1 means unable to handle the instruction ******************************************************************/ int movzxRMHandler(INS ins,int srcA,int srcB,int srcC,int dstA,int dstB,int dstC) { if(INS_IsMemoryRead(ins)){ INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(movzxRMHook), IARG_UINT32, REG(INS_OperandReg(ins, 0)), IARG_MEMORYREAD_EA, IARG_END); }else{ fprintf(log,"Error at writing memory\n"); return -1; } countAllIns++; countHandledIns++; return 0; }
VOID WriteMem(INS ins, UINT64 memOp) { list<UINT64>::iterator i; UINT64 addr = memOp; REG reg_r; if (INS_OperandCount(ins) != 2) return; reg_r = INS_OperandReg(ins, 1); for(i = addressTainted.begin(); i != addressTainted.end(); i++){ if (addr == *i){ std::cout << std::hex << "[WRITE in " << addr << "]\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; if (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r)) removeMemTainted(addr); return ; } } if (checkAlreadyRegTainted(reg_r)){ std::cout << std::hex << "[WRITE in " << addr << "]\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; addMemTainted(addr); } }
VOID ReadMem(INS ins, UINT64 memOp) { list<UINT64>::iterator i; UINT64 addr = memOp; REG reg_r; if (INS_OperandCount(ins) != 2) return; reg_r = INS_OperandReg(ins, 0); for(i = addressTainted.begin(); i != addressTainted.end(); i++){ if (addr == *i){ std::cout << std::hex << "[READ in " << addr << "]\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; taintReg(reg_r); return ; } } /* if mem != tained and reg == taint => free the reg */ if (checkAlreadyRegTainted(reg_r)){ std::cout << std::hex << "[READ in " << addr << "]\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; removeRegTainted(reg_r); } }
// CALLBACKS void SEMAPHORE::cCMPXCHG(INS &ins) { // CMPXCHG : d'abord une comparaison destination (R ou M) avec // puis 1 MOV selon le resultat de la comparaison // Opérande 0 : ModRM:r/m (si reg : regDest) // Opérande 1 : reg (dénommé regSrc) // CMPXCHG compare opérande 0 avec AL/AX/EAX/RAX // Si égal, ZF = 1 (comme une vraie comparaison) et opérande 1 -> opérande 0 // Si différent : ZF = 0 (comme une vraie comparaison) et opérande 0 -> AL/AX/EAX/RAX // Dans les arguments des callbacks, il vaut ajouter la valeur de AL/AX/EAX/RAX // Et celle du registre dest (cas RR) pour faire la comparaison. // opérande 1 : regSrc REG regSrc = INS_OperandReg(ins, 1); UINT32 regSrcSize = getRegSize(regSrc); if (!regSrcSize) return; // registre non suivi // registre de comparasion avec la destination REG cmpReg = REG_INVALID(); // selon la taille, AL/AX/EAX/RAX // pointeur vers fonction à appeler void (*callback)() = nullptr; if (INS_IsMemoryRead(ins)) // CMPXCHG_RM (source 0 = mémoire) { switch (regSrcSize) { case 1: callback = (AFUNPTR) sCMPXCHG_RM<8>; cmpReg = REG_AL; break; case 2: callback = (AFUNPTR) sCMPXCHG_RM<16>; cmpReg = REG_AX; break; case 4: callback = (AFUNPTR) sCMPXCHG_RM<32>; cmpReg = REG_EAX; break; #if TARGET_IA32E case 8: callback = (AFUNPTR) sCMPXCHG_RM<64>; cmpReg = REG_RAX; break; #endif } INS_InsertCall (ins, IPOINT_BEFORE, callback, IARG_THREAD_ID, IARG_UINT32, regSrc, // pas besoin de la valeur du registre, le déplacement se fera octet par octet IARG_MEMORYREAD_EA, IARG_UINT32, cmpReg, IARG_REG_VALUE, cmpReg, IARG_INST_PTR, IARG_END); } else // CMPXCHG_RR (source 0 = registre) { REG regDest = INS_OperandReg(ins, 0); // registre de destination (comparé à AL/AX/EAX/RAX) switch (getRegSize(regDest)) { case 0: return; // non suivi en instrumentation case 1: callback = (AFUNPTR) sCMPXCHG_RR<8>; cmpReg = REG_AL; break; case 2: callback = (AFUNPTR) sCMPXCHG_RR<16>; cmpReg = REG_AX; break; case 4: callback = (AFUNPTR) sCMPXCHG_RR<32>; cmpReg = REG_EAX; break; #if TARGET_IA32E case 8: callback = (AFUNPTR) sCMPXCHG_RR<64>; cmpReg = REG_RAX; break; #endif } INS_InsertCall (ins, IPOINT_BEFORE, callback, IARG_THREAD_ID, IARG_UINT32, regSrc, IARG_UINT32, regDest, IARG_REG_VALUE, regDest,// valeur indispendable pour comparaison à RAX IARG_UINT32, cmpReg, IARG_REG_VALUE, cmpReg, IARG_INST_PTR, IARG_END); } } // cCMPXCHG
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); } }
// Is called for every instruction and instruments reads and writes VOID Instruction(INS ins, VOID *v) { BOOL readsMemory, writesMemory, hasReadSegmentedMemAccess, hasWriteSegmentedMemAccess; if (INS_EffectiveAddressWidth(ins)==16) { if (INS_SegmentRegPrefix(ins) == TESTED_SEG_REG) { readsMemory = INS_SegPrefixIsMemoryRead(ins); writesMemory = INS_SegPrefixIsMemoryWrite(ins); if(readsMemory) { if (INS_IsMemoryRead(ins)) { HandleSegmentedAccess (ins, TRUE /* isRead*/, &hasReadSegmentedMemAccess) ; } } if (writesMemory) { if (INS_IsMemoryWrite(ins)) { HandleSegmentedAccess (ins, FALSE /* isRead*/, &hasWriteSegmentedMemAccess); } } if (!hasReadSegmentedMemAccess && !hasWriteSegmentedMemAccess) { fprintf(trace, "**ERROR SegMemAccess-Lies %p %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); hadError = TRUE; } else { fprintf (trace, "Instrumented ins: %x %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); } fflush(trace); } else if (INS_IsMemoryRead(ins) || INS_IsMemoryWrite(ins)) { fprintf (trace, "Instrumented ins: %x %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); fflush (trace); HandleAccess (ins, INS_IsMemoryRead(ins)) ; } } #ifndef TARGET_LINUX UINT32 operandCount = INS_OperandCount (ins); UINT32 i; for (i=0; i<operandCount; i++) { if (INS_OperandIsReg (ins, i) && REG_is_seg(INS_OperandReg (ins, i)) && INS_OperandWritten(ins, i)) { fprintf(trace, "**ERROR SegOperand-WRITE, not supported %p %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); fflush(trace); hadError = TRUE; } } #endif /*fprintf(trace, "%p %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); fflush (trace);*/ }
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 Image(IMG img, VOID *v) { #ifdef HEAP // Instrument the malloc() and free() functions. Print the input argument // of each malloc() or free(), and the return value of malloc(). // // 1. Find the malloc() function. RTN mallocRtn = RTN_FindByName(img, MALLOC); if (RTN_Valid(mallocRtn)) { RTN_Open(mallocRtn); // Instrument malloc() to print the input argument value and the return value. RTN_InsertCall(mallocRtn, IPOINT_BEFORE, (AFUNPTR)AllocSize, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END); RTN_InsertCall(mallocRtn, IPOINT_AFTER, (AFUNPTR)AllocAddress, IARG_FUNCRET_EXITPOINT_VALUE, IARG_END); RTN_Close(mallocRtn); } // 2. Find the free() function. RTN freeRtn = RTN_FindByName(img, FREE); if (RTN_Valid(freeRtn)) { RTN_Open(freeRtn); // Instrument free() to print the input argument value. RTN_InsertCall(freeRtn, IPOINT_BEFORE, (AFUNPTR)DeallocAddress, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END); RTN_Close(freeRtn); } #endif #ifdef STACK // 3. Visit all routines to collect frame size for( SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec) ) { for( RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn) ) { RTN_Open(rtn); // collect user functions as well as their addresses ADDRINT fAddr = RTN_Address(rtn); string szFunc = RTN_Name(rtn); g_hAddr2Name[fAddr] = szFunc; //cerr << fAddr << ":\t" << szFunc << endl; //bool bFound = false; for(INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins) ) { // collecting stack size according to "SUB 0x20, %esp" or "ADD 0xffffffe0, %esp" if( INS_Opcode(ins) == XED_ICLASS_SUB && INS_OperandIsReg(ins, 0 ) && INS_OperandReg(ins, 0) == REG_STACK_PTR && INS_OperandIsImmediate(ins, 1) ) { int nOffset = INS_OperandImmediate(ins, 1); if(nOffset < 0 ) { nOffset = -nOffset; } g_hFunc2FrameSize[fAddr] = nOffset; //bFound = true; break; } if( INS_Opcode(ins) == XED_ICLASS_ADD && INS_OperandIsReg(ins, 0 ) && INS_OperandReg(ins, 0) == REG_STACK_PTR && INS_OperandIsImmediate(ins, 1) ) { int nOffset = INS_OperandImmediate(ins, 1); if(nOffset < 0 ) { nOffset = -nOffset; } g_hFunc2FrameSize[fAddr] = nOffset; //bFound = true; break; } } //if( !bFound ) // g_hFunc2FrameSize[fAddr] = 0; RTN_Close(rtn); } } #endif }
// Returns a pointer to an IRBuilder object. // It is up to the user to delete it when times come. IRBuilder *createIRBuilder(INS ins) { uint64 address = INS_Address(ins); std::string disas = INS_Disassemble(ins); INT32 opcode = INS_Opcode(ins); IRBuilder *ir = nullptr; switch (opcode) { case XED_ICLASS_ADC: ir = new AdcIRBuilder(address, disas); break; case XED_ICLASS_ADD: ir = new AddIRBuilder(address, disas); break; case XED_ICLASS_AND: ir = new AndIRBuilder(address, disas); break; case XED_ICLASS_ANDNPD: ir = new AndnpdIRBuilder(address, disas); break; case XED_ICLASS_ANDNPS: ir = new AndnpsIRBuilder(address, disas); break; case XED_ICLASS_ANDPD: ir = new AndpdIRBuilder(address, disas); break; case XED_ICLASS_ANDPS: ir = new AndpsIRBuilder(address, disas); break; case XED_ICLASS_BSWAP: ir = new BswapIRBuilder(address, disas); break; case XED_ICLASS_CALL_FAR: case XED_ICLASS_CALL_NEAR: ir = new CallIRBuilder(address, disas); break; case XED_ICLASS_CBW: ir = new CbwIRBuilder(address, disas); break; case XED_ICLASS_CDQE: ir = new CdqeIRBuilder(address, disas); break; case XED_ICLASS_CLC: ir = new ClcIRBuilder(address, disas); break; case XED_ICLASS_CLD: ir = new CldIRBuilder(address, disas); break; case XED_ICLASS_CMC: ir = new CmcIRBuilder(address, disas); break; case XED_ICLASS_CMOVB: ir = new CmovbIRBuilder(address, disas); break; case XED_ICLASS_CMOVBE: ir = new CmovbeIRBuilder(address, disas); break; case XED_ICLASS_CMOVL: ir = new CmovlIRBuilder(address, disas); break; case XED_ICLASS_CMOVLE: ir = new CmovleIRBuilder(address, disas); break; case XED_ICLASS_CMOVNB: ir = new CmovnbIRBuilder(address, disas); break; case XED_ICLASS_CMOVNBE: ir = new CmovnbeIRBuilder(address, disas); break; case XED_ICLASS_CMOVNL: ir = new CmovnlIRBuilder(address, disas); break; case XED_ICLASS_CMOVNLE: ir = new CmovnleIRBuilder(address, disas); break; case XED_ICLASS_CMOVNO: ir = new CmovnoIRBuilder(address, disas); break; case XED_ICLASS_CMOVNP: ir = new CmovnpIRBuilder(address, disas); break; case XED_ICLASS_CMOVNS: ir = new CmovnsIRBuilder(address, disas); break; case XED_ICLASS_CMOVNZ: ir = new CmovnzIRBuilder(address, disas); break; case XED_ICLASS_CMOVO: ir = new CmovoIRBuilder(address, disas); break; case XED_ICLASS_CMOVP: ir = new CmovpIRBuilder(address, disas); break; case XED_ICLASS_CMOVS: ir = new CmovsIRBuilder(address, disas); break; case XED_ICLASS_CMOVZ: ir = new CmovzIRBuilder(address, disas); break; case XED_ICLASS_CMP: ir = new CmpIRBuilder(address, disas); break; case XED_ICLASS_CQO: ir = new CqoIRBuilder(address, disas); break; case XED_ICLASS_CWDE: ir = new CwdeIRBuilder(address, disas); break; case XED_ICLASS_DEC: ir = new DecIRBuilder(address, disas); break; case XED_ICLASS_DIV: ir = new DivIRBuilder(address, disas); break; case XED_ICLASS_IDIV: ir = new IdivIRBuilder(address, disas); break; case XED_ICLASS_IMUL: ir = new ImulIRBuilder(address, disas); break; case XED_ICLASS_INC: ir = new IncIRBuilder(address, disas); break; case XED_ICLASS_JB: ir = new JbIRBuilder(address, disas); break; case XED_ICLASS_JBE: ir = new JbIRBuilder(address, disas); break; case XED_ICLASS_JL: ir = new JlIRBuilder(address, disas); break; case XED_ICLASS_JLE: ir = new JleIRBuilder(address, disas); break; case XED_ICLASS_JMP: ir = new JmpIRBuilder(address, disas); break; case XED_ICLASS_JNB: ir = new JnbIRBuilder(address, disas); break; case XED_ICLASS_JNBE: ir = new JnbeIRBuilder(address, disas); break; case XED_ICLASS_JNL: ir = new JnlIRBuilder(address, disas); break; case XED_ICLASS_JNLE: ir = new JnleIRBuilder(address, disas); break; case XED_ICLASS_JNO: ir = new JnoIRBuilder(address, disas); break; case XED_ICLASS_JNP: ir = new JnpIRBuilder(address, disas); break; case XED_ICLASS_JNS: ir = new JnsIRBuilder(address, disas); break; case XED_ICLASS_JNZ: ir = new JnzIRBuilder(address, disas); break; case XED_ICLASS_JO: ir = new JoIRBuilder(address, disas); break; case XED_ICLASS_JP: ir = new JpIRBuilder(address, disas); break; case XED_ICLASS_JS: ir = new JsIRBuilder(address, disas); break; case XED_ICLASS_JZ: ir = new JzIRBuilder(address, disas); break; case XED_ICLASS_LEA: ir = new LeaIRBuilder(address, disas); break; case XED_ICLASS_LEAVE: ir = new LeaveIRBuilder(address, disas); break; case XED_ICLASS_MOV: ir = new MovIRBuilder(address, disas); break; case XED_ICLASS_MOVAPD: ir = new MovapdIRBuilder(address, disas); break; case XED_ICLASS_MOVAPS: ir = new MovapsIRBuilder(address, disas); break; case XED_ICLASS_MOVDQA: ir = new MovdqaIRBuilder(address, disas); break; case XED_ICLASS_MOVDQU: ir = new MovdquIRBuilder(address, disas); break; case XED_ICLASS_MOVHLPS: ir = new MovhlpsIRBuilder(address, disas); break; case XED_ICLASS_MOVHPD: ir = new MovhpdIRBuilder(address, disas); break; case XED_ICLASS_MOVHPS: ir = new MovhpsIRBuilder(address, disas); break; case XED_ICLASS_MOVLHPS: ir = new MovlhpsIRBuilder(address, disas); break; case XED_ICLASS_MOVLPD: ir = new MovlpdIRBuilder(address, disas); break; case XED_ICLASS_MOVLPS: ir = new MovlpsIRBuilder(address, disas); break; case XED_ICLASS_MOVSX: case XED_ICLASS_MOVSXD: ir = new MovsxIRBuilder(address, disas); break; case XED_ICLASS_MOVZX: ir = new MovzxIRBuilder(address, disas); break; case XED_ICLASS_MUL: ir = new MulIRBuilder(address, disas); break; case XED_ICLASS_NEG: ir = new NegIRBuilder(address, disas); break; case XED_ICLASS_NOT: ir = new NotIRBuilder(address, disas); break; case XED_ICLASS_OR: ir = new OrIRBuilder(address, disas); break; case XED_ICLASS_ORPD: ir = new OrpdIRBuilder(address, disas); break; case XED_ICLASS_ORPS: ir = new OrpsIRBuilder(address, disas); break; case XED_ICLASS_POP: ir = new PopIRBuilder(address, disas); break; case XED_ICLASS_PUSH: ir = new PushIRBuilder(address, disas); break; case XED_ICLASS_RET_FAR: case XED_ICLASS_RET_NEAR: ir = new RetIRBuilder(address, disas); break; case XED_ICLASS_ROL: ir = new RolIRBuilder(address, disas); break; case XED_ICLASS_ROR: ir = new RorIRBuilder(address, disas); break; case XED_ICLASS_SAR: ir = new SarIRBuilder(address, disas); break; case XED_ICLASS_SBB: ir = new SbbIRBuilder(address, disas); break; case XED_ICLASS_SETB: ir = new SetbIRBuilder(address, disas); break; case XED_ICLASS_SETBE: ir = new SetbeIRBuilder(address, disas); break; case XED_ICLASS_SETL: ir = new SetlIRBuilder(address, disas); break; case XED_ICLASS_SETLE: ir = new SetleIRBuilder(address, disas); break; case XED_ICLASS_SETNB: ir = new SetnbIRBuilder(address, disas); break; case XED_ICLASS_SETNBE: ir = new SetnbeIRBuilder(address, disas); break; case XED_ICLASS_SETNL: ir = new SetnlIRBuilder(address, disas); break; case XED_ICLASS_SETNLE: ir = new SetnleIRBuilder(address, disas); break; case XED_ICLASS_SETNO: ir = new SetnoIRBuilder(address, disas); break; case XED_ICLASS_SETNP: ir = new SetnpIRBuilder(address, disas); break; case XED_ICLASS_SETNS: ir = new SetnsIRBuilder(address, disas); break; case XED_ICLASS_SETNZ: ir = new SetnzIRBuilder(address, disas); break; case XED_ICLASS_SETO: ir = new SetoIRBuilder(address, disas); break; case XED_ICLASS_SETP: ir = new SetpIRBuilder(address, disas); break; case XED_ICLASS_SETS: ir = new SetsIRBuilder(address, disas); break; case XED_ICLASS_SETZ: ir = new SetzIRBuilder(address, disas); break; case XED_ICLASS_SHL: // XED_ICLASS_SAL is also a SHL ir = new ShlIRBuilder(address, disas); break; case XED_ICLASS_SHR: ir = new ShrIRBuilder(address, disas); break; case XED_ICLASS_STC: ir = new StcIRBuilder(address, disas); break; case XED_ICLASS_STD: ir = new StdIRBuilder(address, disas); break; case XED_ICLASS_SUB: ir = new SubIRBuilder(address, disas); break; case XED_ICLASS_TEST: ir = new TestIRBuilder(address, disas); break; case XED_ICLASS_XADD: ir = new XaddIRBuilder(address, disas); break; case XED_ICLASS_XCHG: ir = new XchgIRBuilder(address, disas); break; case XED_ICLASS_XOR: ir = new XorIRBuilder(address, disas); break; case XED_ICLASS_XORPD: ir = new XorpdIRBuilder(address, disas); break; case XED_ICLASS_XORPS: ir = new XorpsIRBuilder(address, disas); break; default: ir = new NullIRBuilder(address, disas); break; } // Populate the operands const uint32 n = INS_OperandCount(ins); for (uint32 i = 0; i < n; ++i) { IRBuilderOperand::operand_t type; uint32 size = 0; uint64 val = 0; //Effective address = Displacement + BaseReg + IndexReg * Scale uint64 displacement = 0; uint64 baseReg = ID_INVALID; uint64 indexReg = ID_INVALID; uint64 memoryScale = 0; /* Special case */ if (INS_IsDirectBranchOrCall(ins)){ ir->addOperand(TritonOperand(IRBuilderOperand::IMM, INS_DirectBranchOrCallTargetAddress(ins), 0)); if (INS_MemoryOperandIsWritten(ins, 0)) ir->addOperand(TritonOperand(IRBuilderOperand::MEM_W, 0, INS_MemoryWriteSize(ins))); break; } /* Immediate */ if (INS_OperandIsImmediate(ins, i)) { type = IRBuilderOperand::IMM; val = INS_OperandImmediate(ins, i); } /* Register */ else if (INS_OperandIsReg(ins, i)) { type = IRBuilderOperand::REG; REG reg = INS_OperandReg(ins, i); val = PINConverter::convertDBIReg2TritonReg(reg); // store the register ID. if (REG_valid(reg)) { // check needed because instructions like "xgetbv 0" make // REG_Size crash. size = REG_Size(reg); } } /* Memory */ else if (INS_MemoryOperandCount(ins) > 0) { /* Memory read */ if (INS_MemoryOperandIsRead(ins, 0)) { type = IRBuilderOperand::MEM_R; size = INS_MemoryReadSize(ins); } /* Memory write */ else { type = IRBuilderOperand::MEM_W; size = INS_MemoryWriteSize(ins); } } /* load effective address instruction */ else if (INS_OperandIsAddressGenerator(ins, i)) { REG reg; type = IRBuilderOperand::LEA; displacement = INS_OperandMemoryDisplacement(ins, i); memoryScale = INS_OperandMemoryScale(ins, i); reg = INS_OperandMemoryBaseReg(ins, i); if (REG_valid(reg)) baseReg = PINConverter::convertDBIReg2TritonReg(reg); reg = INS_OperandMemoryIndexReg(ins, i); if (REG_valid(reg)) indexReg = PINConverter::convertDBIReg2TritonReg(reg); } /* Undefined */ else { // std::cout << "[DEBUG] Unknown kind of operand: " << INS_Disassemble(ins) << std::endl; continue; } ir->addOperand(TritonOperand(type, val, size, displacement, baseReg, indexReg, memoryScale)); } // Setup the opcode in the IRbuilder ir->setOpcode(opcode); ir->setOpcodeCategory(INS_Category(ins)); ir->setNextAddress(INS_NextAddress(ins)); return ir; }
VOID Instruction(INS ins, VOID *v){ /** * INS_InsertCall(INS ins, IPOINT action, AFUNPTR funptr, ...) * * insert a call to 'docount' relative to instruction 'ins' * * ins: instruction to instrument * action: specifies before/after, etc. IPOINT_BEFORE is always valid for all instructions. * funptr: insert a call to funptr. * ...: list of arguments to pass funptr, terminated with IARG_END */ //INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)stat_ins, IARG_END); InsCount ++; //string ins_cat = CATEGORY_StringShort(INS_Category(ins)); int num_ops = INS_OperandCount(ins); //total #operands int memOperands = INS_MemoryOperandCount(ins); //#mem_operands string op_string = ""; //string to record all operands stringstream sstm; //string stream int num_mems = 0; for(int ii=0; ii<num_ops; ii++){ //iterate each operand if(INS_OperandIsImmediate(ins, ii)){ //immediate auto value = INS_OperandImmediate(ins, ii); sstm.str(""); //empty sstm << "$" << value; op_string += " " + sstm.str(); } else if(INS_OperandIsReg(ins, ii)){ //register auto reg = REG_StringShort(INS_OperandReg(ins, ii)); sstm.str(""); sstm << "%" << reg; op_string += " " + sstm.str(); } else if(INS_OperandIsMemory(ins, ii) && memOperands>0){ //memory string mem_type = "memXX"; if(INS_MemoryOperandIsRead(ins, num_mems)) { mem_type = "memR"; } else if(INS_MemoryOperandIsWritten(ins, num_mems)) { mem_type = "memW"; } if(INS_MemoryOperandIsRead(ins, num_mems) && INS_MemoryOperandIsWritten(ins, num_mems)) { mem_type = "memRW"; } ++ num_mems; op_string += " " + mem_type; //true if this operand is a memory reference, //Note: this does not include LEA operands. } else if(INS_OperandIsMemory(ins, ii) && memOperands==0){ //NOP assert(INS_IsNop(ins)); } else { //TRUE if memory operand uses predefined base register and this register can not be changed //Example: movs ds:(esi), es:(edi) There are two fixed operands string other_type = ""; if(INS_OperandIsFixedMemop(ins, ii)) other_type = "FM"; //true if this operand is a displacement (e.g. branch offset) else if(INS_OperandIsBranchDisplacement(ins, ii)) other_type = "BD"; //true if this operand is implied by the opcode (e.g. the stack write in a push instruction) else if(INS_OperandIsImplicit(ins, ii)) other_type = "IM"; else { assert(INS_IsLea(ins)); other_type = "lea"; } op_string += " " + other_type; } } assert(num_mems == memOperands); assert(num_ops <= 6); //record ins INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)record_ins, IARG_THREAD_ID, IARG_UINT32, INS_Opcode(ins), IARG_UINT32, num_ops, IARG_PTR, new string(op_string), IARG_END); if (INS_IsXchg(ins) && INS_OperandReg(ins, 0)==REG_BX && INS_OperandReg(ins, 1)==REG_BX) { //INS_InsertPredictedCall() is used to call analysis functions. //This API function prevents pollution of the memory analysis by calling an analysis function only if a particular //instruction is actualy executed, i.e., only if the instruction is executed. INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)handleHook, IARG_THREAD_ID, IARG_REG_VALUE, REG_GAX, #ifdef TARGET_IA32 IARG_REG_VALUE, REG_GDX, #else IARG_REG_VALUE, REG_GBX, #endif IARG_REG_VALUE, REG_GCX, IARG_END); } }
void log_ins(INS ins) { // dump the instruction INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &execute_instruction, IARG_INST_PTR, IARG_PTR, strdup(INS_Disassemble(ins).c_str()), IARG_END); // reads memory (1) if(INS_IsMemoryRead(ins) != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_read_memory, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_END); } // reads memory (2) if(INS_HasMemoryRead2(ins) != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_read_memory, IARG_MEMORYREAD2_EA, IARG_MEMORYREAD_SIZE, IARG_END); } IPOINT after = IPOINT_AFTER; if(INS_IsCall(ins) != 0) { // TODO is this correct? after = IPOINT_TAKEN_BRANCH; } else if(INS_IsSyscall(ins) != 0) { // TODO support syscalls return; } else if(INS_HasFallThrough(ins) == 0 && (INS_IsBranch(ins) != 0 || INS_IsRet(ins) != 0)) { // TODO is this correct? after = IPOINT_TAKEN_BRANCH; } // dump written memory if(INS_IsMemoryWrite(ins) != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_written_memory_before, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_written_memory_after, IARG_END); } // dump all affected registers for (UINT32 i = 0; i < INS_OperandCount(ins); i++) { if(INS_OperandIsMemory(ins, i) != 0) { if(INS_OperandMemoryBaseReg(ins, i) != REG_INVALID()) { REG base_reg = INS_OperandMemoryBaseReg(ins, i); if(g_reg_index[base_reg] != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_reg_before, IARG_UINT32, g_reg_index[base_reg]-1, IARG_REG_VALUE, INS_OperandMemoryBaseReg(ins, i), IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_r_after, IARG_UINT32, g_reg_index[base_reg]-1, IARG_END); } } if(INS_OperandMemoryIndexReg(ins, i) != REG_INVALID()) { REG index_reg = INS_OperandMemoryIndexReg(ins, i); if(g_reg_index[index_reg] != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_reg_before, IARG_UINT32, g_reg_index[index_reg]-1, IARG_REG_VALUE, INS_OperandMemoryIndexReg(ins, i), IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_r_after, IARG_UINT32, g_reg_index[index_reg]-1, IARG_END); } } } if(INS_OperandIsReg(ins, i) != 0) { REG reg_index = REG_FullRegName(INS_OperandReg(ins, i)); if(INS_OperandReadAndWritten(ins, i) != 0) { if(g_reg_index[reg_index] != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_reg_before, IARG_UINT32, g_reg_index[reg_index]-1, IARG_REG_VALUE, reg_index, IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_rw_after, IARG_UINT32, g_reg_index[reg_index]-1, IARG_REG_VALUE, reg_index, IARG_END); } } else if(INS_OperandRead(ins, i) != 0) { if(g_reg_index[reg_index] != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_reg_before, IARG_UINT32, g_reg_index[reg_index]-1, IARG_REG_VALUE, reg_index, IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_r_after, IARG_UINT32, g_reg_index[reg_index]-1, IARG_END); } } else if(INS_OperandWritten(ins, i) != 0) { if(g_reg_index[reg_index] != 0) { INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_w_after, IARG_UINT32, g_reg_index[reg_index]-1, IARG_REG_VALUE, reg_index, IARG_END); } } } } INS_InsertCall(ins, after, (AFUNPTR) &print_newline, IARG_END); }
VOID Instruction(INS ins, VOID *v) { PIN_LockClient(); IMG img = IMG_FindByAddress(INS_Address(ins)); PIN_UnlockClient(); if (IMG_Valid(img) && IMG_IsMainExecutable(img)){ if (INS_IsCall(ins)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)PrologueAnalysis, IARG_ADDRINT, INS_Address(ins), IARG_ADDRINT, INS_NextAddress(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_END); } else if (INS_IsRet(ins)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)EpilogueAnalysis, IARG_ADDRINT, INS_Address(ins), IARG_ADDRINT, INS_NextAddress(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_END); } else if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_UINT32, INS_OperandCount(ins), IARG_UINT32, INS_OperandReg(ins, 1), IARG_MEMORYOP_EA, 0, IARG_END); } /* Value Set Analysis */ if (INS_Opcode(ins) == XED_ICLASS_MOV && INS_RegR(ins, 0) == REG_RBP && INS_RegR(ins, 1) == REG_INVALID() && INS_IsMemoryWrite(ins)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)ValueSetAnalysis, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_REG_VALUE, REG_RSP, IARG_REG_VALUE, REG_RBP, IARG_MEMORYOP_EA, 0, IARG_END); } /* Analyzes stack overflow */ if (INS_MemoryOperandIsWritten(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)WriteMemAnalysis, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_MEMORYOP_EA, 0, IARG_END); } /* Timer Handler - And instruction counter */ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)timerHandler, IARG_ADDRINT, INS_Address(INS_Prev(ins)), IARG_ADDRINT, INS_Address(ins), IARG_ADDRINT, INS_Address(INS_Next(ins)), IARG_PTR, new string(INS_Disassemble(ins)), IARG_END); } }