![]() |
强健的蛋挞 · 爱奇艺封禁暴漫涉侮辱英烈内容:尊重英烈是应尽 ...· 5 月前 · |
![]() |
重情义的豌豆 · 国家金融监督管理总局· 7 月前 · |
![]() |
奔跑的炒面 · 超精密装备研发(管理)工程师-北京国望光学科 ...· 1 年前 · |
![]() |
寂寞的手电筒 · 重温TVB剧《封神榜》,除了殷十娘,竟还有这 ...· 1 年前 · |
![]() |
善良的牛腩 · 国务院安委会通报辽宁盘锦“1·15”重大爆炸 ...· 1 年前 · |
更新的 :参见问题机器人上的更新
我想获得
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
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))
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