You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

注入进程的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 16:17:33