注入进程的DLL复现IDA字节序列搜索功能,地址结果无效
问题
开发注入进程的DLL时,需要通过字节模式自动查找内存地址,已在IDA的【Search -> Sequence of bytes...】功能中验证模式有效,但自行编写的代码输出的地址无效——无论直接使用还是与client.dll基址相加,都指向无效内存区域。
原代码
uintptr_t mainModule = NULL; DWORD WINAPI MainFunc(HMODULE hModule) { AllocConsole(); FILE* f; freopen_s(&f, "CONOUT$", "w", stdout); mainModule = (uintptr_t)GetModuleHandle(L"client.dll"); if (hModule) { if (GetPatterns()) while (true) Sleep(1); } else { std::cout << "Main module not found, press ENTER to exit..." << std::endl; getchar(); } fclose(f); FreeConsole(); FreeLibraryAndExitThread(hModule, 0); return 0; } BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: CloseHandle(CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)MainFunc, hModule, 0, nullptr)); case DLL_PROCESS_DETACH: break; } return TRUE; } bool Compare(const BYTE* pData, const BYTE* pMask, const char* pszMask) { for (; *pszMask; ++pszMask, ++pData, ++pMask) { if (*pszMask == 'x' && *pData != *pMask) { return false; } } return (*pszMask) == NULL; } uintptr_t FindPattern(uintptr_t dwAddress, DWORD dwLen, BYTE* bMask, const char* szMask) { for (DWORD i = 0; i < dwLen; i++) if (Compare((BYTE*)(dwAddress + i), bMask, szMask)) return (uintptr_t)(dwAddress + i); return 0; } MODULEINFO mInfo; bool GetPattern(BYTE pattern[], const char* mask) { DWORD foundAddress = FindPattern(mainModule, mInfo.SizeOfImage, pattern, mask); if (foundAddress != 0) { std::cout << "Found pattern at: 0x" << std::hex << foundAddress << std::endl; return true; } std::cout << "Error: pattern not found" << std::endl; return false; } bool GetPatterns() { if (GetModuleInformation(GetCurrentProcess(), (HMODULE)mainModule, &mInfo, sizeof(mInfo))) { BYTE pattern[] = { 0x48, 0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, 0x48, 0x85, 0xC0, 0x74, 0x00, 0x8B, 0x88 }; const char* mask = "xxx????xxxx?xx"; if (!GetPattern(pattern, mask)) return false; } else { std::cout << "Error: unable to get module info" << std::endl; return false; } return true; }
问题分析与修复
1. 地址截断(核心原因)
GetPattern函数中用32位的DWORD存储64位进程下的地址,导致高32位被截断,输出的地址不完整,自然指向无效内存。
修复:
将DWORD foundAddress改为uintptr_t foundAddress,适配64位地址长度。
2. 循环越界与无效匹配
FindPattern的循环条件i < dwLen会让程序在模块内存末尾区域,尝试匹配长度超出剩余内存的模式,引发非法内存访问或错误匹配。
修复:
计算模式长度,限制循环范围:
uintptr_t FindPattern(uintptr_t dwAddress, DWORD dwLen, BYTE* bMask, const char* szMask) { DWORD maskLen = strlen(szMask); for (DWORD i = 0; i < dwLen - maskLen; i++) if (Compare((BYTE*)(dwAddress + i), bMask, szMask)) return (uintptr_t)(dwAddress + i); return 0; }
3. 模块句柄判断逻辑错误
MainFunc中错误判断DLL自身的hModule,而非目标client.dll的mainModule,导致即使目标模块未找到,仍会执行查找逻辑,错误分支永远无法触发。
修复:
将判断条件改为if (mainModule):
mainModule = (uintptr_t)GetModuleHandle(L"client.dll"); if (mainModule) { if (GetPatterns()) while (true) Sleep(1); } else { std::cout << "Main module not found, press ENTER to exit..." << std::endl; getchar(); }
4. DllMain分支缺少Break
DLL_PROCESS_ATTACH分支后未加break,会直接执行DLL_PROCESS_DETACH的代码,虽当前无严重影响,但不符合编码规范,易引发后续问题。
修复:
添加break:
case DLL_PROCESS_ATTACH: CloseHandle(CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)MainFunc, hModule, 0, nullptr)); break; case DLL_PROCESS_DETACH: break;
修正后的完整代码
#include <windows.h> #include <iostream> #include <cstring> uintptr_t mainModule = NULL; MODULEINFO mInfo; bool Compare(const BYTE* pData, const BYTE* pMask, const char* pszMask) { for (; *pszMask; ++pszMask, ++pData, ++pMask) { if (*pszMask == 'x' && *pData != *pMask) { return false; } } return (*pszMask) == NULL; } uintptr_t FindPattern(uintptr_t dwAddress, DWORD dwLen, BYTE* bMask, const char* szMask) { DWORD maskLen = strlen(szMask); for (DWORD i = 0; i < dwLen - maskLen; i++) { if (Compare((BYTE*)(dwAddress + i), bMask, szMask)) { return (uintptr_t)(dwAddress + i); } } return 0; } bool GetPattern(BYTE pattern[], const char* mask) { uintptr_t foundAddress = FindPattern(mainModule, mInfo.SizeOfImage, pattern, mask); if (foundAddress != 0) { std::cout << "Found pattern at: 0x" << std::hex << foundAddress << std::endl; return true; } std::cout << "Error: pattern not found" << std::endl; return false; } bool GetPatterns() { if (GetModuleInformation(GetCurrentProcess(), (HMODULE)mainModule, &mInfo, sizeof(mInfo))) { BYTE pattern[] = { 0x48, 0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, 0x48, 0x85, 0xC0, 0x74, 0x00, 0x8B, 0x88 }; const char* mask = "xxx????xxxx?xx"; if (!GetPattern(pattern, mask)) return false; } else { std::cout << "Error: unable to get module info" << std::endl; return false; } return true; } DWORD WINAPI MainFunc(HMODULE hModule) { AllocConsole(); FILE* f; freopen_s(&f, "CONOUT$", "w", stdout); mainModule = (uintptr_t)GetModuleHandle(L"client.dll"); if (mainModule) { if (GetPatterns()) { while (true) Sleep(1); } } else { std::cout << "Main module not found, press ENTER to exit..." << std::endl; getchar(); } fclose(f); FreeConsole(); FreeLibraryAndExitThread(hModule, 0); return 0; } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: CloseHandle(CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)MainFunc, hModule, 0, nullptr)); break; case DLL_PROCESS_DETACH: break; } return TRUE; }
内容的提问来源于stack exchange,提问作者kuhi
相关产品推荐
相关产品推荐

