VOID Image(IMG img, VOID *v) { // Walk through the symbols in the symbol table. // for (SYM sym = IMG_RegsymHead(img); SYM_Valid(sym); sym = SYM_Next(sym)) { string undFuncName = PIN_UndecorateSymbolName(SYM_Name(sym), UNDECORATION_NAME_ONLY); // Find the RtlAllocHeap() function. if (undFuncName == "RtlAllocateHeap") { RTN allocRtn = RTN_FindByAddress(IMG_LowAddress(img) + SYM_Value(sym)); if (RTN_Valid(allocRtn)) { // Instrument to print the input argument value and the return value. RTN_Open(allocRtn); RTN_InsertCall(allocRtn, IPOINT_BEFORE, (AFUNPTR)Before, IARG_ADDRINT, "RtlAllocateHeap", IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_FUNCARG_ENTRYPOINT_VALUE, 2, IARG_END); RTN_InsertCall(allocRtn, IPOINT_AFTER, (AFUNPTR)After, IARG_ADDRINT, "RtlAllocateHeap", IARG_FUNCRET_EXITPOINT_VALUE, IARG_END); RTN_Close(allocRtn); } } } }
BaseIRBuilder::BaseIRBuilder(__uint address, const std::string &dis) { RTN rtn; SEC sec; IMG img; this->address = address; this->branchTaken = false; this->branchTargetAddress = 0; this->disas = dis; this->needSetup = false; this->nextAddress = 0; this->imageName = "unknown"; this->sectionName = "unknown"; rtn = RTN_FindByAddress(address); if (RTN_Valid(rtn)) { sec = RTN_Sec(rtn); if (SEC_Valid(sec)) { this->sectionName = SEC_Name(sec); img = SEC_Img(sec); if (IMG_Valid(img)) { this->baseAddress = IMG_LowAddress(img); this->imageName = IMG_Name(img); } } } this->offset = this->address - this->baseAddress; this->routineName = RTN_FindNameByAddress(address); if (this->routineName.empty()) this->routineName = "unknown"; }
PyObject* Python_RTN_FindByAddress(PyObject* self, PyObject* args) { PyObject* address; PyArg_ParseTuple(args, "L", &address); ADDRINT address_object = (ADDRINT) address; RTN* rtn_return = (RTN*) malloc(sizeof(RTN)); *rtn_return = RTN_FindByAddress(address_object); return Py_BuildValue("L", rtn_return); }
std::string getRoutineName(triton::__uint address) { RTN rtn; PIN_LockClient(); rtn = RTN_FindByAddress(address); PIN_UnlockClient(); if (RTN_Valid(rtn)) { return RTN_Name(rtn); } return ""; }
// Pin calls this function every time a new img is loaded VOID ImageLoad(IMG img, VOID *v) { if (!IMG_IsMainExecutable(img)) return; printf("%s loaded\n", IMG_Name(img).c_str()); fflush(stdout); ADDRINT imageBase = IMG_LowAddress(img); WINDOWS::PIMAGE_DATA_DIRECTORY pExpDir = GetExportDirectory(imageBase); if ((pExpDir == 0) || (pExpDir->Size == 0)) { // Failure: Executable image lacks export directory. printf("ERROR: No export directory in executable image\n"); fflush(stdout); exit(3); } ADDRINT exportBase = imageBase + pExpDir->VirtualAddress; // First check that bytes in export directory range do not belong to a RTN for (ADDRINT addr = exportBase; addr < exportBase + pExpDir->Size; ++addr) { if (RTN_FindByAddress(addr) != RTN_Invalid()) { // Test failure. Byte in export directory belongs to a RTN. printf("ERROR: Data from export directory included in RTN\n"); fflush(stdout); exit(1); } } // Second check RTN size. RTN range should not overlap with export directory range. for (SEC sec = IMG_SecHead(img); sec != SEC_Invalid(); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); rtn != RTN_Invalid(); rtn = RTN_Next(rtn)) { if (((RTN_Address(rtn) <= exportBase) && (RTN_Address(rtn) + RTN_Size(rtn) > exportBase)) || ((RTN_Address(rtn) > exportBase) && (exportBase + pExpDir->Size > RTN_Address(rtn)))) { // Test failure. RTN overlaps with export directory. printf("ERROR: RTN overlaps with export directory\n"); fflush(stdout); exit(2); } } } return; }
// ------------------------------------------------------------- // Get function address by branch target address // ------------------------------------------------------------- ADDRINT Target2FunAddr(ADDRINT target) { PIN_LockClient(); ADDRINT funAddr; const RTN rtn = RTN_FindByAddress(target); if ( RTN_Valid(rtn) ) funAddr = RTN_Address(rtn); else funAddr = target; PIN_UnlockClient(); return funAddr; }
// ------------------------------------------------------------- // STool_LibraryIDByAddr // ------------------------------------------------------------- // Return ID of the library of the routine to which the instruction // at address rtnAddr belongs, or STool_INVALID_LIB, if rtnAddr does not belong to // any routine. UINT32 STool_LibraryIDByAddr(ADDRINT rtnAddr){ PIN_LockClient(); const RTN rtn = RTN_FindByAddress(rtnAddr); UINT32 libID; if( RTN_Valid(rtn) ) libID = IMG_Id(SEC_Img(RTN_Sec(rtn))); else libID = STool_INVALID_LIB; PIN_UnlockClient(); return libID; }
std::string getImageName(triton::__uint address) { RTN rtn; SEC sec; IMG img; PIN_LockClient(); rtn = RTN_FindByAddress(address); PIN_UnlockClient(); if (RTN_Valid(rtn)) { sec = RTN_Sec(rtn); if (SEC_Valid(sec)) { img = SEC_Img(sec); if (IMG_Valid(img)) { return IMG_Name(img); } } } return ""; }
triton::__uint getBaseAddress(triton::__uint address) { RTN rtn; SEC sec; IMG img; PIN_LockClient(); rtn = RTN_FindByAddress(address); PIN_UnlockClient(); if (RTN_Valid(rtn)) { sec = RTN_Sec(rtn); if (SEC_Valid(sec)) { img = SEC_Img(sec); if (IMG_Valid(img)) { return IMG_LowAddress(img); } } } return 0; }
RTN FindRTN(IMG img, const char *func_name) { RTN rtn = RTN_FindByName(img, func_name); if (RTN_Valid(rtn)) return rtn; // handle those symbols with version numbers. // e.g. pthread_create has global name: pthread_create@@GLIBC... std::string func_name_v(func_name); func_name_v.append("@@"); for(SYM sym = IMG_RegsymHead(img); SYM_Valid(sym); sym = SYM_Next(sym)) { if (SYM_Name(sym).find(func_name_v) != std::string::npos) { RTN rtn = RTN_FindByAddress(SYM_Address(sym)); DEBUG_ASSERT(RTN_Valid(rtn)); return rtn; } } return RTN_Invalid(); }
static VOID tpss_on_module_loading(IMG img, VOID *data) { unsigned long origAttrs = 0; if (IMG_Valid(img)) { if (IMG_IsMainExecutable(img)) { g_tpss_entry_point = (void(*)())RTN_ReplaceProbed( RTN_FindByAddress(IMG_Entry(img)), (AFUNPTR)tpss_mainStartup); } else { tpss_instrument_module(img, data); } } }
const string& Target2LibName(ADDRINT target) { PIN_LockClient(); const RTN rtn = RTN_FindByAddress(target); static const string _invalid_rtn("[Unknown image]"); string name; if( RTN_Valid(rtn) ) { name = IMG_Name(SEC_Img(RTN_Sec(rtn))); } else { name = _invalid_rtn; } PIN_UnlockClient(); return *new string(name); }
// This function is called whenever Pin wants to report a breakpoint event to the // debugger. // static BOOL InterceptBreakpoint(THREADID tid, DEBUGGING_EVENT eventType, CONTEXT *ctxt, VOID *) { if (eventType != DEBUGGING_EVENT_BREAKPOINT) { std::cout << "FAILURE: Wrong event type in InterceptBreakpoint()" << std::endl; std::exit(1); } ADDRINT pc = PIN_GetContextReg(ctxt, REG_INST_PTR); RTN rtn = RTN_FindByAddress(pc); // When the application triggers the breakpoint in Breakpoint1(), squash the breakpoint // and roll the application back to the Checkpoint() call. The application will NOT stop // at the breakpoint, and it will immediately resume from Checkpoint(). // if (rtn != RTN_Invalid() && RTN_Name(rtn) == "Breakpoint1") { std::cout << "Intercepting breakpoint #1 at 0x" << std::hex << pc << std::endl; PIN_SaveContext(&SavedContext, ctxt); PIN_SetContextReg(ctxt, REG_GAX, 1); MemLog.Restore(); IsCheckpointing = FALSE; return FALSE; } // When the application triggers the breakpoint in Breakpoint2(), do not squash the // breakpoint, but change the return value from Breakpoint2(). The application will stop // in the debugger, and the debugger should see the modified return value. // if (rtn != RTN_Invalid() && (RTN_Name(rtn) == "Breakpoint2" || RTN_Name(rtn) == "Breakpoint2Label")) { std::cout << "Intercepting breakpoint #2 at 0x" << std::hex << pc << std::endl; std::cout << "RTN=" << RTN_Name(rtn) << std::endl; PIN_SetContextReg(ctxt, REG_GAX, 1); return TRUE; } std::cout << "Skipping breakpoint at 0x" << std::hex << pc << ", RTN=" << RTN_Name(rtn) << std::endl; return TRUE; }
int rtn_find_by_address (lua_State *L) { ADDRINT v1 = lua_tonumber(L,1); RTN_to_lua(L, RTN_FindByAddress(v1)); return 1; }
VOID PrintUntouchedRanges(SEC sec) { // Make a bool vector big enough to describe the whole section, 1 bool per byte vector<bool> touched(SEC_Size(sec)); // Put the rtn's that are touched in a set set<RTN> rtnSet; // Mark the ranges for bbls that have been executed for (list<const BBLSTATS*>::const_iterator bi = statsList.begin(); bi != statsList.end(); bi++) { const BBLSTATS * stats = *bi; // Is this bbl contained in the section? if (stats->_start < SEC_Address(sec) || stats->_start >= SEC_Address(sec) + SEC_Size(sec)) continue; // Is the bbl executed? if (!stats->_executed) continue; RTN rtn = RTN_FindByAddress(stats->_start); if (RTN_Valid(rtn)) rtnSet.insert(rtn); // Mark all the bytes of the bbl as executed for (ADDRINT i = stats->_start - SEC_Address(sec); i < stats->_start + stats->_size - SEC_Address(sec); i++) { ASSERTX(i < SEC_Size(sec)); touched[i] = true; } } // Print the routines that are not touched out << " Routines that are not executed" << endl; for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { if (rtnSet.find(rtn) == rtnSet.end()) { out << " " << RTN_Name(rtn) << endl; } } // Print the ranges of untouched addresses out << " Code ranges that are not executed" << endl; string rtnName = ""; for (UINT32 i = 0; i < SEC_Size(sec);) { // Find the first not touched address while(touched[i]) { i++; if (i == SEC_Size(sec)) return; } UINT32 start = i; // Find the first touched address while(!touched[i] && i < SEC_Size(sec)) i++; ADDRINT startAddress = SEC_Address(sec) + start; // Print the rtn name, if it has changed IMG img = IMG_FindByAddress(startAddress); string imgName = (IMG_Valid(img) ? IMG_Name(img) : "InvalidImg"); RTN rtn = RTN_FindByAddress(startAddress); string newName = (RTN_Valid(rtn) ? RTN_Name(rtn) : "InvalidRtn"); if (rtnName != newName) { out << " Image: " << imgName << " Rtn: " << newName << endl; rtnName = newName; } out << " " << SEC_Address(sec) + start << ":" << SEC_Address(sec) + i - 1 << endl; } }
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); }