如何在Windows系统中用Intel Pin插桩ETS6的子进程?
解决ETS6子进程插桩的问题
先定位错误216的根源
Windows系统错误216看似是架构不匹配,但你已经编译了32位DLL,实际问题大概率是Pin在注入子进程时DLL路径传递出错,或者-follow_execv参数不兼容Windows的CreateProcessW机制——毕竟-follow_execv是为类Unix系统的execv调用设计的,Windows进程创建逻辑完全不同。
一步步解决问题
1. 换用Windows专属的子进程跟踪参数
把-follow_execv替换为-follow_child,这是Pin针对Windows平台子进程设计的跟踪参数,命令改成:
pin -follow_child -t obj-ia32\detect_execv.dll -- "C:\你的ETS6完整路径\ETS6.exe"
务必填写ETS6的完整路径,避免系统找不到程序导致隐性错误。
2. 确保工具编译完全兼容
- 不要用自定义编译器,直接用Pin自带的32位MSVC工具链编译,执行Pin提供的makefile:
cd C:\pin\pin-3.25-98650-g8f6168173-msvc-windows\source\tools\SimpleExamples nmake TARGET=ia32 - 检查你的
detect_execv.cpp,确保没有使用64位专属代码(比如硬写8字节内存地址、调用64位独有API)。
3. 调整系统权限和DEP设置
- 用管理员身份打开命令提示符再运行Pin,权限不足会导致DLL映射失败。
- 临时给ETS6关闭数据执行保护(DEP):右键ETS6.exe→属性→兼容性→更改所有用户设置→勾选“关闭数据执行保护”,确定后重新尝试。
4. 修改工具代码,主动拦截CreateProcessW
如果上述方法无效,直接在工具里拦截CreateProcessW,手动将Pin插桩逻辑注入子进程:
#include "pin.H" #include <windows.h> // 拦截CreateProcessW,修改子进程启动参数 VOID HookCreateProcessW(CHAR* name, LPWSTR lpApplicationName, LPWSTR lpCommandLine, ...) { char pinDllPath[MAX_PATH]; // 获取当前Pin工具DLL的路径 GetModuleFileNameA((HMODULE)PIN_MyImageBase(), pinDllPath, MAX_PATH); // 构造带Pin插桩的子进程启动命令 WCHAR childCmd[MAX_PATH * 2]; swprintf(childCmd, L"pin -t %S -- %s", pinDllPath, lpApplicationName); // 替换原命令行,让子进程被Pin插桩 va_list args; va_start(args, lpCommandLine); *va_arg(args, LPWSTR*) = childCmd; va_end(args); } VOID ImageLoad(IMG img, VOID* v) { if (IMG_IsMainExecutable(img)) { // 找到kernel32里的CreateProcessW函数 RTN createProcessRtn = RTN_FindByName(img, "CreateProcessW"); if (RTN_Valid(createProcessRtn)) { // 定义函数原型 PROTO protoCreateProcess = PROTO_Allocate(PIN_PARG(void), CALLINGSTD_STDCALL, "CreateProcessW", PIN_PARG(LPWSTR), PIN_PARG(LPWSTR), PIN_PARG(LPSECURITY_ATTRIBUTES), PIN_PARG(LPSECURITY_ATTRIBUTES), PIN_PARG(BOOL), PIN_PARG(DWORD), PIN_PARG(LPVOID), PIN_PARG(LPCWSTR), PIN_PARG(LPSTARTUPINFOW), PIN_PARG(LPPROCESS_INFORMATION), PIN_PARG_END()); // 替换函数调用 RTN_ReplaceSignature(createProcessRtn, AFUNPTR(HookCreateProcessW), IARG_PROTOTYPE, protoCreateProcess, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_END); PROTO_Free(protoCreateProcess); } } } int main(int argc, char* argv[]) { PIN_InitSymbols(); if (PIN_Init(argc, argv)) return 1; IMG_AddInstrumentFunction(ImageLoad, 0); PIN_StartProgram(); return 0; }
编译修改后的工具,直接运行pin -t obj-ia32\detect_execv.dll -- ETS6即可,无需额外跟踪参数,工具会自动将插桩逻辑应用到子进程。
5. 排查日志细节
运行前清空pin.log,执行命令后查看日志中的错误详情;如果仍崩溃,可在工具中添加更多日志输出(比如在ImageLoad中打印每个加载的模块名称),定位崩溃发生的阶段。
内容的提问来源于stack exchange,提问作者Lught
相关产品推荐
相关产品推荐

