INT32 RecordRegisters(BBL bbl, UINT16 * stats) { INT32 count = 0; for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { const UINT32 max_r = INS_MaxNumRRegs(ins); for( UINT32 i=0; i < max_r; i++ ) { const REG reg = INS_RegR(ins, i ); if( REG_is_gr(reg) ) { stats[count++] = REG_GetStatsIndex(reg,FALSE); } #if 0 // This is for arm else if( REG_is_aggregate(reg) ) { REGSET regset = INS_RegAggregateR(ins); for( REG reg = REGSET_PopNext(regset); REG_valid(reg); reg = REGSET_PopNext(regset) ) { stats[count++] = REG_GetStatsIndex(reg,FALSE); } } #endif } const UINT32 max_w = INS_MaxNumWRegs(ins); for( UINT32 i=0; i < max_w; i++ ) { const REG reg = INS_RegW(ins, i ); if( REG_is_gr(reg) ) { stats[count++] = REG_GetStatsIndex(reg,TRUE); } #if 0 else if( REG_is_aggregate(reg) ) { REGSET regset = INS_RegAggregateW(ins); for( REG reg = REGSET_PopNext(regset); REG_valid(reg); reg = REGSET_PopNext(regset) ) { stats[count++] = REG_GetStatsIndex(reg,TRUE); } } #endif } } stats[count++] = 0; return count; }
/****************************************************************** Title:movzxRRHandler Function:Handler to handle instruction "movzx 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 movzxRRHandler(INS ins,int srcA,int srcB,int srcC,int dstA,int dstB,int dstC) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(movzxRRHook), IARG_UINT32, REG(INS_RegW(ins, 0)), REG(INS_RegR(ins, 0)), IARG_END); countAllIns++; countHandledIns++; return 0; }
// Pin calls this function every time a new instruction is encountered VOID Instruction(INS ins, VOID *v) { // Insert a call to updateSpacingInfo before every instruction. // You may need to add arguments to the call. INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_END); UINT32 regnum = INS_MaxNumWRegs(ins); UINT32 reg,i,j,flag; REG tmp; regn++; for(i=0; i<regnum; i++){ tmp=INS_RegW(ins, i); if(REG_is_partialreg(tmp)){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)updateSpacingInfoW,IARG_UINT32, (UINT32)REG_FullRegName(tmp), IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)updateSpacingInfoW,IARG_UINT32, (UINT32)tmp, IARG_END); } // if((UINT32)tmp==REG_EAX) printf("eax %u\n",tmp); // if((UINT32)tmp==REG_RBASE) printf("base %u\n",tmp); // if((UINT32)tmp== REG_ESI) printf("esi %u\n",tmp); if((UINT32)tmp==REG_AL || (UINT32)tmp==REG_AH) INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)updateSpacingInfoW,IARG_UINT32, (UINT32)REG_AX, IARG_END); else if((UINT32)tmp==REG_BL || (UINT32)tmp==REG_BH) INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)updateSpacingInfoW,IARG_UINT32, (UINT32)REG_BX, IARG_END); else if((UINT32)tmp==REG_CL || (UINT32)tmp==REG_CH) INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)updateSpacingInfoW,IARG_UINT32, (UINT32)REG_CX, IARG_END); else if((UINT32)tmp==REG_DL || (UINT32)tmp==REG_CH) INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)updateSpacingInfoW,IARG_UINT32, (UINT32)REG_DX, IARG_END); } regnum = INS_MaxNumRRegs(ins); for(i=0; i<regnum; i++){ reg=(UINT32)INS_RegR(ins, i); //if(reg>200 || reg<0) printf("Error2: reg=%u\n",reg); //reg=writereg[reg]; //if(reg>regn) printf("Error3\n"); //if(reg>0 && regn-reg < maxSize && reg<regn) dependancySpacing[regn-reg]++; flag=0; for(j=0;j<i;j++) if(readreg[j]==reg){flag=1;break;} if(flag==0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)updateSpacingInfoR, IARG_UINT32, reg, IARG_END); readreg[i]=reg; } else{ readreg[i]=-1; } } }
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); } }
VOID WriteShadows(INS ins, BOOL * live) { for (UINT32 i = 0; i < INS_MaxNumWRegs(ins); i++) { REG reg = INS_RegW(ins, i); if (!GpReg(reg)) continue; if (!live[RegIndex(reg)]) continue; // If this instruction writes a register that is used as a base register in // a memory operation later in the trace, then translate the address and // write it to a shadow register INS_InsertCall(ins, IPOINT_AFTER, AFUNPTR(ProcessAddress), IARG_REG_VALUE, reg, IARG_INST_PTR, IARG_RETURN_REGS, ShadowReg(reg), IARG_END); live[RegIndex(reg)] = false; } }
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); } } }
// Pin calls this function every time a new instruction is encountered VOID Instruction(INS ins, VOID *v) { const UINT32 max_r = INS_MaxNumRRegs(ins); for( UINT32 i=0; i < max_r; i++ ) { const REG reg = INS_RegR(ins, i ); if (reg==REG_STATUS_FLAGS || reg==REG_DF_FLAG) { printf ("Error encountered unexpected flag reg at ins: %s\n", INS_Disassemble(ins).c_str()); numFailures++; } else if (reg==REG_GFLAGS) { numFlagRegs++; } } const UINT32 max_w = INS_MaxNumWRegs(ins); for( UINT32 i=0; i < max_w; i++ ) { const REG reg = INS_RegW(ins, i ); if (reg==REG_STATUS_FLAGS || reg==REG_DF_FLAG) { printf ("Error encountered unexpected flag reg at ins: %s\n", INS_Disassemble(ins).c_str()); numFailures++; } else if (reg==REG_GFLAGS) { numFlagRegs++; } } }
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); } }
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); }