本帖最后由 baopushouzhuo 于 2024-11-23 20:26 编辑
内存特征码搜索源码 支持 ?? F? ?F
①通过掩码的方式使其支持 前、中、后通配符 及半字节; ②通过循环找到特征码字节序列中的第一个不为'??'的元素后,后续的字节只比较不是'??'的特征字节,优化比较字节数。
#include <iostream> #include <windows.h> #include <vector> #include <Psapi.h> /// <summary> 大神论坛 www.dslt.tech /// 内存搜索算法 /// </summary> /// <param name="startAddress">起始地址</param> /// <param name="endAddress">结束地址</param> /// <param name="patternStr">特征码字符串</param> /// <param name="searchNum">搜索个数,0不限制</param> /// <returns>搜索到的地地集合</returns> std::vector<ULONG_PTR> SearchMemory(ULONG_PTR startAddress, ULONG_PTR endAddress, const char*& patternStr, ULONG_PTR searchNum) { std::vector<ULONG_PTR> resultList; std::string pattern = patternStr; int index = 0; while ((index = pattern.find(' ', index)) >= 0) pattern.erase(index, 1); //去除特征码所有空格 ULONG_PTR len = pattern.length() / 2; //计算特征码长度 ULONG_PTR nFirstMatch = len; // 跳过头部??,记录第一次匹配的位置半字符或非??,用于优化搜索 BYTE* pMarkCode = new BYTE[len]; // 存储转换后的特征码字节 BYTE* pWildcard = new BYTE[len]; // 存储特征字符串中??、?(??=FF、?=F、非?=0) 通配符 //处理特征码字符串,转换成字节数组 for (ULONG_PTR i = 0; i < len; i++) { std::string tmpStr = pattern.substr(i * 2, 2); if ("??" == tmpStr) // 是"??"的特征字符 { tmpStr = "FF"; pWildcard[i] = 0xFF; } else // 不是"??"的特征字符 { if ('?' == tmpStr[0]) // 左半字节为'?' { tmpStr[0] = 'F'; pWildcard[i] = (0xF << 4); } else if ('?' == tmpStr[1]) // 右半字节为'?' { tmpStr[1] = 'F'; pWildcard[i] = 0xF; } else { pWildcard[i] = 0x0; } if (nFirstMatch == len) nFirstMatch = i; } pMarkCode[i] = strtoul(tmpStr.c_str(), nullptr, 16); } ULONG_PTR nMemSize = endAddress - startAddress; //计算内存大小 BYTE* pMemBuffer = new BYTE[nMemSize]; // 存放内存数据的缓冲区 //memcpy(pMemBuffer, (void*)startAddress, nMemSize); //跨进程搜索内存,可使用ReadProcessMemory函数,目标进程用参数传入 ReadProcessMemory((HANDLE)-1, (void*)startAddress, pMemBuffer, nMemSize, 0); //搜索内存,匹配特征码算法 大神论坛 www.dslt.tech for (ULONG_PTR m = 0; m < nMemSize; ++m) { if (!((pMemBuffer[m] | pWildcard[nFirstMatch]) ^ pMarkCode[nFirstMatch])) //匹配上第一个字节 { ULONG_PTR offset = m - nFirstMatch; //记录偏移量 for (ULONG_PTR n = nFirstMatch; n < len; ++n) //匹配后续字节 { if (offset > nMemSize - len) break; //超出内存范围 if (pWildcard[n] != 0xFF) //后续字节是"??"的通配符,跳过,这句代码可以优化搜索 if ((pMemBuffer[offset + n] | pWildcard[n]) ^ pMarkCode[n]) break; //匹配失败 if (n + 1 == len) //匹配成功 { if ((ULONG_PTR)pMarkCode != startAddress + offset) // 排除自己 resultList.push_back(startAddress + offset); if (resultList.size() >= searchNum && searchNum != 0) goto endSearchMemory; //限制搜索数量 } } } } endSearchMemory: delete[] pMarkCode; pMarkCode = nullptr; delete[] pWildcard; pWildcard = nullptr; delete[] pMemBuffer; pMemBuffer = nullptr; return resultList; } int main() { //特征码为:?9 ?? 0? ?? 67 //会处理成:F9 FF 0F FF 67 进行匹配 //通配符为:F0 FF 0F FF 00 const char* pattern = "?9 ?? 0? ?? 67 "; // 获取进程模块内存信息 大神论坛 www.dslt.tech MODULEINFO moduleInfo = { }; GetModuleInformation((HANDLE)-1, GetModuleHandle(L"ntdll.dll"), &moduleInfo, sizeof(moduleInfo)); ULONG_PTR startAddress = (ULONG_PTR)moduleInfo.lpBaseOfDll; //模块起始地址 ULONG_PTR endAddress = startAddress + moduleInfo.SizeOfImage; //模块结束地址 clock_t nBeginTime = clock(); // 调用内存搜索算法 大神论坛 www.dslt.tech std::vector<ULONG_PTR> resultList = SearchMemory(startAddress, endAddress, pattern, 0); printf("共搜到:%d个地址-->搜索时间:%d ms\n", resultList.size(), clock() - nBeginTime); for (ULONG_PTR i = 0; i < resultList.size(); ++i) { printf("第%d个:%IX\n", i + 1, resultList[i]); } system("pause"); return 0; }
注:若转载请注明大神论坛来源(本贴地址)与作者信息。
|