如何用Intel Pin获取无符号信息可执行文件中自定义函数的读写内存值
Got it, let's break down how to solve this problem. Since your executable lacks symbol information, we can't rely on Intel Pin's routine-level instrumentation to target getSum directly. Instead, we'll use instruction-level instrumentation paired with manual address range tracking to isolate the instructions belonging to your custom function. Here's a step-by-step approach:
1. Identify the Instruction Range of getSum
First, you need to pinpoint the start and end virtual addresses of the getSum function. Use a disassembler tool like objdump or IDA Pro to analyze your executable:
- Run
objdump -d your_executable > disasm.txtto generate a full disassembly of the binary. - Search for the assembly logic matching
getSum(look for the loop that incrementsifrom 1 to 10 and adds it to a sum variable). - Note down the start address (the first instruction of the function) and end address (the address immediately after the function's
retinstruction).
2. Build a Pin Tool with Address-Range Filtering
We'll create a Pin tool that tracks whether the current executing instruction falls within getSum's address range. When it does, we'll instrument memory read/write operations to log their values.
Here's a sample Pin tool implementation (C++):
#include "pin.H" #include <fstream> #include <iostream> // Replace these with the actual start/end addresses of getSum from your disassembly ADDRINT g_getSum_start = 0x00401000; ADDRINT g_getSum_end = 0x00401030; std::ofstream trace_file; // Flag to track if we're executing inside getSum bool g_in_getSum = false; // Callback to update the in-function flag before each instruction runs VOID InstructionEntry(ADDRINT addr) { g_in_getSum = (addr >= g_getSum_start && addr < g_getSum_end); } // Callback to log memory read operations VOID LogMemRead(ADDRINT addr, UINT32 size) { if (g_in_getSum) { // Read and log the value based on memory size switch(size) { case 1: trace_file << "[READ] Address: 0x" << std::hex << addr << " Value: 0x" << static_cast<UINT32>(*reinterpret_cast<UINT8*>(addr)) << std::endl; break; case 4: trace_file << "[READ] Address: 0x" << std::hex << addr << " Value: 0x" << *reinterpret_cast<UINT32*>(addr) << std::endl; break; // Add cases for 2-byte, 8-byte operations if needed } } } // Callback to log memory write operations VOID LogMemWrite(ADDRINT addr, UINT32 size, ADDRINT value) { if (g_in_getSum) { trace_file << "[WRITE] Address: 0x" << std::hex << addr << " Value: 0x" << value << " Size: " << std::dec << size << std::endl; } } // Core instrumentation routine VOID Instruction(INS ins, VOID *v) { // Check if we're entering getSum before each instruction INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)InstructionEntry, IARG_INST_PTR, IARG_END); // Instrument memory reads if (INS_IsMemoryRead(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)LogMemRead, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_END); } // Instrument memory writes if (INS_IsMemoryWrite(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)LogMemWrite, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_MEMORYWRITE_VALUE, IARG_END); } } // Tool usage help INT32 Usage() { std::cerr << "Usage: pin -t <tool.so> -- <your_executable>" << std::endl; return -1; } int main(int argc, char *argv[]) { if (PIN_Init(argc, argv)) return Usage(); trace_file.open("mem_trace.log"); if (!trace_file.is_open()) { std::cerr << "Failed to open trace file!" << std::endl; return -1; } INS_AddInstrumentFunction(Instruction, 0); PIN_StartProgram(); trace_file.close(); return 0; }
3. Key Details Explained
- Address Range Check: The
InstructionEntrycallback runs before every instruction, updating theg_in_getSumflag to track whether we're inside the target function's boundaries. - Memory Logging: We use Pin's built-in APIs (
INS_IsMemoryRead/INS_IsMemoryWrite) to detect memory operations. For reads, we fetch the value directly from memory; for writes, Pin provides the value being written viaIARG_MEMORYWRITE_VALUE. - Size Handling: The code handles 1-byte and 4-byte operations (matching the
intvariables ingetSum). Extend this to other sizes if your function uses different data types.
4. Compile and Run the Tool
- Compile the Pin tool using the Pin SDK's
makeutility (follow Intel's official build instructions for your OS). - Run it with your executable:
pin -t your_tool.so -- path/to/your_executable - Check the
mem_trace.logfile for the memory operations logged from withingetSum.
Important Notes
- If your executable uses ASLR (Address Space Layout Randomization), disable it first (e.g.,
setarch $(uname -m) -R ./your_executableon Linux) to ensure the disassembly addresses match runtime addresses. - For complex functions, double-check the address range to exclude inline functions or shared library calls nested inside
getSum.
内容的提问来源于stack exchange,提问作者wentaolu

