我一直在尝试用Java编写客户端代码(我老实说:我的世界)。但这不仅适用于Minecraft,它通常适用于java虚拟机架构,或者我认为。基本上,我使用Cheat Engine查找内存地址,并且我发现了一个似乎与播放器健康价值相对应的地址。
问题是:修改它是不可能的,所以问题是:我做错了什么,或者是否存在限制JVM中内存修改的机制?
为您提供一些背景知识:我使用C#从进程读取/写入内存。我实现这一点的方法是使用kernel.dll提供的外部函数(有关它的更多信息,请访问:https://stackoverflow.com/a/4623200/6817922)。我还有一个简化写作任务的功能:
public static bool Write(IntPtr address, byte[] value)
{
if(ProcessToEdit == null) // If the process is not valid: return with no attempt to edit
{
return false;
}
int bytesWritten = 0;
// Writes the byte[] value to a specified address
return WriteProcessMemory(ProcessPointer, address, value, (uint)value.LongLength, out bytesWritten)
}
但是,当我使用代码运行程序时:
Write(0xCDD9BEA0, new byte[] { 20 }); // 0xCDD9BEA0 is the memory address of health.
程序正确执行并且函数“写入”#39;返回它已成功写入内存地址,但它没有(因为游戏没有更新; Cheat Engine界面也没有)。这只有在我尝试修改JVM进程时才会发生。例如:如果我要编辑流程中的一些文本" notepad",它会正确编辑它,程序会显示更改,以及Cheat Engine。
为了更进一步,JVM进程甚至不允许Cheat Engine修改内存地址;它会立即重置它。所以问题仍然存在:JVM中是否存在阻止其内存被外部修改的机制?
答案 0 :(得分:1)
是的,如果用户有足够的权限(即管理员),您可以修改Java进程的内存。这基本上是操作系统功能; JVM没有做任何事情(也做不到),以防止这种情况发生。
此外,JVM甚至可以协助进行此类修改。有public API将代理程序附加到正在运行的JVM进程;然后代理可以使用标准JNI和JVM TI接口来访问加载的类,修改对象字段,调用任意Java方法等。
我不能说为什么Cheat Engine在你的情况下不起作用 - 这可能是引擎的问题 - 但是有很多可能的原因导致这种情况发生。
例如,您尝试修改的值缓存在寄存器中,而不是从内存中读取。每当值发生变化(在寄存器中)时,它可能会被写回内存,这就是为什么您会看到' reset' 的值。
另请注意,Java对象在内存中不一定具有固定地址。垃圾收集器可以跨堆移动对象,这使得Cheat Engine的工作变得更难。
正确的补丁方式'运行时的Java应用程序将使用标准API,如JNI / JVM TI / Instrumentation API,它可以处理非Java实用程序无法解决的所有情况。