前言:
博客好长时间都没有管了,最近放假了,正好有空了。
从学编程之前就对外挂比较感兴趣,刚开始学了一段时间E语言,又后来学了C语言,
上大学之后,找准了目标,主学JAVA和Android,不过对外挂这块儿还是很有兴趣,
就打算用JAVA看看能不能写一个小的游戏修改器,但是因为java是通过JVM虚拟机来运行的,
不能直接操作其他程序的数据,后来了解了一下,可以换一种方式,
那就是通过JNI去调用系统底层的函数,去修改游戏内的数据,
然后我也参考其他的示例代码,用JAVA写了一个简陋的植物大战僵尸的阳光修改器,
可以实现读取阳光值和修改阳光值,那么接下来几天就从JNI到CE找游戏基址到编写游戏修改器。


关于JNI我就不多做介绍了,网上也有很多资料和教程。

工欲善其事,必先利其器。第一步我们肯定要先配置好开发环境了。
jni在github上的开源地址:https://github.com/java-native-access/jna
首先下载jni的jar包配置到我们的eclipse中,下载地址:https://www.lanzous.com/i1brp2b

1.png

首先新建一个java项目,然后在项目里面新建一个文件夹命名为libs,

2.png
然后把我打包好的jni的jar包导入进去,
注意只需导入“jna-4.5.1.jar”和“jna-platform-4.5.1.jar”即可,其他的jar包为帮助文档

Demo1:

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

public class JNITest {
    public static void main(String[] args) {
        //调用printf打印信息
        Clibrary.Instance.printf("Hello,JNA!\n");
    }
    
    //定义接口Clibrary,继承自com.sun.jna.Library
    public interface Clibrary extends Library{
        //定义并初始化接口的静态变量
        Clibrary Instance = (Clibrary)         Native.loadLibrary((Platform.isWindows()?"msvcrt":"c"),Clibrary.class);    
        //printf函数声明
        void printf(String format,Object...args);    
    }

}

3.png

运行这段代码之后,就会调用本地C的动态库的printf函数,然后输出"Hello,JNA!\n"

Demo2:

import com.sun.jna.Native;
import com.sun.jna.win32.StdCallLibrary;

public class JNITest2 {
    public static void main(String[] args) throws InterruptedException {
        int hwnd = User32.INSTANCE.FindWindowA(null, null);
        //设置编码,防止乱码
        System.setProperty("jna.encoding", "GBK");
        
        //调用消息对话框
        User32.INSTANCE.MessageBoxA(hwnd, "闪闪闪", 0, 0);
        
        int i = 0;
        while(true) {
            //阻塞鼠标键盘的输入
            User32.INSTANCE.BlockInput(true);
            
            //关闭显示器
            User32.INSTANCE.SendMessageA(hwnd, 0x0112, 0xF170, 2);
            
            Thread.sleep(2000);
            
            //打开显示器
            User32.INSTANCE.SendMessageA(hwnd, 0x0112, 0xF170, -1);
            
            Thread.sleep(2000);
            
            i++;
            if(i>3) {
                break;
            }    
        }
        //释放鼠标键盘
        User32.INSTANCE.BlockInput(false);
    }
    
    public interface User32 extends StdCallLibrary{
        //加载系统User32 DLL文件 也可以是C++写的DLL文件
        User32 INSTANCE = Native.loadLibrary("User32",User32.class);
        
        int SendMessageA(int hwnd, int msg, int wparam, int lparam);
        int FindWindowA(String arg0, String arg1);
        
        void BlockInput(boolean isBlock);
        
        //对话框
        int MessageBoxA(int hWnd, String IpText, int IpCaption, int uType);

    }
}

执行这段代码,首先会弹出一个对话框,然后屏幕会每隔2秒闪烁一下。
聪明如你,一定发现这两段代码的共同之处,都是自定义一个接口然后继承JNI的类,
然后主函数里面通过创建接口里面的实例,调用系统底层的函数。

最后修改:2023 年 03 月 24 日
如果觉得我的文章对你有用,请随意赞赏