吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3423|回复: 40
收起左侧

[C&C++ 原创] msimg32.dll 劫持补丁源码,支持问号通配符内存搜索替换

  [复制链接]
qqycra 发表于 2025-6-1 20:36
本帖最后由 qqycra 于 2025-6-4 22:29 编辑

2025年6月4日21点更新,新增了完整源码压缩包。
打开cpp,把你自己的特征码填上就能劫持了。
我又写了更多功能的,这个简单的就分享给大家了。

劫持源码使用慎重,责任自负。
msimg32-20250525Normal.7z (5.47 KB, 下载次数: 22)

定义配置:
[C++] 纯文本查看 复制代码
namespace Config {
        // 日志配置
        static const bool EnableLogging = DEBUG_MODE;

        // 目标配置,NULL 是 EXE, 或者 "a.dll" 是 DLL
#ifdef _WIN64
        static const char* Target = "a.dll";
#else
        static const char* Target = NULL;
#endif

        struct PatchInfo {
                const char* pattern;
                const char* replace;
        };

#ifdef _WIN64
        static const PatchInfo Patches[] = {
                {"32 DB 48 8B 4C 24 30 48 63 51 04 4C ?? ?? ?? 30", "88 C3 48 8B 4C 24 30 48 63 51 04 4C 89 74 14 30"},
                {"E8 E1 0D 00 00 48 85 C0 75 10", "E8 E1 0D 00 00 48 85 C0 90 90"}
        };
#else
        static const PatchInfo Patches[] = {
                {"74 23 6A 00 8B 45 F0", "EB 23 6A 00 8B 45 F0"},
                {"55 8B EC 51 89 45 FC 33 D2 8B 45 FC E8 5B 1E F9 FF", "55 8B EC 51 B8 01 00 00 00 90 90 90 90 90 90 90 90"}
        };
#endif
}


辅助函数:
[C++] 纯文本查看 复制代码
// 辅助函数
namespace {
        LPVOID GetModuleBaseAddress(LPCSTR moduleName) {
                MODULEINFO moduleInfo = { 0 };
                HMODULE hModule = GetModuleHandleA(moduleName);
                if (hModule && GetModuleInformation(GetCurrentProcess(), hModule, &moduleInfo, sizeof(moduleInfo))) {
                        LogMessage("Found module %s at 0x%p", moduleName, moduleInfo.lpBaseOfDll);
                        return moduleInfo.lpBaseOfDll;
                }
                LogMessage("Failed to find module %s", moduleName);
                return NULL;
        }

        SIZE_T GetModuleSize(LPCSTR moduleName) {
                MODULEINFO moduleInfo = { 0 };
                HMODULE hModule = GetModuleHandleA(moduleName);
                if (hModule && GetModuleInformation(GetCurrentProcess(), hModule, &moduleInfo, sizeof(moduleInfo))) {
                        return moduleInfo.SizeOfImage;
                }
                return 0;
        }

        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;
        }
}


加载原始msimg32.dll:
[C++] 纯文本查看 复制代码
BOOL LoadOriginalDll(void) {
        CHAR systemDir[MAX_PATH] = { 0 };
        CHAR dllPath[MAX_PATH] = { 0 };

#ifdef _WIN64    
        if (!GetSystemDirectoryA(systemDir, MAX_PATH)) {
                LogMessage("Failed to get system directory");
                return FALSE;
        }
#else
        if (!GetSystemWow64DirectoryA(systemDir, MAX_PATH)) {
                LogMessage("Failed to get system directory");
                return FALSE;
        }
#endif

        StringCchPrintfA(dllPath, MAX_PATH, "%s\\msimg32.dll", systemDir);
        LogMessage("Loading original DLL from: %s", dllPath);
        g_hOriginalDll = LoadLibraryA(dllPath);

        if (!g_hOriginalDll) {
                LogMessage("Failed to load original DLL, error: %lu", GetLastError());
                return FALSE;
        }

        pfnAlphaBlend = (PFN_AlphaBlend)GetProcAddress(g_hOriginalDll, "AlphaBlend");
        pfnGradientFill = (PFN_GradientFill)GetProcAddress(g_hOriginalDll, "GradientFill");
        pfnTransparentBlt = (PFN_TransparentBlt)GetProcAddress(g_hOriginalDll, "TransparentBlt");

        if (!pfnAlphaBlend || !pfnGradientFill || !pfnTransparentBlt) {
                LogMessage("Failed to get original function addresses");
                return FALSE;
        }

        LogMessage("Original DLL loaded successfully");
        return TRUE;
}


打内存补丁:
[Asm] 纯文本查看 复制代码
BOOL PatchMemory(void) {
        LogMessage("Starting memory patching process");

        LPVOID baseAddress = GetModuleBaseAddress(Config::Target);
        SIZE_T moduleSize = GetModuleSize(Config::Target);

        if (!baseAddress || !moduleSize) {
                LogMessage("Failed to get target information");
                return FALSE;
        }

        SIZE_T totalPatches = 0;
        size_t patchCount = sizeof(Config::Patches) / sizeof(Config::Patches[0]);
        LogMessage("Found %zu patch patterns to apply", patchCount);

        for (size_t i = 0; i < patchCount; i++) {
                const auto& patch = Config::Patches[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 patch pattern %zu, skipping", i + 1);
                        continue;
                }

                // 解析替换内容(不允许通配符)
                if (!HexStringToBytes(patch.replace, replaceBytes, NULL, &replaceSize)) {
                        LogMessage("Warning: Failed to parse replace pattern %zu, skipping", i + 1);
                        continue;
                }

                LogMessage("Applying patch %zu:", i + 1);
                LogBytes("  Search pattern", patternBytes, isWildcard, patternSize);
                LogBytes("  Replace with", replaceBytes, NULL, replaceSize);

                LPBYTE currentAddress = (LPBYTE)baseAddress;
                SIZE_T remainingSize = moduleSize;
                DWORD oldProtect = 0;
                SIZE_T matchesFound = 0;

                while (remainingSize >= patternSize) {
                        if (MemCompare(currentAddress, patternBytes, isWildcard, patternSize)) {
                                LogMessage("Found match at 0x%p", currentAddress);
                                LogBytes("  Original bytes", currentAddress, NULL, patternSize);

                                if (VirtualProtect(currentAddress, patternSize, PAGE_EXECUTE_READWRITE, &oldProtect)) {
                                        memcpy(currentAddress, replaceBytes, patternSize);
                                        VirtualProtect(currentAddress, patternSize, oldProtect, &oldProtect);

                                        LogBytes("  Patched bytes", currentAddress, NULL, patternSize);
                                        totalPatches++;
                                        matchesFound++;
                                }
                                else {
                                        LogMessage("Warning: Failed to modify memory protection (error: %lu)", GetLastError());
                                }

                                currentAddress += patternSize;
                                remainingSize -= patternSize;
                        }
                        else {
                                currentAddress++;
                                remainingSize--;
                        }
                }

                LogMessage("Applied %zu instances of patch %zu", matchesFound, i + 1);
        }

        LogMessage("Patching completed, total patches applied: %zu", totalPatches);
        return totalPatches > 0;
}


下面是另一个版本,可以几毫秒完成搜索替换,支持单通配符,速度快些,这个版本没对外分享:
1.jpg

免费评分

参与人数 10吾爱币 +19 热心值 +10 收起 理由
糖糖糖 + 1 + 1 用心讨论,共获提升!
qwg + 1 + 1 谢谢@Thanks!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
eric + 1 + 1 我很赞同!
ZiPP + 2 + 1 用心讨论,共获提升!
bypasshwid + 3 + 1 建议直接打包源码上传。
Hameel + 1 谢谢@Thanks!
Tonyha7 + 2 + 1 谢谢@Thanks!
秋名山 + 1 + 1 谢谢@Thanks!
3yu3 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

m_h 发表于 2025-6-3 12:56
主要修改点说明
内存区域定位:

使用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给的结果

slzslz 发表于 2025-6-6 13:43
 楼主| qqycra 发表于 2025-6-1 20:37
 楼主| qqycra 发表于 2025-6-1 20:38
被汉字显示坑了挺长时间,产生各种奇怪问题,后来日志用英文就啥事没有了
 楼主| qqycra 发表于 2025-6-1 20:39
x64特征码是某录屏软件
 楼主| qqycra 发表于 2025-6-1 20:42
补充下:支持exe或者dll,配置里有开关
天空の幻像 发表于 2025-6-1 21:11
qqycra 发表于 2025-6-1 20:42
补充下:支持exe或者dll,配置里有开关

老哥有没有pyhton37的,python写的咋注入,有没有易语言
秋名山 发表于 2025-6-1 21:21
楼主能否打包一下整个工程
 楼主| qqycra 发表于 2025-6-1 21:25
天空の幻像 发表于 2025-6-1 21:11
老哥有没有pyhton37的,python写的咋注入,有没有易语言

没有啊,python解包呗,论坛里有
 楼主| qqycra 发表于 2025-6-1 21:26
本帖最后由 qqycra 于 2025-6-1 21:28 编辑
秋名山 发表于 2025-6-1 21:21
楼主能否打包一下整个工程

基本没啥了,我是用批处理编译的。
你上网找个msimg32模板,然后把我的代码添加进去就完事了
董督秀 发表于 2025-6-1 21:48
支持堆内存替换吗?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-3-17 07:39

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表