如何通过Intel PIN Instrumentation获取libc函数的真实例程名称?
解决Intel PIN无法解析PLT条目到真实libc函数名的问题
问题背景
使用Intel PIN插桩追踪libc函数(如scanf)时,发现程序中调用scanf的指令实际指向进程的PLT条目(如__isoc99_scanf@plt),但PIN返回的名称却是.plt.sec,无法获取真实的libc函数名。
代码示例
测试二进制源码(test.c)
#include <stdio.h> #include <stdlib.h> void foo(char *buffer) { scanf("%s", buffer); printf("Unsafe gets: %s\n", buffer); } int main() { char *buf = malloc(sizeof(char)*50); foo(buf); return 0; }
原始Intel PIN插桩源码
VOID do_call(ADDRINT addr) { printf("%p - %s\n", (void*)addr, RTN_FindNameByAddress(addr).c_str()); } VOID Instruction(INS ins, VOID *v) { if (INS_IsCall(ins)) { if (INS_IsDirectBranchOrCall(ins)) { const ADDRINT addr = INS_DirectBranchOrCallTargetAddress(ins); INS_InsertPredicatedCall(ins, IPOINT_BEFORE, AFUNPTR(do_call), IARG_PTR, addr, IARG_END); } } } int main(int argc, char **argv) { PIN_InitSymbols(); if (unlikely(PIN_Init(argc, argv))) goto err; INS_AddInstrumentFunction(Instruction, 0); PIN_StartProgram(); return EXIT_SUCCESS; err: return EXIT_FAILURE; }
解决方案
问题根源是:程序调用libc函数时会先跳转至自身的PLT(过程链接表)条目,RTN_FindNameByAddress默认返回PLT节的名称而非对应的外部符号名。我们需要在获取名称时,对PLT地址做额外处理,查找对应的真实符号。
修改do_call函数,添加PLT地址的符号解析逻辑:
#include <string> VOID do_call(ADDRINT addr) { std::string funcName = RTN_FindNameByAddress(addr); // 判断是否为PLT相关地址,尝试解析真实符号 if (funcName.find(".plt") != std::string::npos) { SYM sym = SYM_FindByAddress(addr); if (SYM_Valid(sym)) { funcName = SYM_Name(sym); } } printf("%p - %s\n", (void*)addr, funcName.c_str()); }
关键说明
SYM_FindByAddress:该函数可以根据地址查找对应的符号,对于PLT条目,它会关联到对应的外部libc函数符号。- 符号有效性检查:使用
SYM_Valid确保找到的符号是合法的,避免空指针或无效名称。 - 头文件依赖:需要包含
<string>头文件以处理字符串操作。
运行效果
修改后重新编译PIN插桩库并运行,输出中会显示:
... 0x55a6dcbb8189 - foo 0x55a6dcbb8090 - __isoc99_scanf ...
此时PLT地址对应的真实libc函数名__isoc99_scanf会被正确解析输出。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

