很久以前研究过如何使用java写一个内存读写的程序,但是java都是知道的
它是在虚拟机上进行运行的,所以没办法进行内存的读写
所以用到了jan来执行windows自带的 kernel32.dll程序
感谢
Java - 游戏内存外挂 - 腾讯云开发者社区-腾讯云 (tencent.com)
的相应教程,我只是结合一下目前教程和没有提到的知识
首先引入jar包
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>4.1.0</version>
</dependency>
package cn.ttext.test.wg;
import com.sun.jna.Library;
import java.io.IOException;
public interface MemoryManager extends Library {
int OpenProcess(int processId);
int OpenProcess(String processName) throws IOException;
void CloseHandle(int processId);
int ReadIntProcessMemory(int processId,int address);
int ReadIntProcessMemory(int processId,int ... addresss);
void WriteIntProcessMemory(int processId,long value,int address);
void WriteIntProcessMemory(int processId,long value,int ... addresss);
}
这是接口MemoryManager
MemoryManagerImpl
package cn.ttext.test.wg;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
public class MemoryManagerImpl implements MemoryManager {
private interface Memory extends Library {
Memory INSTANCE = (Memory) Native.loadLibrary("kernel32", Memory.class);
int OpenProcess(int desiredAccess,boolean heritHandle,int pocessID);
void CloseHandle(int process);
boolean ReadProcessMemory(int process, int baseAddress, Pointer buffer, int size, int bytesread);
boolean WriteProcessMemory(int process,int baseAddress,long[] value,int size,int byteswrite);
}
public int OpenProcess(int processId) {
//0x1F0FFF获取最大权限
return Memory.INSTANCE.OpenProcess(0x1F0FFF, false, processId);
}
public int OpenProcess(String processName) throws IOException {
Process process = Runtime.getRuntime().exec("TASKLIST /FI \"IMAGENAME eq " + processName + "\"");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(
new BufferedInputStream(process.getInputStream()), Charset.forName("UTF-8")));
String str;
int pid = -1;
while ((str = bufferedReader.readLine()) != null){
if (str.contains(processName)){
pid = Integer.parseInt(str.substring(processName.length(),str.indexOf("Console")).trim());
}
}
if (pid != -1){
return this.OpenProcess(pid);
}else{
return -1;
}
}
public void CloseHandle(int processId) {
Memory.INSTANCE.CloseHandle(processId);
}
public int ReadIntProcessMemory(int processId, int address) {
Pointer buffer = new com.sun.jna.Memory(4);
Memory.INSTANCE.ReadProcessMemory(processId,address,buffer,4,0);
return buffer.getInt(0);
}
public int ReadIntProcessMemory(int processId, int... addresss) {
int address = 0;
for (int addr:addresss){
address = ReadIntProcessMemory(processId, addr + address);
}
return address;
}
public void WriteIntProcessMemory(int processId, long value, int address) {
Memory.INSTANCE.WriteProcessMemory(processId,address,new long[]{value},4,0);
}
public void WriteIntProcessMemory(int processId, long value, int... addresss) {
int[] t_a = new int[addresss.length - 1];
for (int i = 0; i < t_a.length; i++) {
t_a[i] = addresss[i];
}
WriteIntProcessMemory(processId,value,
this.ReadIntProcessMemory(processId, t_a) + addresss[addresss.length - 1]);
}
}
我们本次使用到的游戏是 植物大战僵尸作为参考
著名:如果需要写其他游戏辅助等,做好还是用其他语言(因为教程很多)
首先,我们需要获取到游戏的pid
其次需要一定的逆向基础等 可以参考其他论坛来学习
并在学习过程中发现各大教程或者讨论贴都没有相应的介绍和详细的使用
因为那些都是只可以获取动态内存,所以说没办法从基地址进行偏移来获取指针的值
现在先拿一个案例来示范和探讨,有错误请指出,看到会改,或者问题 会回复
main方法
//用来获取游戏pid
int process = memoryManager.OpenProcess("PlantsVsZombies.exe");
package cn.ttext.test.wg;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws Exception {
MemoryManager memoryManager = new MemoryManagerImpl();
//打开进程名:PlantsVsZombies.exe
int process = memoryManager.OpenProcess("PlantsVsZombies.exe");
System.out.println("启动成功。。。。。。。。。。");
//向阳光的地址写入数量
memoryManager.WriteIntProcessMemory(process,999999,0x006A9EC0, 0x768, 0x5560);
//清除冷却,每500毫秒清一次
new Thread(()->{
while (true){
for (int i = 0; i < 7; i++) {
memoryManager.WriteIntProcessMemory(process,1,0x006A9EC0, 0x768, 0x144,0x70 + 0x50 * i);
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
//退出进程
//memoryManager.CloseHandle(process);
}
}
好了,问题来了,我想获取CSGO中的矩阵基地址该怎么读呢?
int process = memoryManager.OpenProcess("cstrike.exe");
System.out.println(process);
System.out.println("启动成功。。。。。。。。。。");
//读取矩阵cstrike.exe+1820100
float[] Matrix=new float[16];
Matrix= memoryManager.ReadMatrixProcessMemory(process, 0x1400000+0x1820100);
for (int i=0;i<Matrix.length;i++){
System.out.print(Matrix[i]+"\t");
}
System.out.println();
其次我们要明白 0x1400000是基地址 0x1820100 是偏移量
这就是锁定本地静态地址,每次可便宜到,如果需要画框则需要swing等,请自行研究,仅供学习和参考!
如果有新的我会补充,仅供学习使用!