bool taintReg(REG reg) { if (checkAlreadyRegTainted(reg) == true){ std::cout << "\t\t\t" << REG_StringShort(reg) << " is already tainted" << std::endl; return false; } switch(reg){ case REG_RAX: regsTainted.push_front(REG_RAX); case REG_EAX: regsTainted.push_front(REG_EAX); case REG_AX: regsTainted.push_front(REG_AX); case REG_AH: regsTainted.push_front(REG_AH); case REG_AL: regsTainted.push_front(REG_AL); break; case REG_RBX: regsTainted.push_front(REG_RBX); case REG_EBX: regsTainted.push_front(REG_EBX); case REG_BX: regsTainted.push_front(REG_BX); case REG_BH: regsTainted.push_front(REG_BH); case REG_BL: regsTainted.push_front(REG_BL); break; case REG_RCX: regsTainted.push_front(REG_RCX); case REG_ECX: regsTainted.push_front(REG_ECX); case REG_CX: regsTainted.push_front(REG_CX); case REG_CH: regsTainted.push_front(REG_CH); case REG_CL: regsTainted.push_front(REG_CL); break; case REG_RDX: regsTainted.push_front(REG_RDX); case REG_EDX: regsTainted.push_front(REG_EDX); case REG_DX: regsTainted.push_front(REG_DX); case REG_DH: regsTainted.push_front(REG_DH); case REG_DL: regsTainted.push_front(REG_DL); break; case REG_RDI: regsTainted.push_front(REG_RDI); case REG_EDI: regsTainted.push_front(REG_EDI); case REG_DI: regsTainted.push_front(REG_DI); case REG_DIL: regsTainted.push_front(REG_DIL); break; case REG_RSI: regsTainted.push_front(REG_RSI); case REG_ESI: regsTainted.push_front(REG_ESI); case REG_SI: regsTainted.push_front(REG_SI); case REG_SIL: regsTainted.push_front(REG_SIL); break; default: std::cout << "\t\t\t" << REG_StringShort(reg) << " can't be tainted" << std::endl; return false; } std::cout << "\t\t\t" << REG_StringShort(reg) << " is now tainted" << std::endl; return true; }
PyObject* Python_REG_StringShort(PyObject* self, PyObject* args) { PyObject* reg; PyArg_ParseTuple(args, "L", ®); REG reg_object = *(REG*) reg; return Py_BuildValue("s", REG_StringShort(reg_object).c_str()); }
// Move from memory to register ADDRINT DoLoad(REG reg, ADDRINT * addr) { *out << "Emulate loading from addr " << addr << " to " << REG_StringShort(reg) << endl; ADDRINT value; PIN_SafeCopy(&value, addr, sizeof(ADDRINT)); return value; }
VOID spreadRegTaint(UINT32 insAddr, std::string insDis, UINT32 opCount, REG reg_r, REG reg_w) { if (opCount != 2) return; if (REG_valid(reg_w)){ if (checkAlreadyRegTainted(reg_w) && (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r))){ std::cout << "[SPREAD]\t\t" << insAddr << ": " << insDis << 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" << insAddr << ": " << insDis << std::endl; std::cout << "\t\t\toutput: " << REG_StringShort(reg_w) << " | input: "<< REG_StringShort(reg_r) << std::endl; taintReg(reg_w); } } }
uint32_t pintrace::GetTypeOfReg(REG r) { if (REG_is_gr8(r)) return VT_REG8; if (REG_is_gr16(r)) return VT_REG16; if (REG_is_gr32(r)) return VT_REG32; if (REG_is_gr64(r)) return VT_REG64; string s = REG_StringShort(r); if (s == "eip" || s == "eflags") { // No problem for these return VT_REG32; } else if (s == "rip" || s == "rflags") { // Likewise for the 64-bit registers return VT_REG64; } // Otherwise, print a warning... std::cerr << "Warning: Unknown register size of register " << REG_StringShort(r) << std::endl; return VT_NONE; }
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); } } }
bool removeRegTainted(REG reg) { switch(reg){ case REG_RAX: regsTainted.remove(REG_RAX); case REG_EAX: regsTainted.remove(REG_EAX); case REG_AX: regsTainted.remove(REG_AX); case REG_AH: regsTainted.remove(REG_AH); case REG_AL: regsTainted.remove(REG_AL); break; case REG_RBX: regsTainted.remove(REG_RBX); case REG_EBX: regsTainted.remove(REG_EBX); case REG_BX: regsTainted.remove(REG_BX); case REG_BH: regsTainted.remove(REG_BH); case REG_BL: regsTainted.remove(REG_BL); break; case REG_RCX: regsTainted.remove(REG_RCX); case REG_ECX: regsTainted.remove(REG_ECX); case REG_CX: regsTainted.remove(REG_CX); case REG_CH: regsTainted.remove(REG_CH); case REG_CL: regsTainted.remove(REG_CL); break; case REG_RDX: regsTainted.remove(REG_RDX); case REG_EDX: regsTainted.remove(REG_EDX); case REG_DX: regsTainted.remove(REG_DX); case REG_DH: regsTainted.remove(REG_DH); case REG_DL: regsTainted.remove(REG_DL); break; case REG_RDI: regsTainted.remove(REG_RDI); case REG_EDI: regsTainted.remove(REG_EDI); case REG_DI: regsTainted.remove(REG_DI); case REG_DIL: regsTainted.remove(REG_DIL); break; case REG_RSI: regsTainted.remove(REG_RSI); case REG_ESI: regsTainted.remove(REG_ESI); case REG_SI: regsTainted.remove(REG_SI); case REG_SIL: regsTainted.remove(REG_SIL); break; default: return false; } std::cout << "\t\t\t" << REG_StringShort(reg) << " is now freed" << std::endl; return true; }
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; }
static VOID LogInstruction( /* ADDRINT address, const char *disasm, */ const CONTEXT *ctxt) { REG regList[] = { REG_EDI, REG_ESI, REG_EBP, REG_ESP, REG_EBX, REG_EDX, REG_ECX, REG_EAX, REG_SEG_CS, REG_SEG_SS, REG_SEG_DS, REG_SEG_ES, REG_SEG_FS, REG_SEG_GS, REG_EFLAGS }; // fprintf(outFile, "%#lX :\t%s\t; {", address, disasm); for (unsigned i = 0; i < 15; i++) { REG reg = regList[i]; fprintf(outFile, "%s=%lx ", REG_StringShort(reg).c_str(), PIN_GetContextReg(ctxt, reg) ); } fprintf(outFile, "}\n"); fflush(outFile); }
VOID Fini(int, VOID * v) { ComputeGlobalStats(); *out << "#\n" "#num reg count-read count-written\n" "#\n"; for ( UINT32 i = 0; i < MAX_REG; i++) { if( GlobalStats.reg_w[i] == 0 && GlobalStats.reg_r[i] == 0 ) continue; *out << decstr(i,3) << " " << ljstr(REG_StringShort(REG(i)),15) << decstr( GlobalStats.reg_r[i],12) << decstr( GlobalStats.reg_w[i],12) << endl; } *out << "# eof" << endl; out->close(); }
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); } }
// Move from memory to register ADDRINT DoLoad(REG reg, ADDRINT * addr) { cout << "Emulate loading from addr " << addr << " to " << REG_StringShort(reg) << endl; return *addr; }
static inline void PrintRegval(REG reg, const REGVAL * regval, ostream& ost) { ost << REG_StringShort(reg) << " = "; PrintRawValue(regval, ost); }