Example #1
0
/******************************************************************
 Title:instruction
 Function:Pin calls this function every time a new instruction is 
 executed
 Input:
 RTN rtn:The current instruction.
 VOID *v:The second argument.
 Output:
 VOID
******************************************************************/
VOID instruction(INS ins, VOID *v)
{
	/*fprintf(trace,insName.c_str());
	fprintf(trace,"\n");
	decode(ins);*/
	if(flag==0&&hasFound==0)
		return;
	else
		hasFound=1;
	if(flag==1&&hasFound==1){
		fprintf(output,"****************************************************\n");
		fprintf(output,"Before the application\n");
		ADDRINT baseAdd = getAddr();
		ADDRINT length = getSizeL();
		memManager->markTaintedBlock(baseAdd,length);
		memManager->printState(output);
		flag=0;
	}
	OPCODE opcode  = INS_Opcode(ins);
	UINT32 operandCount = INS_OperandCount(ins);
	UINT insExt = INS_Extension(ins);
	unsigned int realOpcode = opcode&0xffff;
	OperandKind kind = getOperandKind(ins);
	unsigned int insKind = INSNUM(realOpcode,kind);
	handleIns(insKind,ins);
}
Example #2
0
/*
 * 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 BOOL INS_HasImmediateOperand(INS ins)
{
    for (unsigned int i=0; i< INS_OperandCount(ins); i++)
        if (INS_OperandIsImmediate(ins, i))
            return TRUE;

    return FALSE;
}
Example #4
0
bool INS_has_immed(INS ins)
{
    for (unsigned int i = 0; i < INS_OperandCount(ins); i++)
    {
        if (INS_OperandIsImmediate(ins, i))
        {
            return true;
        }
    }
    return false;
}
Example #5
0
REG INS_get_memwr_basereg(INS ins)
{
	for (unsigned int i = 0; i < INS_OperandCount(ins); i++)
	{
        if (INS_OperandIsMemory(ins, i) && INS_OperandWritten(ins, i))
        {
            return REG_FullRegName(INS_OperandMemoryBaseReg(ins, i));
        }
    }
    
    return REG_INVALID();
}
Example #6
0
REG INS_get_mem_indexreg(INS ins)
{
	for (unsigned int i = 0; i < INS_OperandCount(ins); i++)
	{
        if (INS_OperandIsMemory(ins, i) && INS_OperandRead(ins, i))
        {
            return REG_FullRegName(INS_OperandMemoryIndexReg(ins, i));
        }
    }
    
    return REG_INVALID();
}
Example #7
0
// 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();
}
Example #8
0
/**
* 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, &regs,
                       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();
        }
    }
}
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_PTR, ins,
        IARG_MEMORYOP_EA, 0,
        IARG_END);
  }
  else if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)){
    INS_InsertCall(
        ins, IPOINT_BEFORE, (AFUNPTR)WriteMem,
        IARG_PTR, ins,
        IARG_MEMORYOP_EA, 0,
        IARG_END);
  }
  else if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){
    INS_InsertCall(
        ins, IPOINT_BEFORE, (AFUNPTR)spreadRegTaint,
        IARG_PTR, ins,
        IARG_END);
  }
}
Example #10
0
void taint_ins(INS ins, void *v)
{
    uint32_t opcode = INS_Opcode(ins);
    uint32_t opcount = INS_OperandCount(ins);

    // the generic stuff only supports up to 5 operands
    if(opcount < 6 && taint_handler_count[opcode] != 0) {
        // first we have to build up the flags, which is kind of expensive.
        uint32_t flags = 0;

        for (uint32_t i = 0; i < opcount; i++) {
            uint32_t op_flag = 0;
            if(INS_OperandIsMemory(ins, i) != 0) {
                op_flag |= T_MEM;
            }
            if(INS_OperandIsAddressGenerator(ins, i) != 0) {
                op_flag |= T_ADR;
            }
            if(INS_OperandIsReg(ins, i) != 0) {
                op_flag |= T_REG;
            }
            if(INS_OperandIsImmediate(ins, i) != 0) {
                op_flag |= T_IMM;
            }
            if(INS_OperandRead(ins, i) != 0) {
                op_flag |= T_RD;
            }
            if(INS_OperandWritten(ins, i) != 0) {
                op_flag |= T_WR;
            }
            flags |= op_flag << (6 * i);
        }

        for (uint32_t i = 0; i < taint_handler_count[opcode]; i++) {
            if(taint_handler_flag[opcode][i] == flags) {
                taint_prop_handle(ins, taint_handler_fn[opcode][i],
                    taint_handler_args[opcode][i]);
                return;
            }
        }
    }
}
Example #11
0
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);
  }
}
Example #12
0
static void Instruction(INS ins, VOID *)
{
    UINT32 op = INS_Opcode(ins);

    for (UINT32 j=0; j<NumTestDescriptions; j++)
    {
        instructionTest * t = &tests[j];

        if (t->opcode != op)
            continue;

        /* Aha, a test which applies to this opcode */
        UINT32 result = 0;
        INT32 operand = t->operand;
        
        if (operand < 0)
            operand = INS_OperandCount(ins) - operand;

        // Run all the property enquiries and accumulate the results.
        for (UINT32 i=0;i<NumTestFunctions;i++)
        {
            if (t->testProps & (1<<i))
            {
                if (testFunctions[i](ins, operand))
                    result |= (1<<i);
            }
        }
        testCounts[op].tested++;

        // Check the result against the expected value.
        if  (result != t->result)
        {
            testCounts[op].failed++;

            out << std::setw(50) << std::left << INS_Disassemble(ins) << std::right <<
                "Operand " << operand <<
                " Expected '" << formatMask(t->result) <<
                "' Got '" << formatMask(result) << "'" << endl;
        }
    }
}
Example #13
0
VOID RewriteBases(INS ins, BOOL * live)
{
    for (UINT32 i = 0; i < INS_OperandCount(ins); i++)
    {
        if (!INS_OperandIsMemory(ins, i))
            continue;
        
        if (INS_OperandMemoryIndexReg(ins, i) != REG_INVALID())
        {
            CheckEffectiveAddress(ins);
            return;
        }
            
        REG baseReg = INS_OperandMemoryBaseReg(ins, i);

        // If no basereg is used, then it must be an absolute address
        if (baseReg == REG_INVALID())
            continue;

        // No need to rewrite stack references
        if (baseReg == REG_ESP)
            continue;
        
        // If we reach this point, we have an instruction that
        // must be rewritten, but if the memory operand is
        // implicit, we can't rewrite the base register
        if (INS_OperandIsImplicit(ins, i))
        {
            CheckEffectiveAddress(ins);
            return;
        }
        
        REG shadowReg = ShadowReg(baseReg);
        INS_OperandMemorySetBaseReg(ins, i, shadowReg);

        // Remember to write the shadow register
        live[RegIndex(baseReg)] = true;
    }
}
Example #14
0
VOID Instruction(INS ins, VOID *v)
{
    INT32 count = INS_OperandCount(ins);
    
    for (INT32 i = 0; i < 5; i++)
    {
        if (i >= count)
        {
            dis << "        ";
            continue;
        }
        
        else if (INS_OperandIsAddressGenerator(ins, i))
            dis << "AGN";
        else if (INS_OperandIsMemory(ins, i))
        {
            dis << "MEM";
            dis << " " << REG_StringShort(INS_OperandMemoryBaseReg(ins, i));
        }
        else if (INS_OperandIsReg(ins, i))
            dis << "REG";
        else if (INS_OperandIsImmediate(ins, i))
            dis << "IMM";
        else if (INS_OperandIsDisplacement(ins, i))
            dis << "DSP";
        else
            dis << "XXX";

        if (INS_OperandIsImplicit(ins, i))
            dis << ":IMP ";
        else
            dis << "     ";
                
        
    }

    dis << INS_Disassemble(ins) << endl;
}
VOID spreadRegTaint(INS ins)
{
  REG reg_r, reg_w;

  if (INS_OperandCount(ins) != 2)
    return;

  reg_r = INS_RegR(ins, 0);
  reg_w = INS_RegW(ins, 0);
  
  if (REG_valid(reg_w)){
    if (checkAlreadyRegTainted(reg_w) && (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r))){
      std::cout << "[SPREAD]\t\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl;
      std::cout << "\t\t\toutput: "<< REG_StringShort(reg_w) << " | input: " << (REG_valid(reg_r) ? REG_StringShort(reg_r) : "constant") << std::endl;
      removeRegTainted(reg_w);
    }
    else if (!checkAlreadyRegTainted(reg_w) && checkAlreadyRegTainted(reg_r)){
      std::cout << "[SPREAD]\t\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl;
      std::cout << "\t\t\toutput: " << REG_StringShort(reg_w) << " | input: "<< REG_StringShort(reg_r) << std::endl;
      taintReg(reg_w);
    }
  }
}
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);
  }
}
Example #18
0
VOID decode(INS ins)
{
	OPCODE opcode  = INS_Opcode(ins);
	UINT32 operandCount = INS_OperandCount(ins);
	UINT insExt = INS_Extension(ins);
	unsigned int realOpcode = opcode&0xffff;
	unsigned int insKind = INSNUM(realOpcode,1);
	/*for(int i = 0;i<operandCount;i++){
		if(INS_OperandIsAddressGenerator(ins,i))
			fprintf(trace,"operand%d is address generator\n",i);
		else if(::INS_OperandIsMemory(ins,i))
			fprintf(trace,"operand%d is address\n",i);
		else if(::INS_OperandIsImmediate(ins,i))
			fprintf(trace,"operand%d is immediate\n",i);
		else if(::INS_OperandIsReg(ins,i))
			fprintf(trace,"operand%d is register\n",i);
		else if(INS_OperandIsBranchDisplacement(ins,i))
			fprintf(trace,"operand%d is branch displacement\n",i);
		else fprintf(trace,"operand%d is other type\n",i);
	}*/
	/*fprintf(trace,"Opcode:%d | operand count:%d\n",realOpcode,operandCount);
	OperandKind kind = getOperandKind(ins);
	fprintf(trace,"insNum:%d\n",INSNUM(opcode,kind));*/
}
Example #19
0
// 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;
}
Example #20
0
    /* Trace instrumentation */
    static void TRACE_Instrumentation(TRACE trace, VOID *v) {

      for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
        for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) {

          /* Check if the analysis me be unlocked */
          tracer::pintool::checkUnlockAnalysis(INS_Address(ins));

          if (!tracer::pintool::analysisTrigger.getState())
          /* Analysis locked */
            continue;

          if (tracer::pintool::instructionBlacklisted(INS_Address(ins)) == true || tracer::pintool::instructionWhitelisted(INS_Address(ins)) == false)
          /* Insruction blacklisted */
            continue;

          /* Prepare the Triton's instruction */
          triton::arch::Instruction* tritonInst = new triton::arch::Instruction();

          /* Save memory read1 informations */
          if (INS_IsMemoryRead(ins)) {
            INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)saveMemoryAccess,
              IARG_PTR, tritonInst,
              IARG_MEMORYREAD_EA,
              IARG_MEMORYREAD_SIZE,
              IARG_END);
          }

          /* Save memory read2 informations */
          if (INS_HasMemoryRead2(ins)) {
            INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)saveMemoryAccess,
              IARG_PTR, tritonInst,
              IARG_MEMORYREAD2_EA,
              IARG_MEMORYREAD_SIZE,
              IARG_END);
          }

          /* Callback before */
          INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)callbackBefore,
            IARG_PTR, tritonInst,
            IARG_INST_PTR,
            IARG_UINT32, INS_Size(ins),
            IARG_CONTEXT,
            IARG_THREAD_ID,
            IARG_END);

          /* Callback after */
          /* Syscall after context must be catcher with INSERT_POINT.SYSCALL_EXIT */
          if (INS_IsSyscall(ins) == false) {
            IPOINT where = IPOINT_AFTER;
            if (INS_HasFallThrough(ins) == false)
              where = IPOINT_TAKEN_BRANCH;
            INS_InsertCall(ins, where, (AFUNPTR)callbackAfter, IARG_PTR, tritonInst, IARG_CONTEXT, IARG_THREAD_ID, IARG_END);
          }

          /* I/O memory monitoring for snapshot */
          if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)) {
            INS_InsertCall(
              ins, IPOINT_BEFORE, (AFUNPTR)callbackSnapshot,
              IARG_MEMORYOP_EA, 0,
              IARG_UINT32, INS_MemoryWriteSize(ins),
              IARG_END);
          }

        }
      }
    }
// 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);*/
}
Example #22
0
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);
    }
}
Example #23
0
VOID instrument_reg(INS ins, ins_buffer_entry* e){


	UINT32 i, maxNumRegsProd, maxNumRegsCons, regReadCnt, regWriteCnt, opCnt, regOpCnt;
	REG reg;

	if(!e->setRead){

		maxNumRegsCons = INS_MaxNumRRegs(ins); // maximum number of register consumations (reads)

		regReadCnt = 0;
		for(i = 0; i < maxNumRegsCons; i++){ // finding all register operands which are read
			reg = INS_RegR(ins,i);
			//assert(((UINT32)reg) < MAX_NUM_REGS);
			/* only consider valid general-purpose registers (any bit-width) and floating-point registers,
			 * i.e. exlude branch, segment and pin registers, among others */
			if(REG_valid(reg) && (REG_is_fr(reg) || REG_is_mm(reg) || REG_is_xmm(reg) || REG_is_gr(reg) || REG_is_gr8(reg) || REG_is_gr16(reg) || REG_is_gr32(reg) || REG_is_gr64(reg))){
				regReadCnt++;
			}
		}

		e->regReadCnt = regReadCnt;
		e->regsRead = (REG*) checked_malloc(regReadCnt*sizeof(REG));

		regReadCnt = 0;
		for(i = 0; i < maxNumRegsCons; i++){ // finding all register operands which are read
			reg = INS_RegR(ins,i);
			//assert(((UINT32)reg) < MAX_NUM_REGS);
			/* only consider valid general-purpose registers (any bit-width) and floating-point registers,
			 * i.e. exlude branch, segment and pin registers, among others */
			if(REG_valid(reg) && (REG_is_fr(reg) || REG_is_mm(reg) || REG_is_xmm(reg) || REG_is_gr(reg) || REG_is_gr8(reg) || REG_is_gr16(reg) || REG_is_gr32(reg) || REG_is_gr64(reg))){
				e->regsRead[regReadCnt++] = reg;
			}
		}
		e->setRead = true;
	}
	if(!e->setWritten){

		maxNumRegsProd = INS_MaxNumWRegs(ins);

		regWriteCnt = 0;
		for(i=0; i < maxNumRegsProd; i++){

			reg = INS_RegW(ins, i);
			//assert(((UINT32)reg) < MAX_NUM_REGS);
			/* only consider valid general-purpose registers (any bit-width) and floating-point registers,
			 * i.e. exlude branch, segment and pin registers, among others */
			if(REG_valid(reg) && (REG_is_fr(reg) || REG_is_mm(reg) || REG_is_xmm(reg) || REG_is_gr(reg) || REG_is_gr8(reg) || REG_is_gr16(reg) || REG_is_gr32(reg) || REG_is_gr64(reg))){
				regWriteCnt++;
			}
		}

		e->regWriteCnt = regWriteCnt;
		e->regsWritten = (REG*)checked_malloc(regWriteCnt*sizeof(REG));

		regWriteCnt = 0;
		for(i=0; i < maxNumRegsProd; i++){

			reg = INS_RegW(ins, i);
			//assert(((UINT32)reg) < MAX_NUM_REGS);
			/* only consider valid general-purpose registers (any bit-width) and floating-point registers,
			 * i.e. exlude branch, segment and pin registers, among others */
			if(REG_valid(reg) && (REG_is_fr(reg) || REG_is_mm(reg) || REG_is_xmm(reg) || REG_is_gr(reg) || REG_is_gr8(reg) || REG_is_gr16(reg) || REG_is_gr32(reg) || REG_is_gr64(reg))){
				e->regsWritten[regWriteCnt++] = reg;
			}
		}


		e->setWritten = true;
	}

	if(!e->setRegOpCnt){
		regOpCnt = 0;
		opCnt = INS_OperandCount(ins);
		for(i = 0; i < opCnt; i++){
			if(INS_OperandIsReg(ins,i))
				regOpCnt++;
		}
		/*if(regOpCnt >= MAX_NUM_OPER){
			cerr << "BOOM! -> MAX_NUM_OPER is exceeded! (" << regOpCnt << ")" << endl;
			exit(1);
		}*/
		e->regOpCnt = regOpCnt;
		e->setRegOpCnt = true;
	}

	if(interval_size == -1){
		INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)reg_instr_full, IARG_PTR, (void*)e, IARG_END);
	}
	else{
		INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)reg_instr_intervals, IARG_PTR, (void*)e, IARG_END);
		/* only called if interval is full */
		INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)reg_instr_interval, IARG_END);
	}
}
Example #24
0
// 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);
    }
}
VOID HandleAccess (INS ins, BOOL isRead, BOOL *hasSegmentedMemAccess)
{
    UINT32 operandCount = INS_OperandCount (ins);
    UINT32 i, displacement, scale;
    REG baseReg = REG_INVALID(), indexReg = REG_INVALID();
    *hasSegmentedMemAccess = FALSE;
    
    for (i=0; i<operandCount; i++)
    {
        if (INS_OperandIsMemory (ins, i) && 
            (INS_OperandMemorySegmentReg (ins, i) == TESTED_SEG_REG ) &&
            ((isRead && INS_OperandRead (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);
            *hasSegmentedMemAccess = TRUE;
            break;
        }
    }
    /*fprintf(trace, "  SegMemAccess-%s (hasSegmentedMemAccess %d) (operand %d) %p %s\n", 
           isRead?"READ":"WRITE", *hasSegmentedMemAccess, i, INS_Address(ins), INS_Disassemble(ins).c_str());*/
    if (baseReg != REG_INVALID())
    {
        if (indexReg != REG_INVALID())
        {
            if (isRead)
            {
                INS_InsertPredicatedCall(
                    ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessBaseIndexDispl,
                    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)AnalyzeSegmentedMemAccessBaseIndexDispl,
                    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);

            }
        }
        else
        {
            if (isRead)
            {
                INS_InsertPredicatedCall(
                    ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessBaseDispl,
                    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)AnalyzeSegmentedMemAccessBaseDispl,
                    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);
            }
        }
    }
    else if (indexReg != REG_INVALID())
    {
        if (isRead)
        {
            INS_InsertPredicatedCall(
                    ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessIndexDispl,
                    IARG_INST_PTR,
                    IARG_MEMORYREAD_EA,
                    IARG_UINT32, INDEX_DISPLACEMENT_ADDRESSING_READ_TYPE,
                    IARG_REG_VALUE, indexReg,
                    IARG_UINT32, scale,
                    IARG_UINT32, displacement,
                    IARG_THREAD_ID,
                    IARG_END);
        }
        else
        {
            INS_InsertPredicatedCall(
                ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessIndexDispl,
                IARG_INST_PTR,
                IARG_MEMORYWRITE_EA,
                IARG_UINT32, INDEX_DISPLACEMENT_ADDRESSING_WRITE_TYPE,
                IARG_REG_VALUE, indexReg,
                IARG_UINT32, scale,
                IARG_UINT32, displacement,
                IARG_THREAD_ID,
                IARG_END);
        }
        
    }
    else if (*hasSegmentedMemAccess)
    {
        if (isRead)
        {
            INS_InsertPredicatedCall(
                ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessDispl,
                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)AnalyzeSegmentedMemAccessDispl,
                IARG_INST_PTR,
                IARG_MEMORYWRITE_EA,
                IARG_UINT32, DISPLACEMENT_ONLY_ADDRESSING_WRITE_TYPE,
                IARG_UINT32, displacement,
                IARG_THREAD_ID,
                IARG_END);
        }

    }
}
VOID Instruction(INS ins, VOID *v)
{
    
    if (INS_IsMemoryRead(ins) && !instrumentedReadFromIpWithNoOffset)
    {
        
        BOOL readsFromIpWithNoOffset = FALSE;
        for (UINT32 i = 0; i < INS_OperandCount(ins); i++)
        {
            if (!INS_OperandIsMemory(ins, i))
                continue;
        

            if (INS_OperandMemoryBaseReg(ins, i) == REG_INST_PTR && INS_OperandMemoryDisplacement(ins, i)==0)
            {
                readsFromIpWithNoOffset = TRUE;
                break;
            }
        }
        if (!readsFromIpWithNoOffset)
        {
            return;
        }
        instrumentedReadFromIpWithNoOffset = TRUE; // only instrument one of these
        printf ("Instrumenting [ip] read   %p   %s\n", INS_Address(ins), INS_Disassemble(ins).c_str());
        globalIpOfReadRecordedAtInstrumentationTime = INS_Address(ins);
        globalReadInsSize = INS_Size(ins);
        fflush (stdout);
        INS_InsertCall(ins,IPOINT_BEFORE, 
                       (AFUNPTR)IpReadBefore,
                       IARG_INST_PTR,
                       IARG_MEMORYREAD_EA,
                       IARG_REG_VALUE, REG_INST_PTR,
                       IARG_END);
		INS_InsertCall(ins,IPOINT_AFTER, 
                       (AFUNPTR)IpReadAfter,
                       IARG_REG_VALUE, REG_INST_PTR,
                       IARG_END);
    }
    else if (INS_IsMemoryWrite(ins) && !instrumentedWriteFromIpWithNoOffset)
    {
        /*
        const xed_decoded_inst_t* xedd = INS_XedDec(ins);
        
        xed_reg_enum_t breg1 = xed_decoded_inst_get_base_reg(xedd,0);
        if (breg1== XED_REG_RIP) 
        {
            readsFromIpWithNoOffset = TRUE;
        }
        */
        BOOL writesFromIpWithNoOffset = FALSE;
        for (UINT32 i = 0; i < INS_OperandCount(ins); i++)
        {
            if (!INS_OperandIsMemory(ins, i))
                continue;
        

            if (INS_OperandMemoryBaseReg(ins, i) == REG_INST_PTR && INS_OperandMemoryDisplacement(ins, i)==0)
            {
                writesFromIpWithNoOffset = TRUE;
                break;
            }
        }
        if (!writesFromIpWithNoOffset)
        {
            return;
        }
        instrumentedReadFromIpWithNoOffset = TRUE; // only instrument one of these
        printf ("Instrumenting [ip] write  %p   %s\n", INS_Address(ins), INS_Disassemble(ins).c_str());
        globalIpOfWriteRecordedAtInstrumentationTime = INS_Address(ins);
        globalWriteInsSize = INS_Size(ins);
        fflush (stdout);
        INS_InsertCall(ins,IPOINT_BEFORE, 
                       (AFUNPTR)IpWriteBefore,
                       IARG_INST_PTR,
                       IARG_MEMORYWRITE_EA,
                       IARG_REG_VALUE, REG_INST_PTR,
                       IARG_END);
		INS_InsertCall(ins,IPOINT_AFTER, 
                       (AFUNPTR)IpWriteAfter,
                       IARG_REG_VALUE, REG_INST_PTR,
                       IARG_END);
    }
    

}
Example #27
0
VOID instruction(INS ins, void *v) 
{

    UINT32 numOperands = INS_OperandCount(ins);
    int numOpMems = 0;
    for (unsigned int i = 0; i < numOperands; i++) {
        //check number of reads and writes
        if (INS_OperandIsMemory(ins, i))
            numOpMems++;
    }

    if (numOpMems > 2) {
        std::cout << "number of operands = " << numOpMems << std::endl;
    }

    const ADDRINT iaddr = INS_Address(ins);

    UINT32 idx;
   struct PC item;
   item.refs = 0;
   item.miss = 0;
   item.pc = iaddr;
   iCachePC.push_back(item);
   idx = iCachePC.size() - 1;


    INS_InsertPredicatedCall(
            ins, IPOINT_BEFORE, (AFUNPTR) iCacheCount,
            IARG_ADDRINT,
            iaddr,
            IARG_UINT32,
            idx,
            IARG_END);

    if (INS_IsMemoryRead(ins)) {
        struct PC readItem;
        readItem.refs = 0;
        readItem.miss = 0;
        readItem.pc = iaddr;
        readItem.isLoad = 1;
        dCachePC.push_back(readItem);
        UINT32 idx2 = dCachePC.size()-1;
        INS_InsertPredicatedCall(
                ins, IPOINT_BEFORE, (AFUNPTR) dCacheCount,
                IARG_ADDRINT,
                iaddr,
                IARG_MEMORYREAD_EA,
                IARG_MEMORYREAD_SIZE,
                IARG_UINT32,
                idx2,
                IARG_UINT32,
                1,
                IARG_UINT32,
                0,
                IARG_END);

        if (INS_HasMemoryRead2(ins)) {
            INS_InsertPredicatedCall(
                    ins, IPOINT_BEFORE, (AFUNPTR) dCacheCount,
                    IARG_ADDRINT,
                    iaddr,
                    IARG_MEMORYREAD2_EA,
                    IARG_MEMORYREAD_SIZE,
                    IARG_UINT32,
                    idx2,
                    IARG_UINT32,
                    1,
                    IARG_UINT32,
                    1,
                    IARG_END);
        }

    }
    if (INS_IsMemoryWrite(ins)) {
        struct PC writeItem;
        writeItem.refs = 0;
        writeItem.miss = 0;
        writeItem.pc = iaddr;
        writeItem.isLoad = 0;
        dCachePC.push_back(writeItem);
        UINT32 idx2 = dCachePC.size()-1;

         INS_InsertPredicatedCall(
                ins, IPOINT_BEFORE, (AFUNPTR) dCacheCount,
                IARG_ADDRINT,
                iaddr,
                IARG_MEMORYWRITE_EA,
                IARG_MEMORYWRITE_SIZE,
                IARG_UINT32,
                idx2,
                IARG_UINT32,
                0,
                IARG_UINT32,
                0,
                IARG_END);
    }

}
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);
}
Example #29
0
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);
}
Example #30
0
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);
    }
}