java 做外挂 内联汇编

前几天写了个QQ游戏练练看的外挂,不过实现原理很简单,先是从内存中读出练练看的棋盘数据,然后再用算法进行分析,得到两个可以连接的棋子坐标,再用软模拟鼠标在游戏窗口内点击两个棋子。

    如果要做网络游戏的外挂,那么就要找游戏里的CALL,然后再在该游戏进程里注入汇编码,再执行注入的汇编码,来实现调用游戏CALL,那么这里就要用的汇编,其实并不是Java内联汇编,因为在Java里写汇编码,JAVA的JVM是不认识的,现在我们就要用的JNA,在系统函数里有这几个函数:

public HANDLE CreateRemoteThread(W32API.HANDLE hProcess,Structure lpThreadAttributes,int dwStackSize,int lpStartAddress,Structure lpParameter,int dwCreationFlags,IntByReference lpThreadId);

这个函数是调用远程线程。

public int VirtualAllocEx(W32API.HANDLE hProcess,IntByReference lpAddress,int dwSize,int flAllocationType,int flProtect);

这个函数是在指定进程内开辟一段内存空间。

public boolean WriteProcessMemory(W32API.HANDLE hProcess,int lpBaseAddress,byte []lpBuffer,int nSize,IntByReference lpNumberOfBytesWritten);

这个函数是在一段内存空间内,写入指定汇编码。

具体每个参数的意思可以在MSDN里面找到。

刚开始我是用StringBuffer把汇编码组成一个字符串,然后再转换成字节数组,写入内存,在去调用,在测试的时候,发现会把游戏直接送回娘家,游戏直接挂掉,让我纳闷了几个小时,到底是哪里出错了啦?在网上搜索发现,有个牛人已经用JAVA做过内联汇编,查看他的源代码才发现,汇编码不能直接转换成byte数组写入进去,必须要转换成机器码写入才能调用,下面把源码附上:

//获得窗口句柄
  W32API.HWND hwnd=User32.INSTANCE.FindWindow(null, "GameCall");
  //获得窗口进程ID
  IntByReference id=new IntByReference();
  User32.INSTANCE.GetWindowThreadProcessId(hwnd,id);
  //获得进程句柄
  W32API.HANDLE handle=MyKernel32.INSTANCE.OpenProcess(MyKernel32.PROCESS_ALL_ACCESS, false, id.getValue());
  
  //开辟内存空间
  int l=MyKernel32.INSTANCE.VirtualAllocEx(handle, null, 0x3000, 0x1000, 0x40);
  if(l==0){
   System.out.println("分配内存失败");
   return;
  }else{
   System.out.println("分配内存成功");
   System.out.println("内存地址:"+l);
  }
  //编写汇编码
  ASM asm = new ASM();
  //寄存器全部入栈
  asm._PUSHAD();
  //写入CALL汇编码
  asm._CALL(0x401cc0);     //0x401cc0这个是CALL的基址.
  //寄存器全部出栈
  asm._POPAD();
  // 结尾标记,操作开始执行
     asm._RET();
     //将汇编码写入内存
  boolean b=MyKernel32.INSTANCE.WriteProcessMemory(handle, l,ASM.getHexToBytes(asm.getASMCode()), 0x3000, null);
  if(b){
   System.out.println("写入成功");
  }else{
   System.out.println("写入失败");
   return;
  }
  //连续调用写入的汇编码
  for(int i=0;i<50;i++){
   int lpThreadId=0;
   MyKernel32.INSTANCE.CreateRemoteThread(handle, null, 0, l,null , 0, lpThreadId);
   if(lpThreadId==0){
    System.out.println("调用成功");
   }else{
    System.out.println("调用失败");
   }
  }

 

好了,今天就写到这,继续去研究呢。

你可能感兴趣的:(java 做外挂 内联汇编)