You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Intel Pin无法检测memcmp与strcmp函数的技术求助

解决Pintool无法捕获memcmp/strcmp的问题

这问题我之前排查过,大概率是编译器优化或PLT调用机制导致的,给你拆解下原因和解决方案:

核心原因分析

1. 编译器内联优化

现代GCC/Clang这类编译器会对memcmp/strcmp这类高频小函数做内联优化——直接把函数逻辑展开到调用代码里,不会生成单独的函数调用指令。比如你写的简单字符串比较代码,编译器完全可以把memcmp替换成逐字节比较的指令,根本不会去调用标准库的memcmp函数,你的Pintool自然追踪不到。

2. PLT条目未被枚举

如果确实调用了标准库版本的memcmp/strcmp,它们通常是通过PLT(Procedure Linkage Table) 间接调用的。你的枚举代码遍历的是镜像的普通段(SEC)里的例程(RTN),但PLT的特殊条目不会被当成常规RTN处理,所以遍历过程会漏掉它们。

解决方案

方案一:强制编译器关闭内联优化

编译测试程序时,添加编译选项禁用内联,让编译器强制调用标准库的memcmp/strcmp:

gcc test.c -o test -fno-builtin-memcmp -fno-builtin-strcmp

这样Pintool就能捕获到标准库函数的调用了。

方案二:直接查找目标函数(推荐)

不要遍历所有段和例程,改用RTN_FindByName直接定位目标函数,不管它在主程序还是动态库中:

#include "pin.H"
#include <stdio.h>

VOID MemcmpBefore(ADDRINT str1, ADDRINT str2, ADDRINT len) {
    printf("memcmp called, length: %d\n", len);
}

VOID StrcmpBefore(ADDRINT str1, ADDRINT str2) {
    printf("strcmp called\n");
}

VOID Image(IMG img, VOID* v) {
    // 查找并插装memcmp
    RTN memcmpRtn = RTN_FindByName(img, "memcmp");
    if (RTN_Valid(memcmpRtn)) {
        RTN_Open(memcmpRtn);
        RTN_InsertCall(memcmpRtn, IPOINT_BEFORE, (AFUNPTR)MemcmpBefore,
                       IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
                       IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
                       IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
                       IARG_END);
        RTN_Close(memcmpRtn);
    }

    // 查找并插装strcmp
    RTN strcmpRtn = RTN_FindByName(img, "strcmp");
    if (RTN_Valid(strcmpRtn)) {
        RTN_Open(strcmpRtn);
        RTN_InsertCall(strcmpRtn, IPOINT_BEFORE, (AFUNPTR)StrcmpBefore,
                       IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
                       IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
                       IARG_END);
        RTN_Close(strcmpRtn);
    }
}

int main(int argc, char* argv[]) {
    if (PIN_Init(argc, argv)) {
        puts("PIN初始化失败");
        return 1;
    }

    IMG_AddInstrumentFunction(Image, NULL);
    PIN_StartProgram();
    return 0;
}

方案三:全局函数入口挂钩

使用PIN_AddFunctionEntryHook全局挂钩函数,无需关心函数所在镜像:

#include "pin.H"
#include <stdio.h>

VOID MemcmpEntry(CHAR* name, ADDRINT retAddr, ADDRINT str1, ADDRINT str2, ADDRINT len) {
    printf("memcmp called, length: %d\n", len);
}

VOID StrcmpEntry(CHAR* name, ADDRINT retAddr, ADDRINT str1, ADDRINT str2) {
    printf("strcmp called\n");
}

int main(int argc, char* argv[]) {
    if (PIN_Init(argc, argv)) {
        puts("PIN初始化失败");
        return 1;
    }

    PIN_AddFunctionEntryHook((AFUNPTR)MemcmpEntry, "memcmp");
    PIN_AddFunctionEntryHook((AFUNPTR)StrcmpEntry, "strcmp");
    
    PIN_StartProgram();
    return 0;
}

额外注意:变体函数名

有些编译器会把memcmp/strcmp替换成带指令集后缀的优化版本,比如__memcmp_sse4_1、__strcmp_avx2。如果上面的方法还是找不到,可以在枚举时检查函数名是否包含memcmp或strcmp关键字:

if (strstr(rtn_name, "memcmp") != NULL || strstr(rtn_name, "strcmp") != NULL) {
    printf("%s -- %s -- %s\n", img_name, sec_name, rtn_name);
}

内容的提问来源于stack exchange,提问作者Lught

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 20:47:33