更新的:参见问题机器人上的更新
我想获得game.dll
的基址,它位于war3.exe进程中。我正试图通过JNA库5.9.0版本来完成这一任务,但没有成功。
我面临的问题是:我无法从war3.exe进程中获取game.dll模块。我试着用:
int pid = getProcessId("Warcraft III");
openProcess(PROCESS_ALL_ACCESS, pid);
WinDef.HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle("game.dll")
但hMod
的结果是null
。
此外,我还试图获得war3.exe进程所拥有的所有模块。如您所见,它只包含5个模块,并且不包含game.dll
。但是当我通过Process打开war3.exe时,我看到的绝对超过5个。
与Intellij:一起执行
从Process获取的:
请分享你的观点和想法,为什么我只从IDE得到5个模块。
任何关于如何通过JNA获得game.dll
模块及其基本地址的建议将不胜感激。
更新:根据雷米的回答,我又尝试了一次EnumProcessModules()
。下面是我的代码片段:
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Psapi;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HMODULE;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.ptr.IntByReference;
import java.util.Arrays;
import java.util.List;
import static com.sun.jna.platform.win32.WinNT.PROCESS_ALL_ACCESS;
import static handler.memory.MemoryHandler.openProcess;
public class MemoryHandler {
static final User32 user32 = User32.INSTANCE;
static final Psapi psapi = Psapi.INSTANCE;
public static void main(String[] args) {
int pid = getProcessId("Warcraft III");
HANDLE process = openProcess(PROCESS_ALL_ACCESS, pid);
HMODULE[] hMods = new HMODULE[1024];
psapi.EnumProcessModules(process, hMods, hMods.length, new IntByReference(1024));
List<HMODULE> hModList = Arrays.asList(hMods);
hModList.forEach(hMod ->
System.out.println(Pointer.nativeValue(hMod.getPointer())));
}
public static int getProcessId(String window) {
IntByReference pid = new IntByReference(0);
user32.GetWindowThreadProcessId(user32.FindWindow(null, window), pid);
return pid.getValue();
}
}
,下面是结果:
据我所知,我有一些建议。但是,我应该如何理解其中的哪一个与game.dll
有关?我假设我应该以某种方式得到模块上的列表,在那里我可以看到它们的名称和基本地址。
另外,如果我将System.out.println(Pointer.nativeValue(hMod.getPointer())));
更改为hModList.forEach(System.out::println);
,我会看到以下指针和许多空值(大约1000)。
这些地址是否包含game.dll
的地址?
发布于 2021-09-18 18:51:57
最后,我找到了解决方案,但没有用Java或JNA。我使用C++编写了这段代码,我将在Java中像dll一样使用它。
以下是我的C++代码:
#include <conio.h>
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
#include <psapi.h>
using namespace std;
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;
}
DWORD GetProcessId(LPCTSTR ProcessName) // non-conflicting function name
{
PROCESSENTRY32 pt;
HANDLE hsnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
pt.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hsnap, &pt)) { // must call this first
do {
if (!lstrcmpi(pt.szExeFile, ProcessName)) {
CloseHandle(hsnap);
return pt.th32ProcessID;
}
} while (Process32Next(hsnap, &pt));
}
CloseHandle(hsnap); // close handle on failure
return 0;
}
uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName)
{
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 modEntry;
modEntry.dwSize = sizeof(modEntry);
if (Module32First(hSnap, &modEntry))
{
do
{
if (!_wcsicmp(modEntry.szModule, modName))
{
modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
int main()
{
DWORD pid = GetProcessId(TEXT("war3.exe"));
cout << "Process ID of war3.exe: "<< pid << endl;
DWORD_PTR war3_exe_base_addr = GetProcessBaseAddress(pid);
cout <<"Base address of war3.exe: "<< war3_exe_base_addr << endl;
uintptr_t gameDllBaseAddress = GetModuleBaseAddress(pid, TEXT("game.dll"));
cout <<"Base address of game.dll: " << gameDllBaseAddress << endl;
}
结果是:
发布于 2021-09-13 20:19:38
GetModuleHandle()
只在调用过程中查看。因为game.dll
没有加载到您自己的进程中,所以GetModuleHandle()
找不到它。
要查找在另一个进程中加载的模块,您需要使用以下两种方法:
EnumProcessModules()
/EnumProcessModulesEx()
,使用GetModuleFileNameEx()
获取它们的文件名。见枚举进程的所有模块。CreateToolhelp32Snapshot(TH32CS_SNAPMODULE|TH32CS_SNAPMODULE32)
,使用Module32First()
/Module32Next()
枚举快照。见遍历模块列表。Kernel32Utils.getModules()
使用CreateToolhelp32Snapshot(TH32CS_SNAPMODULE)
,所以如果您的Java作为64位应用程序运行,那么它只会枚举64位模块。但是war3.exe
在屏幕截图中作为32位进程运行,所以如果在64位进程中使用CreateToolhelp32Snapshot()
,则需要使用TH32CS_SNAPMODULE32
。
更新:
正如我前面提到的,如果采用EnumProcessModules()
方法,可以使用GetModuleFileNameEx()
来确定每个模块的文件名。这样,您就可以找到game.dll
的模块。
更重要的是:
openProcess()
请求openProcess()
权限。只要求你真正需要的权利,不再。在本例中,使用PROCESS_QUERY_INFORMATION | PROCESS_VM_READ
代替。EnumProcessModules()
的第四个参数的输出来了解实际存储在数组中的模块数量。EnumProcessModules()
的第3和第4个参数的输入值是错误的,它们需要用字节表示,而不是以元素表示。根据文档
cb
lphModule数组的大小,(以字节为单位)。lpcbNeeded
在数组中存储所有模块句柄所需的字节数。 ..。 指定大量的HMODULE值是个好主意,因为很难预测在调用EnumProcessModules
时流程中会有多少个模块。若要确定lphModule
lpcbNeeded
数组是否太小,无法容纳进程的所有模块句柄,请将lpcbNeeded
中返回的值与cb
**.中指定的值进行比较。如果**lpcbNeeded
大于cb
**,,则增加数组的大小并再次调用**EnumProcessModules
。 确定调用EnumProcessModules
**,所枚举的模块数量的除以sizeof(HMODULE)
.在**lpcbNeeded
参数中的结果值
https://stackoverflow.com/questions/69167015
复制相似问题