Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Windows上使用JNA从Java操作内存_Java_Memory_Jna - Fatal编程技术网

如何在Windows上使用JNA从Java操作内存

如何在Windows上使用JNA从Java操作内存,java,memory,jna,Java,Memory,Jna,如何从Java操作内存?我知道Java在它自己的JVM中运行,所以它不能直接访问进程内存 我听说过JNA,它可以用来获取操作系统和Java代码之间的接口 假设我想操纵纸牌的分数。这种尝试可能是这样的: 获得纸牌的过程 获得对纸牌的记忆 找出分数在内存中的存储位置 在地址中写下我的新值 Java本身无法访问该内存,因此如何使用JNA实现这一点?您需要使用JNA库。两个Jar文件(jna.Jar和jna platform.Jar) 我在pastebin上找到了一个解释如何使用这个库的。但是没有必要阅

如何从Java操作内存?我知道Java在它自己的JVM中运行,所以它不能直接访问进程内存

我听说过JNA,它可以用来获取操作系统和Java代码之间的接口

假设我想操纵纸牌的分数。这种尝试可能是这样的:

  • 获得纸牌的过程
  • 获得对纸牌的记忆
  • 找出分数在内存中的存储位置
  • 在地址中写下我的新值

  • Java本身无法访问该内存,因此如何使用JNA实现这一点?

    您需要使用JNA库。两个Jar文件(jna.Jar和jna platform.Jar)

    我在pastebin上找到了一个解释如何使用这个库的。但是没有必要阅读它来理解以下内容

    比如说,您想要操纵Windows游戏“纸牌”的地址及其值


    知道吗,你是干什么的
  • 如果你想操纵地址及其值,知道你在做什么
    您需要知道存储在地址中的值的大小。是4字节,还是8字节,或者其他

  • 知道如何使用工具获取动态地址和基址。我用

  • 了解基址和动态地址之间的区别:

    • 动态地址将在每次重新启动应用程序(纸牌)时更改。
      它们将包含所需的值,但每次都需要重新查找地址。因此,您首先需要了解的是如何获取基址。
      通过玩CheatEngine教程了解这一点

    • 基址是静态地址。这些地址指向其他地址的方式大致如下:[[base addres+offset]+offset]->value。因此,您需要知道基址,以及需要添加到地址中以获得动态地址的偏移量

  • 现在你知道你需要知道什么了,你用纸牌上的作弊引擎做了一些研究


    您找到了动态地址并搜索了基址?很好,让我们分享我们的结果:

    分数的基址:
    0x10002AFA8

    到达动态地址的偏移量:
    0x50
    (第一个)和
    0x14
    (第二个)

    一切都好吗?好!!让我们继续实际编写一些代码


    创建新项目 在新项目中,需要导入这些库。我使用Eclipse,但它应该可以在任何其他IDE上工作

    用户32接口 感谢Todd Fast,为我们建立了一个。虽然还不完整,但我们需要的已经足够了

    通过这个接口,我们可以在Windows上访问user32.dll的一些函数。 我们需要以下函数:
    FindWindowA
    GetWindowThreadProcessID

    旁注:如果Eclipse告诉您需要添加未实现的方法,只需忽略它并运行代码即可

    内核32接口 感谢Deject3d的支持。我稍微修改了一下

    此接口包含我们用于读取和写入内存的方法
    WriteProcessMemory
    ReadProcessMemory
    。它还包含打开进程的方法
    OpenProcess

    实际操作 我们现在创建一个新类,该类将包含一些helper方法和作为JVM访问点的主函数

    public class SolitaireHack {
    
        public static void main(String... args)
        {
    
        }
    }
    
    让我们填写我们已经知道的东西,比如偏移量和基址

    public class SolitaireHack {
    
        final static long baseAddress = 0x10002AFA8L;
        final static int[] offsets = new int[]{0x50,0x14};
    
        public static void main(String... args)
        {
    
        }
    }
    
    接下来,我们使用界面访问Windows特定的方法:

    导入com.sun.jna.Native

    public class SolitaireHack {
    
        final static long baseAddress = 0x10002AFA8L;
        final static int[] offsets = new int[]{0x50,0x14};
    
        static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32",Kernel32.class);
        static User32 user32 = (User32) Native.loadLibrary("user32", User32.class);
    
        public static void main(String... args)
        {
    
        }
    }
    
    最后但并非最不重要的一点是,我们创建了一些需要的权限常量,以获得对进程进行读写的权限

    import com.sun.jna.Native;
    
    public class SolitaireHack {
    
        final static long baseAddress = 0x10002AFA8L;
        final static int[] offsets = new int[]{0x50,0x14};
    
        static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32",Kernel32.class);
        static User32 user32 = (User32) Native.loadLibrary("user32", User32.class);
    
        public static int PROCESS_VM_READ= 0x0010;
        public static int PROCESS_VM_WRITE = 0x0020;
        public static int PROCESS_VM_OPERATION = 0x0008;
    
        public static void main(String... args)
        {
    
        }
    }
    
    为了得到一个进程,在那里我们可以操作内存,我们需要得到窗口。此窗口可用于获取进程id。使用此id,我们可以打开进程

    public static void main(String... args)
    {
        int pid = getProcessId("Solitaire");
        Pointer process = openProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, pid);
    }
    
    public static int getProcessId(String window) {
         IntByReference pid = new IntByReference(0);
         user32.GetWindowThreadProcessId(user32.FindWindowA(null, window), pid);
    
         return pid.getValue();
    }
    
    public static Pointer openProcess(int permissions, int pid) {
         Pointer process = kernel32.OpenProcess(permissions, true, pid);
         return process;
    }
    
    getProcessId
    方法中,我们使用参数(窗口标题)来查找窗口句柄。(
    FindWindowA
    )此窗口句柄用于获取进程id。IntByReference是指针的JNA版本,将在其中存储进程id

    如果您获得了进程id,可以使用它通过
    openProcess
    打开进程。此方法获取打开进程的权限和pid,并返回指向该进程的指针。要从进程读取,需要权限进程\u VM\u读取;要从进程写入,需要权限进程\u VM\u写入和进程\u VM\u操作

    接下来我们需要得到的是实际地址。动态地址。因此,我们需要另一种方法:

    public static void main(String... args)
    {
        int pid = getProcessId("Solitaire");
        Pointer process = openProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, pid);
    
        long dynAddress = findDynAddress(process,offsets,baseAddress);
    }
    
    public static long findDynAddress(Pointer process, int[] offsets, long baseAddress)
    {
    
        long pointer = baseAddress;
    
        int size = 4;
        Memory pTemp = new Memory(size);
        long pointerAddress = 0;
    
        for(int i = 0; i < offsets.length; i++)
        {
            if(i == 0)
            {
                 kernel32.ReadProcessMemory(process, pointer, pTemp, size, null);
            }
    
            pointerAddress = ((pTemp.getInt(0)+offsets[i]));
    
            if(i != offsets.length-1)
                 kernel32.ReadProcessMemory(process, pointerAddress, pTemp, size, null);
    
    
        }
    
        return pointerAddress;
    }
    
    我们为kernel32方法
    readProcessMemory
    编写了一个包装器。我们知道我们需要读取4字节,因此bytesToRead将为4。在该方法中,将创建并返回一个
    Memory
    对象,该对象的大小为byteToRead,并存储地址中包含的数据。使用
    .getInt(0)
    方法,我们可以读取偏移量0处内存的整数值

    玩一点你的纸牌,并得到一些分数。然后运行代码并读取值。看看这是不是你的分数

    我们的最后一步将是操纵我们的分数。我们想成为最好的。所以我们需要将4字节的数据写入内存

    byte[] newScore = new byte[]{0x22,0x22,0x22,0x22};
    
    这将是我们的新分数
    newScore[0]
    将是最低字节,
    newScore[3]
    将是最高字节。因此,如果您想将分数更改为20,您的
    字节[]
    将是:
    byte[]newScore=新字节[]{0x14,0x00,0x00,0x00}

    让我们把它写在我们的记忆中:

    public static void main(String... args)
    {
        int pid = getProcessId("Solitaire");
        Pointer process = openProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, pid);
    
        long dynAddress = findDynAddress(process,offsets,baseAddress);
    
        Memory scoreMem = readMemory(process,dynAddress,4);
        int score = scoreMem.getInt(0);
        System.out.println(score);
    
        byte[] newScore = new byte[]{0x22,0x22,0x22,0x22};
        writeMemory(process, dynAddress, newScore);
    }
    
    public static void writeMemory(Pointer process, long address, byte[] data)
    {
        int size = data.length;
        Memory toWrite = new Memory(size);
    
        for(int i = 0; i < size; i++)
        {
                toWrite.setByte(i, data[i]);
        }
    
        boolean b = kernel32.WriteProcessMemory(process, address, toWrite, size, null);
    }
    
    用你能做的

    long size = 1L << 40; // 1 TB
    DirectStore store = DirectStore.allocate(size);
    DirectBytes slice = store.createSlice();
    slice.writeLong(0, size);
    slice.writeLong(size - 8, size);
    store.free();
    

    long size=1L
    很多人想用Java操作Windows操作系统上的内存。
    我非常怀疑这一点,但你可以用不安全的或6.0版来完成这一任务
    import com.sun.jna.Memory;
    import com.sun.jna.Native;
    import com.sun.jna.Pointer;
    import com.sun.jna.ptr.IntByReference;
    
    public class SolitaireHack {
    
        final static long baseAddress = 0x10002AFA8L;
        final static int[] offsets = new int[]{0x50,0x14};
    
        static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32",Kernel32.class);
        static User32 user32 = (User32) Native.loadLibrary("user32", User32.class);
    
        public static int PROCESS_VM_READ= 0x0010;
        public static int PROCESS_VM_WRITE = 0x0020;
        public static int PROCESS_VM_OPERATION = 0x0008;
    
        public static void main(String... args)
        {
            int pid = getProcessId("Solitaire");
            Pointer process = openProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, pid);
    
            long dynAddress = findDynAddress(process,offsets,baseAddress);
    
            Memory scoreMem = readMemory(process,dynAddress,4);
            int score = scoreMem.getInt(0);
            System.out.println(score);
    
            byte[] newScore = new byte[]{0x22,0x22,0x22,0x22};
            writeMemory(process, dynAddress, newScore);
        }
    
        public static int getProcessId(String window) {
             IntByReference pid = new IntByReference(0);
             user32.GetWindowThreadProcessId(user32.FindWindowA(null, window), pid);
    
             return pid.getValue();
        }
    
        public static Pointer openProcess(int permissions, int pid) {
             Pointer process = kernel32.OpenProcess(permissions, true, pid);
             return process;
        }
    
        public static long findDynAddress(Pointer process, int[] offsets, long baseAddress)
        {
    
            long pointer = baseAddress;
    
            int size = 4;
            Memory pTemp = new Memory(size);
            long pointerAddress = 0;
    
            for(int i = 0; i < offsets.length; i++)
            {
                if(i == 0)
                {
                     kernel32.ReadProcessMemory(process, pointer, pTemp, size, null);
                }
    
                pointerAddress = ((pTemp.getInt(0)+offsets[i]));
    
                if(i != offsets.length-1)
                     kernel32.ReadProcessMemory(process, pointerAddress, pTemp, size, null);
    
    
            }
    
            return pointerAddress;
        }
    
        public static Memory readMemory(Pointer process, long address, int bytesToRead) {
            IntByReference read = new IntByReference(0);
            Memory output = new Memory(bytesToRead);
    
            kernel32.ReadProcessMemory(process, address, output, bytesToRead, read);
            return output;
        }
    
        public static void writeMemory(Pointer process, long address, byte[] data)
        {
            int size = data.length;
            Memory toWrite = new Memory(size);
    
            for(int i = 0; i < size; i++)
            {
                    toWrite.setByte(i, data[i]);
            }
    
            boolean b = kernel32.WriteProcessMemory(process, address, toWrite, size, null);
        }
    }
    
    long size = 1L << 40; // 1 TB
    DirectStore store = DirectStore.allocate(size);
    DirectBytes slice = store.createSlice();
    slice.writeLong(0, size);
    slice.writeLong(size - 8, size);
    store.free();