Java - 阅读有关另一个程序的信息?
Java - Read information about another program?
所以我想制作一个 Java 程序,可以从另一个程序读取数据。它来自游戏,我无法(据我所知)从文件中获取信息(它是 运行 服务器端)。我该怎么做?目前我正在从屏幕上读取像素,但我认为这不是正确的方法。我能以某种方式访问 RAM 吗?信息将存储在那里。读取像素的问题是它应该在更多计算机上 运行,并且它们不一定具有与 window 相同的分辨率/位置(可能是 windowed 模式)。有什么想法吗?
您实际上正在或多或少地尝试编写一个机器人程序。
我建议尝试找出负责此信息传递的文件 and/or 端口是什么(这可能很难)。
而且我不确定 Java 是最好的方法。 (也许是 Visual Basic?)
Java 不一定是最好的语言。完成你想做的事情的一种方法是制作一个可注入的 DLL,它使用指针从内存中读取或使用 ReadProcessMemory
从外部进程读取内存。
如果您确定要为此使用 Java,您可以使用 JNA Library to access the native method ReadProcessMemory
and you can find the memory addresses using a tool like CheatEngine.
要在 Kernel32
中加载(ReadProcessMemory
方法所在的位置),您必须执行以下操作:
Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
然后您需要知道完成您想要做的事情所需的访问权限,可以在 Microsoft's website 找到。在这种情况下,我们只想读取,因此我们需要的访问权限是 PROCESS_VM_READ (0x0010)
。然后我们可以将这个值存储在一个常量中:
public static final int PROCESS_VM_READ = 0x0010;
那我们再去查一下ReadProcessMemory的语法,发现语法是这样的:
BOOL WINAPI ReadProcessMemory(
_In_ HANDLE hProcess,
_In_ LPCVOID lpBaseAddress,
_Out_ LPVOID lpBuffer,
_In_ SIZE_T nSize,
_Out_ SIZE_T *lpNumberOfBytesRead
);
ReadProcessMemory
采用进程句柄(JNA 中的 Pointer
)、要读取的内存地址(假设我们要从静态值 0x10101AAA82
读取)、缓冲区到读到,值的大小和输出读取的字节数的最后一个值我们将设置为 null
因为我们并不关心。
所以首先,我们要打开一个指向我们要读取的进程的指针,假设您知道进程的 PID:
Pointer process = kernel32.OpenProcess(PROCESS_VM_READ, pid);
现在我们有了进程的句柄(即 ReadProcessMemory
的第一个参数
我们要读取的缓冲区将是 Memory 的一个实例,我们可以通过传入要读取的值的大小来实例化它,假设我想读取 2这种情况下的字节数。
Memory memory = new Memory(2);
我们现在已经获得了读取内存值所需的所有参数:
kernel32.ReadProcessMemory(process, 0x10101AAA82, memory, 2, null);
这意味着我们要从进程 process
的内存地址 0x10101AAA82
读取 2 bytes
到 memory
内存。
现在我们可以得到刚才读到的值了!如果我的值是一个整数,我们可以在 memory
上调用 getInt(offset)
,因为我们想从头开始读取,所以我们将传入 0
作为偏移量。您还可以 运行 getString
、getChar
或 javadoc 中列出的任何内容。现在你有了你的价值!
所以我想制作一个 Java 程序,可以从另一个程序读取数据。它来自游戏,我无法(据我所知)从文件中获取信息(它是 运行 服务器端)。我该怎么做?目前我正在从屏幕上读取像素,但我认为这不是正确的方法。我能以某种方式访问 RAM 吗?信息将存储在那里。读取像素的问题是它应该在更多计算机上 运行,并且它们不一定具有与 window 相同的分辨率/位置(可能是 windowed 模式)。有什么想法吗?
您实际上正在或多或少地尝试编写一个机器人程序。 我建议尝试找出负责此信息传递的文件 and/or 端口是什么(这可能很难)。 而且我不确定 Java 是最好的方法。 (也许是 Visual Basic?)
Java 不一定是最好的语言。完成你想做的事情的一种方法是制作一个可注入的 DLL,它使用指针从内存中读取或使用 ReadProcessMemory
从外部进程读取内存。
如果您确定要为此使用 Java,您可以使用 JNA Library to access the native method ReadProcessMemory
and you can find the memory addresses using a tool like CheatEngine.
要在 Kernel32
中加载(ReadProcessMemory
方法所在的位置),您必须执行以下操作:
Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
然后您需要知道完成您想要做的事情所需的访问权限,可以在 Microsoft's website 找到。在这种情况下,我们只想读取,因此我们需要的访问权限是 PROCESS_VM_READ (0x0010)
。然后我们可以将这个值存储在一个常量中:
public static final int PROCESS_VM_READ = 0x0010;
那我们再去查一下ReadProcessMemory的语法,发现语法是这样的:
BOOL WINAPI ReadProcessMemory(
_In_ HANDLE hProcess,
_In_ LPCVOID lpBaseAddress,
_Out_ LPVOID lpBuffer,
_In_ SIZE_T nSize,
_Out_ SIZE_T *lpNumberOfBytesRead
);
ReadProcessMemory
采用进程句柄(JNA 中的 Pointer
)、要读取的内存地址(假设我们要从静态值 0x10101AAA82
读取)、缓冲区到读到,值的大小和输出读取的字节数的最后一个值我们将设置为 null
因为我们并不关心。
所以首先,我们要打开一个指向我们要读取的进程的指针,假设您知道进程的 PID:
Pointer process = kernel32.OpenProcess(PROCESS_VM_READ, pid);
现在我们有了进程的句柄(即 ReadProcessMemory
我们要读取的缓冲区将是 Memory 的一个实例,我们可以通过传入要读取的值的大小来实例化它,假设我想读取 2这种情况下的字节数。
Memory memory = new Memory(2);
我们现在已经获得了读取内存值所需的所有参数:
kernel32.ReadProcessMemory(process, 0x10101AAA82, memory, 2, null);
这意味着我们要从进程 process
的内存地址 0x10101AAA82
读取 2 bytes
到 memory
内存。
现在我们可以得到刚才读到的值了!如果我的值是一个整数,我们可以在 memory
上调用 getInt(offset)
,因为我们想从头开始读取,所以我们将传入 0
作为偏移量。您还可以 运行 getString
、getChar
或 javadoc 中列出的任何内容。现在你有了你的价值!