Java JNA - 基地址查找

时间:2017-03-28 21:05:17

标签: java memory jna psapi

我目前正在尝试通过使用JNA for Java来读取/写入内存。在过去的一周里,我尝试了大量的解决方案,主要来自我在网上找到的similar projects,但没有解决我的问题。

我知道我收到了程序的正确进程ID,然后使用openProcess方法创建了一个指针。然后我使用新创建的指针调用getBaseAddress。我认为问题在于EnumProcessModules / Psapi方法/类。

说实话,我有点头脑,但这是我对这个程序的最后一个问题。我的总体目标是找到程序的基地址,使用各种偏移来访问我试图修改的信息,然后适当地修改它。该程序是32位,我见过其他人说你需要使用EnumProcessModulesEx方法?但实际上我不确定如何/在何处实施。

任何帮助将不胜感激!

Here is a link to a github of the majority of my project

1 个答案:

答案 0 :(得分:1)

您收到Access Denied错误,因为在访问其他进程的内存之前,Windows要求您在当前进程中enable Debug privilege。因此,在调用OpenProcess代码之前,您需要以管理员,运行程序,启用调试权限。

这是我的应用程序中执行此操作的JNA代码。这是一个静态方法,因为我只为整个应用程序调用一次:

/**
 * Enables debug privileges for this process, required for OpenProcess() to
 * get processes other than the current user
 */
private static void enableDebugPrivilege() {
    HANDLEByReference hToken = new HANDLEByReference();
    boolean success = Advapi32.INSTANCE.OpenProcessToken(Kernel32.INSTANCE.GetCurrentProcess(),
            WinNT.TOKEN_QUERY | WinNT.TOKEN_ADJUST_PRIVILEGES, hToken);
    if (!success) {
        LOG.error("OpenProcessToken failed. Error: {}" + Native.getLastError());
        return;
    }
    WinNT.LUID luid = new WinNT.LUID();
    success = Advapi32.INSTANCE.LookupPrivilegeValue(null, WinNT.SE_DEBUG_NAME, luid);
    if (!success) {
        LOG.error("LookupprivilegeValue failed. Error: {}" + Native.getLastError());
        return;
    }
    WinNT.TOKEN_PRIVILEGES tkp = new WinNT.TOKEN_PRIVILEGES(1);
    tkp.Privileges[0] = new WinNT.LUID_AND_ATTRIBUTES(luid, new DWORD(WinNT.SE_PRIVILEGE_ENABLED));
    success = Advapi32.INSTANCE.AdjustTokenPrivileges(hToken.getValue(), false, tkp, 0, null, null);
    if (!success) {
        LOG.error("AdjustTokenPrivileges failed. Error: {}" + Native.getLastError());
    }
    Kernel32.INSTANCE.CloseHandle(hToken.getValue());
}

我不确定您的代码是否也拥有OpenProcess的正确权限。请确保您拥有VM_READ权限。这是我使用的,你的里程可能会有所不同(我假设你也需要写作权限)。

final HANDLE pHandle = Kernel32.INSTANCE.OpenProcess(
    WinNT.PROCESS_QUERY_INFORMATION | WinNT.PROCESS_VM_READ, 
    false, processID);