Exemple #1
0
/**
* Converts a PIN instruction object into a disassembled string.
**/
std::string dumpInstruction(INS ins)
{
	std::stringstream ss;

	ADDRINT address = INS_Address(ins);

	// Generate address and module information
	ss << "0x" << setfill('0') << setw(8) << uppercase << hex << address << "::" << getModule(address) << "  ";

	// Generate instruction byte encoding
	for (int i=0;i<INS_Size(ins);i++)
	{
		ss << setfill('0') << setw(2) << (((unsigned int) *(unsigned char*)(address + i)) & 0xFF) << " ";
	}

	for (int i=INS_Size(ins);i<8;i++)
	{
		ss << "   ";
	}

	// Generate diassembled string
	ss << INS_Disassemble(ins);
	
	// Look up call information for direct calls
	if (INS_IsCall(ins) && INS_IsDirectBranchOrCall(ins))
	{
		ss << " -> " << RTN_FindNameByAddress(INS_DirectBranchOrCallTargetAddress(ins));
	}

	return ss.str();
}
VOID PolymorphicCodeHandlerModule::inspectTrace(TRACE trace){
	// set the range of address in which the current trace resides
	this->trace_head = TRACE_Address(trace);
	this->trace_tail = trace_head + TRACE_Size(trace);
	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))
        {	
			// for ech instruction we have to check if it has been overwritten by a previous instruction of the current trace (polimiorfic code detection)
			INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(checkIfWrittenAddress), 
				IARG_INST_PTR, 
				IARG_CONTEXT, 
				IARG_UINT32, INS_Size(ins), 
				IARG_PTR, this,
				IARG_END);				
			for (UINT32 op = 0; op<INS_MemoryOperandCount(ins); op++) {
				if(INS_MemoryOperandIsWritten(ins,op)){	
					// for each write operation we have to check if the traget address is inside the current trace (attempt to write polimorfic code)
					INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(polimorficCodeHandler),
						IARG_INST_PTR,
						IARG_MEMORYOP_EA, op,
						IARG_PTR, this,
						IARG_END);		
				}	
			}					
        }
    }
}
Exemple #3
0
// record the page(s) occupied by the instruction
VOID SANDBOX::RecordIns(INS ins)
{
    const ADDRINT beginAddr = INS_Address(ins);
    const ADDRINT endAddr = beginAddr + INS_Size(ins) - 1;

    RecordAddressRange(reinterpret_cast<const char *>(beginAddr), reinterpret_cast<const char *>(endAddr));
}
Exemple #4
0
VOID Trace(TRACE trace, VOID *v)
{
    const INS beginIns = BBL_InsHead(TRACE_BblHead(trace));
    const INS endIns = BBL_InsTail(TRACE_BblTail(trace));
    const ADDRINT beginAddr = INS_Address(beginIns);
    const ADDRINT endAddr = INS_Address(endIns) + INS_Size(endIns) - 1;

    sandbox.CheckAddressRange(reinterpret_cast<const char *>(beginAddr), reinterpret_cast<const char *>(endAddr));
}
// Insert a direct branch over the first mov immediate
static VOID insertJump (RTN rtn)
{
    for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins))
    {
        if (INS_IsMov(ins) && INS_HasImmediateOperand(ins))
        {
            INS_InsertDirectJump(ins, IPOINT_BEFORE, INS_Address(ins) + INS_Size(ins));
            instrumentationCount++;
            return;
        }
    }
}
Exemple #6
0
const char *
dumpInstruction(INS ins)
{
	ADDRINT address = INS_Address(ins);
	std::stringstream ss;

	// Generate instruction byte encoding
	for (size_t i=0;i<INS_Size(ins);i++)
	{
		ss << setfill('0') << setw(2) << hex << (((unsigned int) *(unsigned char*)(address + i)) & 0xFF) << " ";
	}

	for (size_t i=INS_Size(ins);i<8;i++)
	{
		ss << "   ";
	}

	// Generate diassembled string
	ss << INS_Disassemble(ins);

	return strdup(ss.str().c_str());
}
VOID Instruction(INS ins, VOID *v)
{

    ADDRINT nextAddr   = INS_NextAddress(ins);
    UINT32 maxRRegs    = INS_MaxNumRRegs(ins);
    UINT32 maxWRegs    = INS_MaxNumWRegs(ins);
    USIZE  sz          = INS_Size(ins);
    
    INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordFirstInstructionInfo,
                   IARG_THREAD_ID,
                   IARG_INST_PTR,
                   IARG_ADDRINT, nextAddr,
                   IARG_UINT32, maxRRegs,
                   IARG_UINT32, maxWRegs,
                   IARG_ADDRINT, sz,
                   IARG_UINT32, 'r', IARG_END);
}
// Insert an indirect branch over the first mov immediate
static VOID insertIndirectJump (RTN rtn)
{
    for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins))
    {
        if (INS_IsMov(ins) && INS_HasImmediateOperand(ins))
        {
            INS_InsertCall(ins, IPOINT_BEFORE,
                           AFUNPTR(returnValue),
                           IARG_ADDRINT, INS_Address(ins) + INS_Size(ins),
                           IARG_RETURN_REGS, scratchReg, IARG_END);

            INS_InsertIndirectJump(ins, IPOINT_BEFORE, scratchReg);
            instrumentationCount++;
            return;
        }
    }
}
VOID Trace(TRACE trace, VOID *v)
{
    // Instrument only at the head of the trace
    BBL bbl = TRACE_BblHead(trace);
    
    if (BBL_Valid(bbl))
    {
        INS_InsertCall(BBL_InsHead(bbl), IPOINT_BEFORE, (AFUNPTR)docount, IARG_UINT32, 1, IARG_END);
    }

    for (bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl))
    {
        for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins))
        {
            ASSERTX(INS_Size(ins) != 0);
        }
    }

}
Exemple #10
0
int main(INT32 argc, CHAR **argv)
{
    PIN_InitSymbols();

    if( PIN_Init(argc,argv) )
    {
        return Usage();
    }
    
    IMG img = IMG_Open(KnobInputFile);

    if (!IMG_Valid(img))
    {
        std::cout << "Could not open " << KnobInputFile.Value() << endl;
        exit(1);
    }
    
    std::cout << hex;
    rtnInternalRangeList.clear();

    for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec))
    {
        std::cout << "Section: " << setw(8) << SEC_Address(sec) << " " << SEC_Name(sec) << endl;
                
        for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn))
        {
            std::cout << "  Rtn: " << setw(8) << hex << RTN_Address(rtn) << " " << RTN_Name(rtn) << endl;
            string path;
            INT32 line;
            PIN_GetSourceLocation(RTN_Address(rtn), NULL, &line, &path);

            if (path != "")
            {
                std::cout << "File " << path << " Line " << line << endl; 
            }

            RTN_Open(rtn);
           
            if (!INS_Valid(RTN_InsHead(rtn)))
            {
                RTN_Close(rtn);
                continue;
            }
 
            RTN_INTERNAL_RANGE rtnInternalRange;
            rtnInternalRange.start = INS_Address(RTN_InsHead(rtn));
            rtnInternalRange.end 
              = INS_Address(RTN_InsHead(rtn)) + INS_Size(RTN_InsHead(rtn));
            INS lastIns = INS_Invalid();
            for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins))
            {
                std::cout << "    " << setw(8) << hex << INS_Address(ins) << " " << INS_Disassemble(ins) << endl;
                if (INS_Valid(lastIns))
                {
                    if ((INS_Address(lastIns) + INS_Size(lastIns)) == INS_Address(ins))
                    {
                        rtnInternalRange.end = INS_Address(ins)+INS_Size(ins);
                    }
                    else
                    { 
                        rtnInternalRangeList.push_back(rtnInternalRange);
                        std::cout << "  rtnInternalRangeList.push_back " << setw(8) << hex << rtnInternalRange.start << " " << setw(8) << hex << rtnInternalRange.end << endl;
                        // make sure this ins has not already appeared in this RTN
                        for (vector<RTN_INTERNAL_RANGE>::iterator ri = rtnInternalRangeList.begin(); ri != rtnInternalRangeList.end(); ri++)
                        {
                            if ((INS_Address(ins) >= ri->start) && (INS_Address(ins)<ri->end))
                            {
                                std::cout << "***Error - above instruction already appeared in this RTN\n";
                                std::cout << "  in rtnInternalRangeList " << setw(8) << hex << ri->start << " " << setw(8) << hex << ri->end << endl;
                                exit (1);
                            }
                        }
                        rtnInternalRange.start = INS_Address(ins);
                        rtnInternalRange.end = INS_Address(ins) + INS_Size(ins);
                    }
                }
                lastIns = ins;
            }

            RTN_Close(rtn);
            rtnInternalRangeList.clear();
        }
    }
    IMG_Close(img);
}
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);
    }
    

}
Exemple #12
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);
          }

        }
      }
    }
instruction::instruction(const INS& ins)
{
  this->address     = INS_Address(ins);
  this->next_address = INS_NextAddress(ins);

//  this->opcode      = INS_Mnemonic(ins);
  this->opcode_size = static_cast<uint8_t>(INS_Size(ins));
  this->opcode_buffer = std::shared_ptr<uint8_t>(new uint8_t[this->opcode_size], std::default_delete<uint8_t[]>());
  PIN_SafeCopy(opcode_buffer.get(), reinterpret_cast<const VOID*>(this->address), this->opcode_size);

  this->disassemble = INS_Disassemble(ins);

  // including image, routine
  auto img                = IMG_FindByAddress(this->address);
  this->including_image   = IMG_Valid(img) ? IMG_Name(img) : "";
//  this->including_routine = RTN_FindNameByAddress(this->address);

  PIN_LockClient();
  auto routine = RTN_FindByAddress(this->address);
  PIN_UnlockClient();

  if (RTN_Valid(routine)) {
    auto routine_mangled_name = RTN_Name(routine);
    this->including_routine_name = PIN_UndecorateSymbolName(routine_mangled_name, UNDECORATION_NAME_ONLY);
  }
  else this->including_routine_name = "";

  // has fall through
  this->has_fall_through = INS_HasFallThrough(ins);

  // is call, ret or syscall
  this->is_call    = INS_IsCall(ins);
  this->is_branch  = INS_IsBranch(ins);
  this->is_ret     = INS_IsRet(ins);
  this->is_syscall = INS_IsSyscall(ins);

  this->category = static_cast<xed_category_enum_t>(INS_Category(ins));
  this->iclass = static_cast<xed_iclass_enum_t>(INS_Opcode(ins));

  // read registers
  auto read_reg_number = INS_MaxNumRRegs(ins);
  for (decltype(read_reg_number) reg_id = 0; reg_id < read_reg_number; ++reg_id) {
    this->src_registers.push_back(INS_RegR(ins, reg_id));
  }

  // written registers
  auto written_reg_number = INS_MaxNumWRegs(ins);
  for (decltype(written_reg_number) reg_id = 0; reg_id < written_reg_number; ++reg_id) {
    this->dst_registers.push_back(INS_RegW(ins, reg_id));
  }

  auto is_special_reg = [](const REG& reg) -> bool {
    return (reg >= REG_MM_BASE);
  };

  this->is_special =
      std::any_of(std::begin(this->src_registers), std::end(this->src_registers), is_special_reg) ||
      std::any_of(std::begin(this->dst_registers), std::end(this->dst_registers), is_special_reg) ||
      (this->category == XED_CATEGORY_X87_ALU) || (this->iclass == XED_ICLASS_XEND) || (this->category == XED_CATEGORY_LOGICAL_FP) ||
      (this->iclass == XED_ICLASS_PUSHA) || (this->iclass == XED_ICLASS_PUSHAD) || (this->iclass == XED_ICLASS_PUSHF) ||
      (this->iclass == XED_ICLASS_PUSHFD) || (this->iclass == XED_ICLASS_PUSHFQ);


  // is memory read, write
  this->is_memory_read  = INS_IsMemoryRead(ins);
  this->is_memory_write = INS_IsMemoryWrite(ins);
  this->is_memory_read2 = INS_HasMemoryRead2(ins);
}
VOID Instruction(INS ins, VOID *v)
{

    ADDRINT nextAddr   = INS_NextAddress(ins);
    UINT32 maxRRegs    = INS_MaxNumRRegs(ins);
    UINT32 maxWRegs    = INS_MaxNumWRegs(ins);
    ADDRINT  sz        = INS_Size(ins);





    if (numContextsInstrumented < 100)
    {
        numContextsInstrumented++;
        INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordContext,
                       // 4 dummy params to get the real params to be pushed on the stack in Intel64
                       IARG_UINT32, 1, IARG_UINT32, 2, IARG_UINT32, 3, IARG_UINT32, 4,
                       IARG_CONTEXT,
                       IARG_END);
        INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordContextFastCall,
                       IARG_FAST_ANALYSIS_CALL,
                       IARG_CONTEXT,
                       IARG_END);
        INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)VerifyContext,
                       IARG_INST_PTR,
                       IARG_CONTEXT,
                       IARG_END);
    }
    else if (numRegularInstrumented < 100)
    {
        numRegularInstrumented++;
        INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordInstructionInfoFastCall,
                   IARG_FAST_ANALYSIS_CALL,
                   IARG_THREAD_ID,
                   IARG_INST_PTR,
                   IARG_REG_VALUE, REG_GFLAGS,
                   IARG_ADDRINT, nextAddr,
                   IARG_UINT32, maxRRegs,
                   IARG_UINT32, maxWRegs,
                   IARG_ADDRINT, sz,
#ifdef TARGET_IA32E
                   IARG_ADDRINT, 0xdeadbeefdeadbeefLL,
#else
                   IARG_ADDRINT, 0xdeadbeef,
#endif
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_END);

        INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordInstructionInfo,
                   // 4 dummy params to get the real params to be pushed on the stack in Intel64
                   IARG_UINT32, 1, IARG_UINT32, 2, IARG_UINT32, 3, IARG_UINT32, 4,
                   IARG_THREAD_ID,
                   IARG_INST_PTR,
                   IARG_REG_VALUE, REG_GFLAGS,
                   IARG_ADDRINT, nextAddr,
                   IARG_UINT32, maxRRegs,
                   IARG_UINT32, maxWRegs,
                   IARG_ADDRINT, sz,
#ifdef TARGET_IA32E
                   IARG_ADDRINT, 0xdeadbeefdeadbeefLL,
#else
                   IARG_ADDRINT, 0xdeadbeef,
#endif
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_END);



        INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)VerifyInstructionInfo,
                   IARG_THREAD_ID,
                   IARG_INST_PTR,
                   IARG_REG_VALUE, REG_GFLAGS,
                   IARG_ADDRINT, nextAddr,
                   IARG_UINT32, maxRRegs,
                   IARG_UINT32, maxWRegs,
                   IARG_ADDRINT, sz,
#ifdef TARGET_IA32E
                   IARG_ADDRINT, 0xdeadbeefdeadbeefLL,
#else
                   IARG_ADDRINT, 0xdeadbeef, 
#endif
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_REG_VALUE, REG_GDX,
                   IARG_END);
    }

}