我最近一直在玩内存读取/编辑,遇到了一个我认为是64位应用程序的问题,我也尝试在64位下编译。 我使用32位应用程序使用这个脚本没有问题,但是当我在Solitaire上尝试这个时,它无法获得基地址,然后无法解决正确的偏移等问题。 这是脚本:
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
using namespace std;
DWORD dwGetModuleBaseAddress(DWORD dwProcessID, TCHAR *lpszModuleName)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessID);
DWORD dwModuleBaseAddress = 0;
if (hSnapshot != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 ModuleEntry32 = { 0 };
ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
if (Module32First(hSnapshot, &ModuleEntry32))
{
do
{
if (_tcscmp(ModuleEntry32.szModule, lpszModuleName) == 0)
{
dwModuleBaseAddress = (DWORD)ModuleEntry32.modBaseAddr;
break;
}
} while (Module32Next(hSnapshot, &ModuleEntry32));
}
CloseHandle(hSnapshot);
}
return dwModuleBaseAddress;
}
int main()
{
DWORD address = 0xBAFA8;
HWND hwnd = FindWindow(0, L"Solitaire");
DWORD pid;
int data = 0;
int newData = 0;
if (hwnd)
{
GetWindowThreadProcessId(hwnd, &pid);
HANDLE phandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
if (phandle)
{
DWORD base = dwGetModuleBaseAddress(pid, L"Solitaire.exe");
cout << "Base: " << (void*)base << endl;
ReadProcessMemory(phandle, (LPCVOID)(base + address), &data, sizeof(data), 0);
}
else {
cout << "Couldnt get handle" << endl;
}
}
else {
cout << "Couldn't find window" << endl;
}
cin.get();
return 0;
}
问题可能是我使用的函数使用MODULE32,但是我尝试了其他函数(使用EnumModules)仍然无法返回地址。
任何想法如何获得64位应用程序的基地址或让这个脚本运行?
由于
答案 0 :(得分:2)
您的代码永远不会成功,因为您正在谈论64位,但您使用DWORD作为基址! Solitare 可能有32位地址,但你不能保证,你永远不应该假设它。
此功能有效。它只需要相关进程的进程ID,并假定您需要该进程的基址。即不是其中一个DLL。如果您不想拥有进程,则需要使用moduleArray
等内容迭代for (int i=0; i<moduleCount; i++ ) { // do something with moduleArray[i] }
,然后检查模块文件名。
如果你只想要启动过程(可执行文件),你可以假设它是数组中的第一个元素。
DWORD_PTR GetProcessBaseAddress( DWORD processID )
{
DWORD_PTR baseAddress = 0;
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
HMODULE *moduleArray;
LPBYTE moduleArrayBytes;
DWORD bytesRequired;
if ( processHandle )
{
if ( EnumProcessModules( processHandle, NULL, 0, &bytesRequired ) )
{
if ( bytesRequired )
{
moduleArrayBytes = (LPBYTE)LocalAlloc( LPTR, bytesRequired );
if ( moduleArrayBytes )
{
unsigned int moduleCount;
moduleCount = bytesRequired / sizeof( HMODULE );
moduleArray = (HMODULE *)moduleArrayBytes;
if ( EnumProcessModules( processHandle, moduleArray, bytesRequired, &bytesRequired ) )
{
baseAddress = (DWORD_PTR)moduleArray[0];
}
LocalFree( moduleArrayBytes );
}
}
}
CloseHandle( processHandle );
}
return baseAddress;
}
答案 1 :(得分:1)
正如大卫所暗示的那样,这句话是错误的:
dwModuleBaseAddress = (DWORD)ModuleEntry32.modBaseAddr;
因为您正在将64位指针(在64位应用程序上)转换为DWORD
截断值(来自调试器的屏幕截图,64位应用程序打开64位进程)
你应该选择指针类型(DWORD_PTR
也适用于便携式解决方案。)
答案 2 :(得分:-1)
基于@Nostromoo给出的示例的控制台应用程序示例
应该在x86 / x64上工作
#include "stdafx.h"
#include <windows.h>
#include <psapi.h>
#include <vector>
#define MODULE_NAME L"TestModule"
#define WINDOW_NAME L"TestConsole"
bool GetBaseModuleInfo(MODULEINFO* baseModuleInfo);
HMODULE GetProcessBaseAddressFromProcessHandle(HANDLE processHandle);
bool EnumProcessModulesPlattform(HANDLE processHandle, HMODULE* lphModule, DWORD cb, LPDWORD bytesRequired);
DWORD GetProcessIdentifier(const wchar_t* windowName);
int main()
{
SetConsoleTitle(WINDOW_NAME);
// Wait for the title to be set otherwise the window might not be found.
Sleep(200);
MODULEINFO baseModuleInfo;
bool success = GetBaseModuleInfo(&baseModuleInfo);
if (success == false) {
wprintf(MODULE_NAME L"main() - GetBaseModuleInfo() failed.\n");
std::getchar();
return 1;
}
wchar_t buffer[2000];
#ifdef _WIN64
swprintf_s(buffer, sizeof(buffer) / sizeof(*buffer), MODULE_NAME L"main() - baseAddress: '%llX' size: '%lX'\n", baseModuleInfo.lpBaseOfDll, baseModuleInfo.SizeOfImage);
#elif _WIN32
swprintf_s(buffer, sizeof(buffer) / sizeof(*buffer), MODULE_NAME L"main() - baseAddress: '%lX' size: '%lX'\n", baseModuleInfo.lpBaseOfDll, baseModuleInfo.SizeOfImage);
#endif
wprintf(buffer);
std::getchar();
return 0;
}
bool GetBaseModuleInfo(MODULEINFO* baseModuleInfo)
{
DWORD processID = GetProcessIdentifier(WINDOW_NAME);
if (processID == NULL) {
wprintf(MODULE_NAME L"GetBaseModuleInfo() - GetProcessIdentifier() returned NULL.\n");
return false;
}
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
if (processHandle == NULL) {
wprintf(MODULE_NAME L"GetBaseModuleInfo() - OpenProcess() returned NULL.\n");
return false;
}
HMODULE baseAddress = GetProcessBaseAddressFromProcessHandle(processHandle);
if (baseAddress == NULL) {
wprintf(MODULE_NAME L"GetBaseModuleInfo() - GetProcessBaseAddressFromProcessHandle() returned NULL.\n");
return false;
}
bool resultGMI = GetModuleInformation(processHandle, baseAddress, baseModuleInfo, sizeof(*baseModuleInfo));
// NOTE: GetModuleInformation doesn't fail even if the baseAddress is wrong. Maybe it uses the nearest module?
if (resultGMI == false) {
wprintf(MODULE_NAME L"GetBaseModuleInfo() - GetModuleInformation() failed.\n");
return false;
}
CloseHandle(processHandle);
return true;
}
HMODULE GetProcessBaseAddressFromProcessHandle(HANDLE processHandle)
{
DWORD bytesRequired;
if (EnumProcessModulesPlattform(processHandle, NULL, 0, &bytesRequired) == false) {
wprintf(MODULE_NAME L"GetProcessBaseAddressFromProcessHandle() - EnumProcessModules() error.\n");
return NULL;
}
if (bytesRequired == NULL) {
wprintf(MODULE_NAME L"GetProcessBaseAddressFromProcessHandle() - EnumProcessModules() returned 0 bytesRequired.\n");
return NULL;
}
unsigned int moduleCount = bytesRequired / sizeof(HMODULE);
std::vector<HMODULE> hModules(moduleCount, 0);
if (EnumProcessModulesPlattform(processHandle, &hModules[0], bytesRequired, &bytesRequired) == false) {
wprintf(MODULE_NAME L"GetProcessBaseAddressFromProcessHandle() - EnumProcessModules(moduleArray) error.\n");
return NULL;
}
// The first item is always the baseModule.
HMODULE baseAddress = hModules[0];
return baseAddress;
}
bool EnumProcessModulesPlattform(HANDLE processHandle, HMODULE* lphModule, DWORD cb, LPDWORD bytesRequired)
{
#ifdef _WIN64
bool returnValue = EnumProcessModulesEx(processHandle, lphModule, cb, bytesRequired, LIST_MODULES_64BIT);
#elif _WIN32
bool returnValue = EnumProcessModulesEx(processHandle, lphModule, cb, bytesRequired, LIST_MODULES_32BIT);
#endif
DWORD lastError = GetLastError();
if (lastError != 0) {
wprintf(MODULE_NAME L"EnumProcessModulesPlattform() - lastError != 0 EnumProcessModulesEx().\n");
return false;
}
return returnValue;
}
DWORD GetProcessIdentifier(const wchar_t* windowName)
{
HWND windowHandle = FindWindow(NULL, windowName);
if (windowHandle == NULL) {
wprintf(MODULE_NAME L"GetProcessIdentifier() - Could not find hwnd of '%s'.\n", windowName);
return NULL;
}
DWORD processID;
GetWindowThreadProcessId(windowHandle, &processID);
return processID;
}