【问题标题】:Base address of a process without DLL injection?没有DLL注入的进程的基地址?
【发布时间】:2019-02-13 10:37:47
【问题描述】:

通过DLL注入,获取进程的基地址就像使用一样简单

GetModuleHandleW(0);

所以我试图在不注入的情况下获取地址,但我似乎无法让它工作。我在 Google 上搜索了一些解决方案,并从 stackoverflow 中找到了其他解决方案,但它们似乎不起作用。这是我现在正在使用的。我有正确的标题,它可以编译。它只是不起作用。

DWORD_PTR dwGetModuleBaseAddress(DWORD dwProcID, TCHAR *szModuleName)
{
    DWORD_PTR dwModuleBaseAddress = 0;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, dwProcID);
    if (hSnapshot != INVALID_HANDLE_VALUE)
    {
        MODULEENTRY32 ModuleEntry32;
        ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
        if (Module32First(hSnapshot, &ModuleEntry32))
        {
            do
            {
                if (_tcsicmp(ModuleEntry32.szModule, szModuleName) == 0)
                {
                    dwModuleBaseAddress = (DWORD_PTR)ModuleEntry32.modBaseAddr;
                    break;
                }
            } while (Module32Next(hSnapshot, &ModuleEntry32));
        }
        CloseHandle(hSnapshot);
    }
    return dwModuleBaseAddress;
}

我尝试计算这个地址,它只给我 0。我认为这可能是我不理解第二个参数的事实。我只是复制我看到的。这是我的主要功能。

int main() { 
   HWND hwnd = FindWindowA(NULL, gameName); 
   int x; 
   if (hwnd == NULL) { 
      cout << "Cannot find " << (string)gameName << " window" << endl; 
      cin >> x; 
      exit(-1); 
   } 

   DWORD procID; 
   GetWindowThreadProcessId(hwnd, &procID); 
   HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID); 

   DWORD playerAddr = 0; 
   playerAddr = dwGetModuleBaseAddress(procID, _T("starbound.exe")); 
   cout << hex << playerAddr; 
}

其中一些可能是多余的,因为我只是将它添加到我之前的内容中。我只是不确定为什么它不起作用。

【问题讨论】:

  • 您的进程是 32 位还是 64 位?而且,这个问题之前已经被问过数百次了。做更多的研究。并且不要忽略返回值。

标签: c++ winapi


【解决方案1】:

你的代码是正确的,没有任何问题,我只是在x86和x64上测试过。

您的问题是您需要以管理员身份运行,因此您拥有访问其他进程的正确安全权限,并且您还应该将项目构建为与目标进程相同的架构(x86 或 x64)。

如果这些解决方案都没有解决它,那么您的“gameName”变量或您的模块名称定义不正确。

【讨论】:

    【解决方案2】:

    如果您使用 dwModuleBaseAddress 作为调试工具,可能更容易发现失败的调用...

    DWORD_PTR dwGetModuleBaseAddress(DWORD dwProcID, TCHAR *szModuleName)
    {
        DWORD_PTR dwModuleBaseAddress = (DWORD_PTR)-1; // unlikely value...
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, dwProcID);
        if (hSnapshot != INVALID_HANDLE_VALUE)
        {
            MODULEENTRY32 ModuleEntry32;
            ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
    
            dwModuleBaseAddress = (DWORD_PTR)-2;
    
            if (Module32First(hSnapshot, &ModuleEntry32))
            {
                do
                {
                    --dwModuleBaseAddress;
                    if (_tcsicmp(ModuleEntry32.szModule, szModuleName) == 0)
                    {
                        dwModuleBaseAddress = (DWORD_PTR)ModuleEntry32.modBaseAddr;
                        break;
                    }
                } while (Module32Next(hSnapshot, &ModuleEntry32));
            }
            CloseHandle(hSnapshot);
        }
        return dwModuleBaseAddress;
    }
    

    您还可以使用 GetLastError() 检查导致问题的错误

    void PrintLastError()
    {
        LPTSTR psz;
        DWORD dwError = GetLastError();
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
            NULL,
            dwError,
            0,
            (LPTSTR)&psz,
            1024,
            NULL);
    
        _tprintf(_T("Windows reports error: (0x%08X): %s\n"), dwError, (psz) ? psz : _T("(null)"));
        if (psz)
        {
            LocalFree(psz);
        }
    }
    

    如果一切都失败了,请尝试从 msdn https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms686849(v=vs.85).aspx 运行此示例

    它会打印你想要匹配的确切字符串,问题可能来自那里。

    【讨论】:

    • 谢谢。我还没有解决它,但它确实帮助了我。我不知道为什么我以前没有尝试过。基本上我只是在某些时候做了一个 cout 只是为了看看它走了多远。因此,它似乎甚至没有通过 if 语句 if (hSnapshot != INVALID_HANDLE_VALUE)。这意味着 HANDLE hSnapshot 没有得到这个过程。为什么它不起作用?进程处于打开状态,并且进程 ID 正确。我正在这样做: dwGetModuleBaseAddress(procID, _T("starbound.exe"));我觉得这有问题。
    • 您的进程可能没有必要的安全访问权限。
    • 我该如何解决这个问题?我尝试以管理员身份运行 Visual Studio,但它不起作用。我什至尝试以管理员身份运行 .exe 文件本身。
    • 检查确实是问题所在,检查答案中添加的信息
    • 所以我在我认为错误所在的行之前和之后做了一个 PrintLastError() 。在它说“操作成功完成”之前,在它说“只有部分 ReadProcessmemory 或 WriteProcessMemory 请求已完成”之后。在这之后,我用谷歌搜索了这个错误,人们在谈论 x86 与 x64,我意识到我正在运行它 x86。现在我做了 x64 因为我有 64 位 Windows。这次它说“操作已成功完成”而不是其他错误,但它仍然显示 0 作为地址。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    相关资源
    最近更新 更多