其实也就是记录一下用 WinDbg 调试 fHash 的一次过程,这个 bug 是由于没好好看文档造成的,我需要让 fHash 知道当前运行的操作系统是 32 位还是 64 位的,之后好去选择正确的 shell extension 文件。查文档看到了这个函数 IsWow64Process ,之后错误的以为 kernel32 中有这个函数就是 64 位操作系统,结果就已这个逻辑写下了错误的 64 位系统判断函数,和错误文件读取逻辑。
tstring tstrExeDirPath(pszExeFullPath); tstring::size_type idx = tstrExeDirPath.rfind(_T("\\")); tstrExeDirPath = tstrExeDirPath.substr(0, idx); tstring tstrShlExtDll = tstrExeDirPath; tstrShlExtDll.append(_T("\\fHashShlExt")); if(IsWindows64()) tstrShlExtDll.append(_T("64")); tstrShlExtDll.append(_T(".dll")); WIN32_FIND_DATA ffData; HANDLE hFind = FindFirstFile(tstrShlExtDll.c_str(), &ffData); bool bRet = (hFind != INVALID_HANDLE_VALUE); if(bRet) { #if defined(UNICODE) || defined(_UNICODE) wcscpy_s(pszShlDllPath, MAX_PATH, tstrShlExtDll.c_str()); #else strcpy_s(pszShlDllPath, MAX_PATH, tstrShlExtDll.c_str()); #endif FindClose(hFind); } return bRet;
结果很自然,在 32 位的 Windows XP 上没有执行正确。但是测试环境没有 VisualStudio,而且用的是 Release 编译,也没有带着符号文件,这怎么调试呢。Windows XP 上装有 WinDbg,那么就用它来调试。
启动 fHash 和 WinDbg,附加到 fHash 进程,由于没有 fHash 的符号,于是考虑在 FindFirstFile 函数上下断点:
bp kernel32!FindFirstFileW
Go,开始运行,点击“添加右键菜单”,WinDbg 停在 FindFirstFile 断点上,回到 Call Stack 的上一层:
.frame 01
看到 call 之前第二次压栈 push eax,检查 eax 对应内存地址的数据:
r eax db 003b7ed0
看到指针指向的字符串是 …/fHashShlExt64.dll,说明之前 IsWindows64() 返回的 true。也就是说 kernel32 中有 IsWow64Process 函数,我们来看一下。
在 GetProcAddress 函数上下断点:
bp kernel32!GetProcAddress
再次尝试添加右键菜单,WinDbg 停在 GetProcAddress 断点,我们让它 Step Out,之后停在 IsWindows64() 函数里面,看看返回值 eax:
r eax u 7c81f2b9
可以看到反编译该内存地址就是 IsWow64Process。
18-22 可以用_tcscpy来替换