主要修改点说明
内存区域定位:
使用GetProcessMemoryRegions函数获取目标进程的所有可读可写内存区域
通过MEMORY_BASIC_INFORMATION结构获取内存区域的详细信息
特别关注MEM_PRIVATE类型的内存,这通常包含堆内存
内存搜索与替换:
SearchAndReplaceInRegion函数负责在特定内存区域中搜索模式并替换
使用ReadProcessMemory读取目标进程内存
使用VirtualProtectEx和WriteProcessMemory修改目标进程内存
配置调整:
修改了配置结构,添加了max_search_size参数限制搜索范围
支持指定目标进程ID(0表示当前进程)
安全措施:
修改内存前先调整内存保护属性
操作完成后恢复原始保护属性
添加了详细的错误日志
使用注意事项
权限要求:
修改其他进程的内存需要足够的权限(PROCESS_VM_OPERATION等)
在Windows Vista及更高版本上可能需要管理员权限
稳定性考虑:
修改堆内存可能影响目标进程的稳定性
建议先在测试环境中验证补丁效果
性能影响:
搜索大范围内存可能耗时较长
可以通过max_search_size参数限制搜索范围
法律合规:
修改其他进程内存可能违反某些软件的使用条款
确保在合法范围内使用此技术
这个实现提供了灵活的堆内存修改能力,可以用于调试、逆向工程等合法用途。使用时请确保遵守相关法律法规。
#include <windows.h>
#include <strsafe.h>
#include <psapi.h>
#include <stdio.h>
#include <tlhelp32.h>
// 调试模式定义
#define DEBUG_MODE 1
// 日志函数
void LogMessage(const char* format, ...) {
if (!DEBUG_MODE) return;
char buffer[1024];
va_list args;
va_start(args, format);
StringCchVPrintfA(buffer, sizeof(buffer), format, args);
va_end(args);
OutputDebugStringA(buffer);
OutputDebugStringA("\n");
}
// 配置命名空间
namespace Config {
// 日志配置
static const bool EnableLogging = DEBUG_MODE;
// 目标进程ID (0表示当前进程)
static const DWORD TargetProcessId = 0;
struct HeapPatchInfo {
const char* pattern;
const char* replace;
SIZE_T max_search_size; // 最大搜索范围
};
static const HeapPatchInfo HeapPatches[] = {
{"74 23 6A 00 8B 45 F0", "EB 23 6A 00 8B 45 F0", 0x100000}, // 示例堆补丁
{"55 8B EC 51 89 45 FC", "55 8B EC 51 B8 01 00", 0x200000} // 另一个示例
};
}
// 辅助函数命名空间
namespace {
BOOL HexStringToBytes(LPCSTR hexString, LPBYTE buffer, BOOL* isWildcard, SIZE_T* bufferSize) {
SIZE_T strLen = strlen(hexString);
SIZE_T byteCount = 0;
for (SIZE_T i = 0; i < strLen; ) {
if (hexString[i] == ' ') {
i++;
continue;
}
// 检查通配符 "??"
if (i + 1 < strLen && hexString[i] == '?' && hexString[i + 1] == '?') {
if (isWildcard) {
isWildcard[byteCount] = TRUE;
}
buffer[byteCount++] = 0;
i += 2;
continue;
}
if (i + 1 >= strLen) return FALSE;
CHAR hexPair[3] = { hexString[i], hexString[i + 1], 0 };
if (sscanf_s(hexPair, "%hhx", &buffer[byteCount]) != 1) return FALSE;
if (isWildcard) {
isWildcard[byteCount] = FALSE;
}
byteCount++;
i += 2;
}
*bufferSize = byteCount;
return TRUE;
}
inline BOOL MemCompare(const BYTE* data, const BYTE* pattern, const BOOL* isWildcard, SIZE_T size) {
for (SIZE_T i = 0; i < size; i++) {
if (!isWildcard[i] && data[i] != pattern[i]) {
return FALSE;
}
}
return TRUE;
}
// 获取进程的所有可读可写内存区域
BOOL GetProcessMemoryRegions(DWORD pid, MEMORY_BASIC_INFORMATION** regions, SIZE_T* count) {
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
if (!hProcess) {
LogMessage("Failed to open process (error: %lu)", GetLastError());
return FALSE;
}
BYTE* address = 0;
MEMORY_BASIC_INFORMATION mbi;
SIZE_T capacity = 100;
SIZE_T size = 0;
*regions = (MEMORY_BASIC_INFORMATION*)malloc(capacity * sizeof(MEMORY_BASIC_INFORMATION));
if (!*regions) {
CloseHandle(hProcess);
return FALSE;
}
while (VirtualQueryEx(hProcess, address, &mbi, sizeof(mbi))) {
// 只关注可读可写的内存区域
if ((mbi.Protect & PAGE_READWRITE) &&
(mbi.State == MEM_COMMIT) &&
(mbi.Type == MEM_PRIVATE)) { // MEM_PRIVATE 包含堆内存
if (size >= capacity) {
capacity *= 2;
MEMORY_BASIC_INFORMATION* newRegions = (MEMORY_BASIC_INFORMATION*)realloc(
*regions, capacity * sizeof(MEMORY_BASIC_INFORMATION));
if (!newRegions) {
free(*regions);
CloseHandle(hProcess);
return FALSE;
}
*regions = newRegions;
}
(*regions)[size++] = mbi;
}
address += mbi.RegionSize;
}
CloseHandle(hProcess);
*count = size;
return TRUE;
}
// 在内存区域中搜索并替换模式
BOOL SearchAndReplaceInRegion(HANDLE hProcess, BYTE* baseAddress, SIZE_T regionSize,
const BYTE* pattern, const BOOL* isWildcard, SIZE_T patternSize,
const BYTE* replace, SIZE_T replaceSize) {
BYTE* buffer = (BYTE*)malloc(regionSize);
if (!buffer) {
return FALSE;
}
SIZE_T bytesRead = 0;
if (!ReadProcessMemory(hProcess, baseAddress, buffer, regionSize, &bytesRead) || bytesRead != regionSize) {
free(buffer);
return FALSE;
}
BOOL result = FALSE;
for (SIZE_T i = 0; i <= regionSize - patternSize; i++) {
if (MemCompare(buffer + i, pattern, isWildcard, patternSize)) {
LogMessage("Found pattern at 0x%p", baseAddress + i);
DWORD oldProtect;
if (VirtualProtectEx(hProcess, baseAddress + i, replaceSize, PAGE_EXECUTE_READWRITE, &oldProtect)) {
if (WriteProcessMemory(hProcess, baseAddress + i, replace, replaceSize, NULL)) {
LogMessage("Successfully replaced memory at 0x%p", baseAddress + i);
result = TRUE;
} else {
LogMessage("Failed to write memory (error: %lu)", GetLastError());
}
VirtualProtectEx(hProcess, baseAddress + i, replaceSize, oldProtect, &oldProtect);
} else {
LogMessage("Failed to change memory protection (error: %lu)", GetLastError());
}
}
}
free(buffer);
return result;
}
}
// 堆内存补丁函数
BOOL PatchHeapMemory(void) {
LogMessage("Starting heap memory patching process");
DWORD pid = Config::TargetProcessId;
if (pid == 0) {
pid = GetCurrentProcessId();
}
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION |
PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pid);
if (!hProcess) {
LogMessage("Failed to open target process (error: %lu)", GetLastError());
return FALSE;
}
MEMORY_BASIC_INFORMATION* regions = NULL;
SIZE_T regionCount = 0;
if (!GetProcessMemoryRegions(pid, ®ions, ®ionCount)) {
CloseHandle(hProcess);
return FALSE;
}
size_t patchCount = sizeof(Config::HeapPatches) / sizeof(Config::HeapPatches[0]);
LogMessage("Found %zu heap patch patterns to apply", patchCount);
SIZE_T totalPatches = 0;
for (size_t i = 0; i < patchCount; i++) {
const auto& patch = Config::HeapPatches[i];
BYTE patternBytes[256] = { 0 };
BYTE replaceBytes[256] = { 0 };
BOOL isWildcard[256] = { FALSE };
SIZE_T patternSize = 0;
SIZE_T replaceSize = 0;
// 解析模式(允许通配符)
if (!HexStringToBytes(patch.pattern, patternBytes, isWildcard, &patternSize)) {
LogMessage("Warning: Failed to parse heap patch pattern %zu, skipping", i + 1);
continue;
}
// 解析替换内容(不允许通配符)
if (!HexStringToBytes(patch.replace, replaceBytes, NULL, &replaceSize)) {
LogMessage("Warning: Failed to parse heap replace pattern %zu, skipping", i + 1);
continue;
}
if (patternSize != replaceSize) {
LogMessage("Warning: Pattern and replace size mismatch for patch %zu, skipping", i + 1);
continue;
}
LogMessage("Applying heap patch %zu:", i + 1);
SIZE_T matchesFound = 0;
for (SIZE_T j = 0; j < regionCount; j++) {
BYTE* baseAddress = (BYTE*)regions[j].BaseAddress;
SIZE_T regionSize = regions[j].RegionSize;
// 限制搜索范围
if (patch.max_search_size > 0 && regionSize > patch.max_search_size) {
regionSize = patch.max_search_size;
}
if (SearchAndReplaceInRegion(hProcess, baseAddress, regionSize,
patternBytes, isWildcard, patternSize,
replaceBytes, replaceSize)) {
matchesFound++;
}
}
LogMessage("Applied %zu instances of heap patch %zu", matchesFound, i + 1);
totalPatches += matchesFound;
}
free(regions);
CloseHandle(hProcess);
LogMessage("Heap patching completed, total patches applied: %zu", totalPatches);
return totalPatches > 0;
}
// DLL入口点
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
LogMessage("DLL_PROCESS_ATTACH");
// 应用堆内存补丁
PatchHeapMemory();
// 执行劫持后的操作
MessageBoxA(NULL, "Heap memory patching completed!", "Heap Patch", MB_OK);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
LogMessage("DLL_PROCESS_DETACH");
break;
}
return TRUE;
}
ds v3 AI给的结果