精华内容
下载资源
问答
  • Java外挂开发入门示例

    2019-04-22 01:04:24
    NULL 博文链接:https://smile5098.iteye.com/blog/1935107
  • 若是Java外挂开发,需要导入jacob.jar,外挂开发请使用JRE1.7作为运行环境 若是需要发送邮件,需要导入mail.jar 版本v1.0 日期:2015.2.10 想做辅助软件,被老师忽悠学了Java,目前用Java写辅助的极少以至于...
  • 欢迎下载研究交流,使用步骤:打开进程->输入搜索的数据->开始搜索->改变游戏中的数据->搜索变化->内存修改! 解压后,包含三个文件: ...第三个是打包好的EXE安装包,可以在没有Java环境的电脑上运行
  • java 外挂开发

    2011-05-05 01:02:50
    java 外挂开发包.rar 内涵java调用鼠标键盘 模拟控制包jar文件 全局钩子不需要了,为什么呢..因为java开发出来的是javaw进程的....一般杀毒软件都不会报..所以都不用担心客户端了...快下吧..你伤不起,也等不起......
  • 独门绝技之使用Java语言开发游戏外挂脚本。如果要编写出强大的挂机脚本程序,需要大量的算法和完善的代码架构。此时就需要借助于java面向对象的编程思想来完成。
  • Java外挂开发之内存修改器(类似CE)

    万次阅读 多人点赞 2016-12-09 21:44:55
    当然我只会Java,C++嘛,了解了解,嘿嘿,所以这个工具也是用Java写的 这个工具在写内存搜索时,简直累死了,最开始暴力搜索,效率慢的要死,经过三天的不懈努力,终于搞定这搜索功能!这也是整个工具最难的部分,...

    最近闲着蛋疼,无聊之中用CE耍了一哈游戏,发现挺好用的,于是就想,我自己能不能写个内存修改器呢?于是乎,这个软件就诞生了!

    当然我只会Java,C++嘛,了解了解,嘿嘿,所以这个工具也是用Java写的大笑


    这个工具在写内存搜索时,简直累死了,最开始暴力搜索,效率慢的要死,经过三天的不懈努力,终于搞定这搜索功能!这也是整个工具最难的部分,至少我是这么认为的

    微软的MSDN都被我翻了又翻 - - !


    完整源码和项目我已上传csdn

    http://download.csdn.net/detail/qq969422014/9707030

    下载解压后的目录结构:

    第一个是源代码:用Eclipse导入即可,记得修改Build Path

    第二个是打包好的Jar,如果电脑安装了Java,就可以直接运行

    第三个是打包好的exe安装程序,可以在没有安装Java的电脑上运行


    不多说了,先上一张效果图: (这里用植物大战僵尸做实验,4399的小游戏)

    原来阳光是150,被我改成1024了


    先说说这个软件的使用步骤吧,与CE用法差不多,先打开游戏进程,输入搜索的游戏值(比如这里改阳光,所以输入150),然后开始搜索,搜索完成后,种一柱植物,或者捡一个阳光,总之让阳光值发生变化,然后再点击搜索变化,地址就出来啦,最后,鼠标点击,输入修改值,点击写入内存就可以咯吐舌头如果搜索变化没有,就多搜两次哦


    本工具开发环境如下:

    开发工具:Eclipse

    开发语言:Java

    开发系统:windows7

    JDK版本:1.6


    项目所需的第三方包:

    官网下载JNA包:https://github.com/java-native-access/jna   这个包用于调用windows系统函数库

    官网下载皮肤包:http://www.jtattoo.net/   这个包是Swing的皮肤包,用于做界面用的


    代码实现大致思路如下:

    获取Debug权限->创建系统快照->获取进程ID->获取进程在内存中的首地址与结束地址->打开进程->遍历内存->查找数据->修改数据


    项目包目录如下:


    entity 这是实体包

    event 这是窗体的事件监听相应包

    impl 功能的核心实现

    interfaces C++ API函数接口定义

    quantity C++ API函数常量描述

    structure C++结构体描述

    wnd 软件界面


    下面开始给出关键代码:

    代码一:获取Debug权限,这里可以理解为赋予软件管理员,如果不获取Debug权限,会导致有些进程可能会拒绝访问

    	/**
    	 * processHandle 需要给予的进程句柄
    	 * privilegeValue 特权值,详情请参阅LookupPrivilegeValue接口
    	 * **/
    	public ExecuteResult give(int processHandle,String privilegeValue)
    	{
    		ExecuteResult executeResult = new ExecuteResult();
    		//创建令牌句柄指針,用于保存OpenProcessToken函数返回的令牌
    		HANDLEByReference tokenHandle = new HANDLEByReference();
    		try 
    		{
    			//打开进程令牌,用于查询和修改令牌
    			if(Advapi32_DLL.INSTANCE.OpenProcessToken(processHandle, OpenProcessToken.TOKEN_ADJUST_PRIVILEGES|OpenProcessToken.TOKEN_QUERY, tokenHandle))
    			{
    				//创建一个令牌特权,初始化为1,用于保存LookupPrivilegeValue函数返回的令牌特权
    				TOKEN_PRIVILEGES tkp = new TOKEN_PRIVILEGES(1);
    				//初始化令牌特LUID值
    				tkp.Privileges[0] = new LUID_AND_ATTRIBUTES();
    				tkp.Privileges[0].Luid = new LUID();
    			    tkp.Privileges[0].Attributes = OpenProcessToken.SE_PRIVILEGE_ENABLED;
    			    //查看系统权限的特权值,返回到tkp LUID
    				if(Advapi32_DLL.INSTANCE.LookupPrivilegeValue(null, privilegeValue, tkp.Privileges[0].Luid))
    				{
    					//告诉系统启用该令牌
    					Advapi32_DLL.INSTANCE.AdjustTokenPrivileges(tokenHandle.getValue(), false, tkp, tkp.size(), null, null);
    				}
    			}
    		} 
    		finally 
    		{
    			//释放令牌指针
    			ReferenceFree.free(tokenHandle);
    			//获取执行结果
    			executeResult.setLastError(Kernel32_DLL.INSTANCE.GetLastError());
    			//释放句柄资源
    			Kernel32_DLL.INSTANCE.CloseHandle(processHandle);
    		}
    		return executeResult;
    	}

    代码二:创建系统快照,获取系统进程相关信息

    	/**
    	 * 得到系统进程列表
    	 * */
    	public ExecuteResult getProcess()
    	{
    		ExecuteResult executeResult = new ExecuteResult();
    		//获取结果集
    		List<Process> list = new ArrayList<Process>();
    		//创建当前系统进程快照,返回快照句柄,具体参考com.memory.interfaces.Kernel32_DLL中的描述
    		int processHandle = Kernel32_DLL.INSTANCE.CreateToolhelp32Snapshot(CreateToolhelp32Snapshot.TH32CS_SNAPPROCESS, 0);
    		//快照結果
    		int lastError = Kernel32_DLL.INSTANCE.GetLastError();
    		if(processHandle==0 || lastError!=0)
    		{
    			executeResult.setLastError(lastError);
    			executeResult.setMessage("获取系统进程信息失败,错误代码:"+lastError);
    			return executeResult;
    		}
    		try 
    		{
    			//创建进程结构体,用于保存进程的相关信息,具体参考com.memory.entity.Process中的描述
    			PROCESSENTRY32 lppe = new PROCESSENTRY32();
    			//根据快照句柄遍历系统进程
    			while(Kernel32_DLL.INSTANCE.Process32Next(processHandle, lppe))
    			{
    				Process temp = new Process();
    				temp.setProcessName(lppe.getSzExeFileStr());
    				temp.setPid(lppe.th32ProcessID);
    				list.add(temp);
    			}
    			if(list.size()!=0)
    			{
    				executeResult.setValue(list);
    			}
    			else
    			{
    				lastError = Kernel32_DLL.INSTANCE.GetLastError();
    				executeResult.setLastError(lastError);
    				executeResult.setMessage("获取系统进程信息失败,错误代码:"+lastError);
    			}
    		} 
    		finally
    		{
    			//释放句柄资源
    			Kernel32_DLL.INSTANCE.CloseHandle(processHandle);
    		}
    		return executeResult;
    	}

    代码三: 获取进程的开始内存地址与结束内存地址,获取系统的内存地址

    	/**
    	 * 查询进程在内存中的开始地址与结束地址
    	 * **/
    	public ExecuteResult queryProcessRange(int pid)
    	{
    		ExecuteResult executeResult = new ExecuteResult();
    		//创建内存范围对象
    		MemoryRange range = new MemoryRange();
    		//创建进程模版快照,查询应用程序的在内存中的基地址
    		int handleModule = Kernel32_DLL.INSTANCE.CreateToolhelp32Snapshot(CreateToolhelp32Snapshot.TH32CS_SNAPMODULE, pid);
    		//快照执行结果
    		int lastError = Kernel32_DLL.INSTANCE.GetLastError();
    		executeResult.setLastError(lastError);
    		//判断结果
    		if(lastError==5)
    		{
    			executeResult.setMessage("无法打开进程,系统Debug权限获取失败,请以管理员方式重新运行程序!");
    			return executeResult;
    		}
    		//如果为299,说明只有部分权限,判断该进程是否是64位进程
    		else if(lastError==299)
    		{
    			//声明INT指针,保存IsWow64Process返回的值
    			IntByReference Wow64Process = new IntByReference();
    			int handle = Kernel32_DLL.INSTANCE.OpenProcess(OpenProcess.PROCESS_ALL_ACCESS, false, pid);
    			if(Kernel32_DLL.INSTANCE.IsWow64Process(handle, Wow64Process))
    			{
    				//如果为64位进程,那么久获取系统的内存范围
    				if(Wow64Process.getValue()==0)
    				{
    					executeResult = querySystemRange();
    				}
    			}
    			else
    			{
    				executeResult.setMessage("无法打开该进程,错误代码:"+lastError);
    			}
    			//释放内存
    			ReferenceFree.free(Wow64Process);
    			Kernel32_DLL.INSTANCE.CloseHandle(handle);
    			return executeResult;
    		}
    		else if(lastError!=0)
    		{
    			executeResult.setMessage("无法打开该进程,OpenProcess函数返回错误码:"+lastError);
    			return executeResult;
    		}
    		try 
    		{
    			MODULEENTRY32 lpme = new MODULEENTRY32();
    			if(Kernel32_DLL.INSTANCE.Module32First(handleModule, lpme))
    			{
    				range.setMinValue(lpme.modBaseAddr);
    				if(Kernel32_DLL.INSTANCE.Module32Next(handleModule, lpme))
    				{
    					range.setMaxValue(lpme.modBaseAddr);
    				}
    			}
    			//执行结果返回值
    			executeResult.setValue(range);
    			//执行结果
    			lastError = Kernel32_DLL.INSTANCE.GetLastError();
    			if(range.getMinValue() == 0 && lastError!=0)
    			{
    				executeResult.setLastError(lastError);
    				executeResult.setMessage("Module32Next失败,错误代码:"+lastError);
    			}
    				
    		} 
    		finally 
    		{
    			//释放快照
    			Kernel32_DLL.INSTANCE.CloseHandle(handleModule);
    		}
    		return executeResult;
    	}
    	
    	/**
    	 * 查询当前系统的可搜索的开始地址与结束地址
    	 * **/
    	public ExecuteResult querySystemRange()
    	{
    		ExecuteResult executeResult = new ExecuteResult();
    		//创建内存范围对象
    		MemoryRange range = new MemoryRange();
    		//创建描述系统信息的结构
    		SYSTEM_INFO info = new SYSTEM_INFO();
    		//获取系统内存范围
    		Kernel32_DLL.INSTANCE.GetSystemInfo(info);
    		range.setMinValue(Pointer.nativeValue(info.lpMinimumApplicationAddress));
    		range.setMaxValue(Pointer.nativeValue(info.lpMaximumApplicationAddress));
    		//返回值
    		executeResult.setValue(range);
    		//调用结果
    		int lastError = Kernel32_DLL.INSTANCE.GetLastError();
    		if(lastError!=0)
    		{
    			executeResult.setLastError(lastError);
    			executeResult.setMessage("获取系统内存地址范围失败,错误代码:"+lastError);
    		}
    		return executeResult;
    	}

    代码四:搜索内存,也是最核心的部分,个人感觉也是最难的部分,可能是之前没做个之类的软件吧,反正耗费我三天,头都要炸了

    package com.memory.impl;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import com.memory.entity.ExecuteResult;
    import com.memory.entity.MemoryValue;
    import com.memory.interfaces.Kernel32_DLL;
    import com.memory.quantity.OpenProcess;
    import com.memory.quantity.VirtualProtect;
    import com.memory.structure.MEMORY_BASIC_INFORMATION;
    import com.sun.jna.Memory;
    import com.sun.jna.Pointer;
    
    /**
     * 内存搜索实现类
     * 作者:Code菜鸟
     * 技术交流QQ:969422014
     * CSDN博客:http://blog.csdn.net/qq969422014
     * */
    public class MemorySearchImpl
    {	
    	//保存查询内存结果信息的结构体类
    	private MEMORY_BASIC_INFORMATION memoryInfo = new MEMORY_BASIC_INFORMATION();
    	//查询结果的大小
    	private int size = memoryInfo.size();
    	//统计内存扫描数量
    	public int memoryScore = 0;
    	//保存搜索
    	public List<MemoryValue> searchResult = Collections.synchronizedList(new ArrayList<MemoryValue>());
    	
    	/**
    	 * 值搜索
    	 * pid 进程ID
    	 * value 需要搜索的值
    	 * searchDataType 搜索的实际数据类型 0=INT 1=Short 2=long 3=float 4=double 5=byte
    	 * equalsSearchValue 与搜索值相比较 0等于,1大于,2小于
    	 * startBaseAddr 搜索开始的内存基址
    	 * endBaseAddr 搜索结束的内存基址
    	 * increasing 搜索地址的递增量
    	 * **/
    	public ExecuteResult search(int pid,String searchValue,int searchDataType,int equalsSearchValue,int startBaseAddr,int endBaseAddr)
    	{
    		if(searchResult.size()!=0) searchResult.clear();
    		ExecuteResult executeResult = new ExecuteResult();
    		memoryScore = 0;
    		//根据进程ID,打开进程,返回进程句柄
    		int handle = Kernel32_DLL.INSTANCE.OpenProcess(OpenProcess.PROCESS_ALL_ACCESS, false, pid);
    		//判断进程句柄是否打开成功
    		int lastError = Kernel32_DLL.INSTANCE.GetLastError();
    		executeResult.setLastError(lastError);
    		if(lastError==5)
    		{
    			executeResult.setMessage("无法打开进程,系统Debug权限获取失败,请以管理员方式重新运行程序!");
    			return executeResult;
    		}
    		else if(lastError!=0)
    		{
    			executeResult.setMessage("无法打开该进程,OpenProcess函数返回错误码:"+lastError);
    			return executeResult;
    		}
    		try 
    		{
    			//根据基址遍历内存
    			while(startBaseAddr <= endBaseAddr)
    			{
    				//读取内存信息
    				int vqe = Kernel32_DLL.INSTANCE.VirtualQueryEx(handle, startBaseAddr, memoryInfo, size);
    				if(vqe==0) break;
    				//判断内存是否已提交,非空闲内存		
    		        if (memoryInfo.state == MEMORY_BASIC_INFORMATION.MEM_COMMIT)
    		        {
    		        	//更改内存保护属性为可写可读,成功返回TRUE,执行这个函数,OpenProcess函数必须为PROCESS_ALL_ACCESS
    		        	boolean vpe = Kernel32_DLL.INSTANCE.VirtualProtectEx(handle, startBaseAddr, memoryInfo.regionSize, VirtualProtect.PAGE_READWRITE, memoryInfo.protect);
    		        	//判断内存是否可读可写
    		        	if(vpe || memoryInfo.protect == MEMORY_BASIC_INFORMATION.PAGE_READWRITE)
    		        	{
    		        		//声明一块内存空间,保存读取内存块的值,这个空间的大小与内存块大小相同
    		        		Pointer buffer = new Memory(memoryInfo.regionSize);
    		        		//判断是否读取成功
    		        		if(Kernel32_DLL.INSTANCE.ReadProcessMemory(handle, startBaseAddr, buffer, memoryInfo.regionSize, 0))
    		        		{	
    	                		//对比的值
    	                		double searchValueDouble = Double.parseDouble(searchValue);
    							//根据搜索类型查找对应数据
    							switch(searchDataType)
    							{
    							//查找整形int,4字节,所以i+=4
    							case 0:
    			        			for(int i = 0; i < memoryInfo.regionSize; i+=4) 
    			        		    { 
    			        				double memoryValue = buffer.getInt(i);
    			                		//统计内存数量
    			                		memoryScore++;
    			                		//与搜索值相比较释放符合条件 0等于,1大于,2小于
    			                		if((equalsSearchValue ==0 &&  memoryValue == searchValueDouble) || 
    			                				   (equalsSearchValue==1 && memoryValue > searchValueDouble) ||
    			                				   (equalsSearchValue==2 && memoryValue < searchValueDouble))
    			                		{
    			                			MemoryValue temp = new MemoryValue();
    			                			temp.setAddress(startBaseAddr + i);
    			                			temp.setAddress16("0x"+Long.toString((startBaseAddr + i), 16).toUpperCase());
    			                			temp.setValue(memoryValue+"");
    			                			searchResult.add(temp);
    			                		}
    			        		    }
    								break;
    							//查找短整形short,2字节,所以i+=2
    							case 1:
    			        			for(int i = 0; i < memoryInfo.regionSize; i+=2) 
    			        		    { 
    			        				double memoryValue = buffer.getShort(i);
    			                		//统计内存数量
    			                		memoryScore++;
    			                		//与搜索值相比较释放符合条件 0等于,1大于,2小于
    			                		if((equalsSearchValue ==0 &&  memoryValue == searchValueDouble) || 
    			                				   (equalsSearchValue==1 && memoryValue > searchValueDouble) ||
    			                				   (equalsSearchValue==2 && memoryValue < searchValueDouble))
    			                		{
    			                			MemoryValue temp = new MemoryValue();
    			                			temp.setAddress(startBaseAddr + i);
    			                			temp.setAddress16("0x"+Long.toString((startBaseAddr + i), 16).toUpperCase());
    			                			temp.setValue(memoryValue+"");
    			                			searchResult.add(temp);
    			                		}
    			        		    }
    								break;
    							//查找长整形Long,8字节,所以i+=8
    							case 2:
    			        			for(int i = 0; i < memoryInfo.regionSize; i+=8) 
    			        		    { 
    			        				double memoryValue = buffer.getLong(i);
    			                		//统计内存数量
    			                		memoryScore++;
    			                		//与搜索值相比较释放符合条件 0等于,1大于,2小于
    			                		if((equalsSearchValue ==0 &&  memoryValue == searchValueDouble) || 
    			                				   (equalsSearchValue==1 && memoryValue > searchValueDouble) ||
    			                				   (equalsSearchValue==2 && memoryValue < searchValueDouble))
    			                		{
    			                			MemoryValue temp = new MemoryValue();
    			                			temp.setAddress(startBaseAddr + i);
    			                			temp.setAddress16("0x"+Long.toString((startBaseAddr + i), 16).toUpperCase());
    			                			temp.setValue(memoryValue+"");
    			                			searchResult.add(temp);
    			                		}
    			        		    }
    								break;
    							//查找单精度浮点 float,4字节,所以i+=4
    							case 3:
    			        			for(int i = 0; i < memoryInfo.regionSize; i+=4) 
    			        		    { 
    			        				double memoryValue = buffer.getFloat(i);
    			                		//统计内存数量
    			                		memoryScore++;
    			                		//与搜索值相比较释放符合条件 0等于,1大于,2小于
    			                		if((equalsSearchValue ==0 &&  memoryValue == searchValueDouble) || 
    			                				   (equalsSearchValue==1 && memoryValue > searchValueDouble) ||
    			                				   (equalsSearchValue==2 && memoryValue < searchValueDouble))
    			                		{
    			                			MemoryValue temp = new MemoryValue();
    			                			temp.setAddress(startBaseAddr + i);
    			                			temp.setAddress16("0x"+Long.toString((startBaseAddr + i), 16).toUpperCase());
    			                			temp.setValue(memoryValue+"");
    			                			searchResult.add(temp);
    			                		}
    			        		    }
    								break;
    							//查找双精度浮点 double,8字节,所以i+=8
    							case 4:
    			        			for(int i = 0; i < memoryInfo.regionSize; i+=8) 
    			        		    { 
    			        				double memoryValue = buffer.getDouble(i);
    			                		//统计内存数量
    			                		memoryScore++;
    			                		//与搜索值相比较释放符合条件 0等于,1大于,2小于
    			                		if((equalsSearchValue ==0 &&  memoryValue == searchValueDouble) || 
    			                				   (equalsSearchValue==1 && memoryValue > searchValueDouble) ||
    			                				   (equalsSearchValue==2 && memoryValue < searchValueDouble))
    			                		{
    			                			MemoryValue temp = new MemoryValue();
    			                			temp.setAddress(startBaseAddr + i);
    			                			temp.setAddress16("0x"+Long.toString((startBaseAddr + i), 16).toUpperCase());
    			                			temp.setValue(memoryValue+"");
    			                			searchResult.add(temp);
    			                		}
    			        		    }
    								break;
    							//查找字节byte,1字节,所以i++
    							case 5:
    			        			for(int i = 0; i < memoryInfo.regionSize; i++) 
    			        		    { 
    			        				double memoryValue = buffer.getByte(i);
    			                		//统计内存数量
    			                		memoryScore++;
    			                		//与搜索值相比较释放符合条件 0等于,1大于,2小于
    			                		if((equalsSearchValue ==0 &&  memoryValue == searchValueDouble) || 
    			                				   (equalsSearchValue==1 && memoryValue > searchValueDouble) ||
    			                				   (equalsSearchValue==2 && memoryValue < searchValueDouble))
    			                		{
    			                			MemoryValue temp = new MemoryValue();
    			                			temp.setAddress(startBaseAddr + i);
    			                			temp.setAddress16("0x"+Long.toString((startBaseAddr + i), 16).toUpperCase());
    			                			temp.setValue(memoryValue+"");
    			                			searchResult.add(temp);
    			                		}
    			        		    }
    								break;
    							}
    		        		}
    		        		//释放内存
    		        		ReferenceFree.free(buffer);
    		        	}
    		        }
    			    //设置基地址偏移
    		        startBaseAddr = (int) Pointer.nativeValue(memoryInfo.baseAddress) + memoryInfo.regionSize; 
    			}
    		}
    		catch (Exception e)
    		{
    			e.printStackTrace();
    			executeResult.setLastError(-1);
    			executeResult.setMessage("内存地址扫描错误!\n"+e.getMessage());
    			return executeResult;
    		}
    		finally
    		{
    			//释放资源
    			Kernel32_DLL.INSTANCE.CloseHandle(handle);
    		}
    		return executeResult;
    	}
    	
    	/**
    	 * 再次搜索实现
    	 * pid 进程ID
    	 * addressList 搜索的内存地址列表
    	 * searchDataType 搜索的数据类型
    	 * **/
    	public ExecuteResult search(int pid,List<MemoryValue> addressList,int searchDataType)
    	{
    		ExecuteResult executeResult = new ExecuteResult();
    		if(searchResult.size()!=0) searchResult.clear();
    		memoryScore = 0;
    		//获取进程句柄
    		int handle = Kernel32_DLL.INSTANCE.OpenProcess(OpenProcess.PROCESS_ALL_ACCESS, false,pid);
    		try
    		{
    			//保存读取的新值
    			Map<String,MemoryValue> tableValueMap = new HashMap<String,MemoryValue>();
    			//声明一块内存,保存读取值
    			Pointer readResult = new Memory(1024);
    			for(int i = 0;i<addressList.size();i++)
    			{
    				memoryScore++;
    				//将0xffff table中的值转换为int类型
    				int temp = Integer.parseInt(addressList.get(i).getAddress16().replace("0x", ""),16);
    				if(Kernel32_DLL.INSTANCE.ReadProcessMemory(handle, temp, readResult, 1024, 0))
    				{
    					MemoryValue m = new MemoryValue();
    					m.setAddress(temp);
    					m.setAddress16("0x"+(Integer.toString(temp, 16).toUpperCase()));
    					//根据搜索类型读取对应数据
    					switch(searchDataType)
    					{
    					//整形int
    					case 0:
    						m.setValue(readResult.getInt(0)+"");
    						break;
    					//短整形short
    					case 1:
    						m.setValue(readResult.getShort(0)+"");
    						break;
    					//长整形Long
    					case 2:
    						m.setValue(readResult.getLong(0)+"");
    						break;
    					//单精度浮点 float
    					case 3:
    						m.setValue(readResult.getFloat(0)+"");
    						break;
    					//双精度浮点 double
    					case 4:
    						m.setValue(readResult.getDouble(0)+"");
    						break;
    					//字节byte
    					case 5:
    						m.setValue(readResult.getByte(0)+"");
    						break;
    					}
    					tableValueMap.put(m.getAddress16(), m);
    				}
    			}
    			//释放内存
    			ReferenceFree.free(readResult);
    			//移除列表中没有发生变化的内存值
    			for(int i = 0;i<addressList.size();i++)
    			{
    				String key = addressList.get(i).getAddress16();
    				String value = addressList.get(i).getValue();
    				if(tableValueMap.get(key)!=null
    						&& Double.parseDouble(tableValueMap.get(key).getValue())==Double.parseDouble(value))
    				{
    					tableValueMap.remove(key);
    				}
    			}
    			//搜索结果
    			for(String key:tableValueMap.keySet())
    			{
    				searchResult.add(tableValueMap.get(key));
    			}
    			executeResult.setLastError(Kernel32_DLL.INSTANCE.GetLastError());
    			if(executeResult.getLastError()!=0)
    			{
    				executeResult.setMessage("搜索内存发生错误!错误代码:"+executeResult.getLastError());
    			}
    		} 
    		catch (Exception e)
    		{
    			e.printStackTrace();
    			executeResult.setLastError(-1);
    			executeResult.setMessage("内存地址扫描错误!\n"+e.getMessage());
    		}
    		finally
    		{
    			//资源释放
    			Kernel32_DLL.INSTANCE.CloseHandle(handle);
    		}
    		return executeResult;
    	}
    }
    

    代码五:内存的写实现

    package com.memory.impl;
    
    import com.memory.entity.ExecuteResult;
    import com.memory.interfaces.Kernel32_DLL;
    import com.memory.quantity.OpenProcess;
    import com.memory.structure.MEMORY_BASIC_INFORMATION;
    import com.sun.jna.Memory;
    import com.sun.jna.Pointer;
    
    /**
     * 内存的写实现类
     * 作者:Code菜鸟
     * 技术交流QQ:969422014
     * CSDN博客:http://blog.csdn.net/qq969422014
     * */
    public class MemoryWrite 
    {	
    	/**
    	 * 写入内存实现方法
    	 * pid 进程ID
    	 * lpBaseAddress 写入地址
    	 * value 写入值
    	 * dataType 数据类型,这个值确定value的实际数据类型
    	 * **/
    	public ExecuteResult write(int pid,int lpBaseAddress,String value,int dataType)
    	{
    		ExecuteResult result = new ExecuteResult();
    		int hProcess = Kernel32_DLL.INSTANCE.OpenProcess(OpenProcess.PROCESS_ALL_ACCESS, false, pid);
    		//判断进程句柄是否打开成功
    		int lastError = Kernel32_DLL.INSTANCE.GetLastError();
    		result.setLastError(lastError);
    		if(lastError==5)
    		{
    			result.setMessage("进程拒绝访问,可能是系统Debug权限获取失败,请以管理员方式重新运行程序!");
    			return result;
    		}
    		else if(lastError!=0)
    		{
    			result.setMessage("无法打开该进程,错误代码:"+lastError);
    			return result;
    		}
    		try 
    		{
    			//判断内存地址是否合法幷且是否满足读写权限
    			MEMORY_BASIC_INFORMATION lpBuffer = new MEMORY_BASIC_INFORMATION();
    			Kernel32_DLL.INSTANCE.VirtualQueryEx(hProcess, lpBaseAddress, lpBuffer, lpBuffer.size());
    			if(!(lpBuffer.state == MEMORY_BASIC_INFORMATION.MEM_COMMIT 
    					&& lpBuffer.protect == MEMORY_BASIC_INFORMATION.PAGE_READWRITE))
    			{
    				result.setLastError(-1);
    				result.setMessage("内存地址不存在或者该内存无法读写!");
    				return result;
    			}
    			//新内存地址,用于写入内存用
    			Pointer updatePointer = null;
    			int size = 4;
    			switch(dataType)
    			{
    			//整形int
    			case 0:
    				size = 4;
    				updatePointer = new Memory(size);
    				updatePointer.setInt(0, Integer.parseInt(value));
    				break;
    			//短整形short
    			case 1:
    				size = 2;
    				updatePointer = new Memory(size);
    				updatePointer.setShort(0, Short.parseShort(value));
    				break;
    			//长整形Long
    			case 2:
    				size = 8;
    				updatePointer = new Memory(size);
    				updatePointer.setLong(0, Long.parseLong(value));
    				break;
    			//单精度浮点 float
    			case 3:
    				size = 4;
    				updatePointer = new Memory(size);
    				updatePointer.setFloat(0, Float.parseFloat(value));
    				break;
    			//双精度浮点 double
    			case 4:
    				size = 8;
    				updatePointer = new Memory(size);
    				updatePointer.setDouble(0, Double.parseDouble(value));
    				break;
    			//字节byte
    			case 5:
    				size = 1;
    				updatePointer = new Memory(size);
    				updatePointer.setByte(0, Byte.parseByte(value));
    				break;
    			}
    			//写入内存
    			boolean writeResult = Kernel32_DLL.INSTANCE.WriteProcessMemory(hProcess, lpBaseAddress, updatePointer, size, 0);
    			//是否写入成功
    			lastError = Kernel32_DLL.INSTANCE.GetLastError();
    			if((!writeResult) || lastError!=0)
    			{
    				result.setLastError(lastError);
    				result.setMessage("内存写入发生错误,错误代码:"+lastError);
    				return result;
    			}
    			result.setLastError(0);
    			result.setMessage("写入成功!");
    			return result;
    		} 
    		catch (Exception e)
    		{
    			result.setLastError(-1);
    			result.setMessage("写入失败,请检查输入值是否正确或超出范围!\n错误代码:"+e.getMessage());
    		}
    		finally
    		{
    			Kernel32_DLL.INSTANCE.CloseHandle(hProcess);
    		}
    		return result;
    	}
    }
    

    代码六:进程的杀死实现

    package com.memory.impl;
    
    import com.memory.entity.ExecuteResult;
    import com.memory.interfaces.Kernel32_DLL;
    import com.memory.quantity.OpenProcess;
    import com.sun.jna.ptr.IntByReference;
    
    /**
     * 进程杀死实现类
     * 作者:Code菜鸟
     * 技术交流QQ:969422014
     * CSDN博客:http://blog.csdn.net/qq969422014
     * */
    public class KillProcess 
    {
    	/**
    	 * 具体解释,请查看com.memory.interfaces.Kernel32_DLL接口中的描述
    	 * pid 进程ID,这个值可以通过任务管理器查看或通过CreateToolhelp32Snapshot函数获取
    	 * **/
    	public ExecuteResult kill(int pid)
    	{
    		ExecuteResult executeResult = new ExecuteResult();
    		int hProcess = Kernel32_DLL.INSTANCE.OpenProcess(OpenProcess.PROCESS_ALL_ACCESS, false, pid);
    		//INT指针,保存GetExitCodeProcess函数调用成功后,返回的程序退出值
    		IntByReference lpExitCode = new IntByReference();
    		try 
    		{
    			//获取程序的退出代码
    			if(Kernel32_DLL.INSTANCE.GetExitCodeProcess(hProcess, lpExitCode))
    			{
    				//退出程序
    				Kernel32_DLL.INSTANCE.TerminateProcess(hProcess, lpExitCode.getValue());
    			}
    		}
    		finally
    		{
    			//释放INT指针
    			ReferenceFree.free(lpExitCode);
    			Kernel32_DLL.INSTANCE.CloseHandle(hProcess);
    		}
    		//获取执行结果
    		int lastError = Kernel32_DLL.INSTANCE.GetLastError();
    		executeResult.setLastError(lastError);
    		if(lastError!=0)
    			executeResult.setMessage("杀死进程时发生错误,错误代码:"+lastError);
    		return executeResult;
    	}
    }
    



    展开全文
  • 若是Java外挂开发,需要导入jacob.jar,外挂开发请使用JRE1.7作为开发环境,建议使用 http://www.xnx3.com/doc/jre1.7.html 若其他地方下载的JRE1.7出错,请下载这里给的链接的 若是需要发送邮件,需要导入mail.jar...
  • //此处为我的包名删除即可//以下三个包需要导入JNA库,JNA的官网:https://github.com/java-native-access/jna#jna//JNA的安装链接:https://pan.baidu.com/s/1qNRGLU06V1oAx3gp0uKBBg 密码:pfbz 该链接有效时间为7...

    package plugin.com;                //此处为我的包名删除即可


    //以下三个包需要导入JNA库,JNA的官网:https://github.com/java-native-access/jna#jna
    //JNA的安装链接:https://pan.baidu.com/s/1qNRGLU06V1oAx3gp0uKBBg 密码:pfbz   该链接有效时间为7天
    import com.sun.jna.Library;
    import com.sun.jna.Native;
    import com.sun.jna.ptr.IntByReference;


    public class Xtgame
    {
    //继承了Library库顺便说一下StdCallLibrary库是遵循函数调用约定,如果你想让别的程序可以调用本程序中的方法那么可以采用StdCallLibrary这个库。
    public interface XT extends Library
    {
    XT u = (XT) Native.loadLibrary("User32",XT.class);              //调用了User32.dll库
    XT k = (XT) Native.loadLibrary("Kernel32",XT.class);            //调用了Kernel32.dll库


    //以下是要用到的函数的声明,想用什么函数就在这里进行声明。
    //举个例子int FindWindowA(形式参数),这个语句由两个部分组成即返回值和函数本身。这里的返回值为int型,函数即FindWindowA()不要忘了以分号作为结尾。
    int FindWindowA(String lpClassName,String lpWindowName);
    int GetWindowThreadProcessId(int HWND,IntByReference lpdwProcessId);
    int OpenProcess(int PROCESS_ALL_ACCESS,boolean FALSE,int PID);
    int CloseHandle(Object hProcess);
    void ReadProcessMemory(int hProcess,int BaseAddress,IntByReference localAddress,int Size,IntByReference ReadSize);
    void WriteProcessMemory(int hProcess,IntByReference BaseAddress,IntByReference Buffer,int Size,IntByReference WriteSize);
    IntByReference VirtualAllocEx(int hProcess,IntByReference lpAddress,int Size,int flAllocationType,int flProtect);
    }
    public static void main(String[] args)      //这里就是java程序的入口处了即程序从该处开始运行,我们都知道每个程序都有一个自己的入口不然程序是得不到执行的。
    {
    //在Java语言中是没有地址这一概念,地址这一概念是C语言的强项java的弱项,所以要用Java开发一款对内存进行读写操作的应用(例如我们的外挂程序)程序是非常困难的一件事情。
    //sun公司是注意到这一点的java作为一门跨平台的语言,为了能够调用其它系统自身提供的函数专门为Java编写了一项工具JNI,但是JNI要求编程人员必须具备C语言的知识,那对于那些
    //只会Java的开发人员来说还是没有得到什么帮助,于是又在JNI的基础上引出了JNA的概念来实现纯Java编程。


    //以下语句表示向一个声明好了的变量传入一个地址,这个地址是随机的每一次运行程序都会变动。
    //举个例子IntByReference PID = new IntByReference()  其中IntByReference表示传入了一个长度为int型的地址。
    //PID就是声明的变量用来存放要传入的地址,注意不是这个地址的值。
    IntByReference PID = new IntByReference();
    IntByReference LocalAddress0 = new IntByReference();
    IntByReference LocalAddress1 = new IntByReference();
    IntByReference LocalAddress2 = new IntByReference();
    IntByReference LocalAddress3 = new IntByReference();
    IntByReference LocalAddress4 = new IntByReference();
    IntByReference LocalAddress5 = new IntByReference();
    IntByReference LocalAddress6 = new IntByReference();
    IntByReference LocalAddress7 = new IntByReference();
    IntByReference LocalAddress8 = new IntByReference();
    IntByReference ReadSize = new IntByReference();
    IntByReference WriteSize = new IntByReference();
    //这调用了FindWindowA()在java中要调用C里面的函数必须指明这个函数所属那个库,例如
    //FindWindowA()是属于User32.dll中的那么可以用XT.u.FindWindowA(实际参数)这样的语法格式来表示。
    //如果要进行调用的函数是属于Kernel32.dll那么可以用XT.k.函数名(实际参数)来表示。好比要调用OpenProcess()这个API
    //语法格式为XT.k.OpenProcess(实际参数)。
    int HWND = XT.u.FindWindowA("CLIENT_CLASS",null);
    XT.u.GetWindowThreadProcessId(HWND,PID);
    int hProcess = XT.k.OpenProcess(2035711,false,PID.getValue());
    XT.k.ReadProcessMemory(hProcess,0x0090B614,LocalAddress0,4,ReadSize);
    XT.k.ReadProcessMemory(hProcess,0x0090B618,LocalAddress1,4,ReadSize);
    XT.k.ReadProcessMemory(hProcess,0x009147B8,LocalAddress2,4,ReadSize);
    XT.k.ReadProcessMemory(hProcess,LocalAddress2.getValue()+0x5466C,LocalAddress3,4,ReadSize);
    XT.k.ReadProcessMemory(hProcess,LocalAddress2.getValue()+0x54668,LocalAddress4,4,ReadSize);
    XT.k.ReadProcessMemory(hProcess,LocalAddress2.getValue()+0x54674,LocalAddress5,4,ReadSize);
    XT.k.ReadProcessMemory(hProcess,LocalAddress2.getValue()+0x54670,LocalAddress6,4,ReadSize);
    XT.k.ReadProcessMemory(hProcess,LocalAddress2.getValue()+0x5467C,LocalAddress7,4,ReadSize);
    XT.k.ReadProcessMemory(hProcess,LocalAddress2.getValue()+0x54678,LocalAddress8,4,ReadSize);
    XT.k.CloseHandle(hProcess);


    //以下是Java里的输出语句和C语言里的printf()易语言里的调试输出()命令是一样的道理。
    //用getValue()方法输出地址里的值,Java中没有API这一概念在Java中函数被称之为“方法”。
    System.out.println("角色横坐标:"+LocalAddress0.getValue());
    System.out.println("角色纵坐标:"+LocalAddress1.getValue());
    System.out.println("当前血量值:"+LocalAddress3.getValue());
    System.out.println("最大血量值:"+LocalAddress4.getValue());
    System.out.println("当前魔法值:"+LocalAddress5.getValue());
    System.out.println("最大魔法值:"+LocalAddress6.getValue());
    System.out.println("当前经验值:"+LocalAddress7.getValue());
    System.out.println("最大经验值:"+LocalAddress8.getValue());
    }
    }










    /*最后讲一下XT u = (XT) Native.loadLibrary("User32",XT.class);这个语句的用意。
     *它表示Java程序中要调用的库函数,这里就为大家介绍那些东西是可以自由命名的吧。
     *我做了一下标号这样可以方便讲解,(1)XT (2)u (3)= (4)(XT) Native.loadLibrary("User32",XT.class);
     *其中(1)(2)的内容是可以任意改变的,(3)是赋值语句的意思我想每一门语言都是一样的意思吧。
     *重点来了(4)中唯一可以自由改变了就是引号里面的内容这里指明了Java要调用的函数库,如果你开发了一个DLL想要用Java来调用的话
     *可以在这个引号里面输入你DLL的名称,加上文件的后缀名也没关系比如这样XT u = (XT) Native.loadLibrary("User32.dll",XT.class);
     *(XT) Native.loadLibrary("User32",XT.class)中间的空格是可以去掉的,这里之所以加上空格是因为我觉得这样比较美观。
     *(4)里的(XT)和XT.class是必须对应(1)中的内容,如果我把(1)的内容改为WG,那么就应该写成WG u = (WG) Native.loadLibrary("User32",WG.class);
     *值得注意的是XT必须是大写的而不能是xt,Java是一门严格区分大小写的语言。
     *另外提一下我目前对getValue()的研究只发现它取的内容为整数值,并不能取字符串也就是说如果你要读的地址存储的是字符串的内容(例如读取角色名称或地图名称),那么getValue()方法
     *只会把这个地址存放的十六进制的数据转为整数值输出,你看到的会是一大堆十进制的数字而不是字符串。
     *Windows内核安全技术开源交流,QQ群:728096809
     *好了到这里基本就已经结束了,如果你是一个喜欢Java语言或是正在学习Java的朋友可以加上面的QQ群欢迎你们,再者如果是一个想用Java写挂的朋友可以加群一起讨论JNA的使用
     *对JNA的研究目前国内的网站还是非常缺少这方面的资料的。
     */

    展开全文
  • java开发外挂

    千次阅读 2020-02-25 23:37:32
    java可以写部分外挂,但是仅限于简单的外挂,操作内存的外挂机不行了。 两个思路 电脑上面运行的游戏 java可以使用jdk提供的Robot工具,来实现模拟键盘点击事件和监听键盘的点击事件。基于此,就可以编写一些...

    本文分享外挂思路,不提供具体代码,被游戏爪牙搞怕了。使用了阴阳师(痒痒鼠)和跳一跳作为实验体,成功实践。内容仅供编程学习

    java也能写外挂?

    java可以写部分外挂,但是仅限于简单的外挂,操作内存的外挂机就十分难搞了,不适合,但理论也可以,以后实践了再过来补充。

     

    两个思路

    电脑上面运行的游戏

    java可以使用jdk提供的Robot工具,来实现模拟键盘点击事件和监听键盘的点击事件。基于此,就可以编写一些脚本,自动点击键盘。

    手机上面的游戏

    java可以使用adb工具和cmd工具,通过程序操控手机。基于此,可以模拟很多人为操作:手指滑动、手指点击、截屏等等。

    adb工具可以实现安卓设备通过数据线或者wifi连接电脑。

    cmd工具可以实现java执行cmd命令。

    截屏是一个很关键的地方,可以配合游戏界面的识别,实现一些自动判断,比如游戏进行到什么地方了,游戏是否结束等等。

    展开全文
  • java编写外挂

    热门讨论 2012-10-19 12:02:12
    java编写外挂基本介绍。
  • Java Web整合开发王者归来(源代码) 免资源分
  • Java游戏外挂基础

    千次阅读 2020-10-15 14:25:40
    import java.awt.*; import java.awt.event.InputEvent; import java.awt.event.KeyEvent;... * 游戏外挂基础 * @param args * @throws AWTException */ public static void main(String[] args) thr
    package com.robit.test;
    
    import java.awt.*;
    import java.awt.event.InputEvent;
    import java.awt.event.KeyEvent;
    
    public class Test1 {
    
        /**
         * 游戏外挂基础
         * @param args
         * @throws AWTException
         */
        public static void main(String[] args) throws AWTException {
            keyTest();
            mouseTest();
            colorTest();
        }
    
        /**
         * 模拟键盘点击,弹起
         * @throws AWTException
         */
        public static void keyTest() throws AWTException {
            Robot robot = new Robot();
            while(true){
                robot.delay(500);
                robot.keyPress(KeyEvent.VK_K);//按下键盘 K键
                robot.keyRelease(KeyEvent.VK_K);//释放键盘 K键
            }
        }
        /**
         * 模拟鼠标移动,点击,释放
         */
        public static void mouseTest() throws AWTException {
            Robot robot = new Robot();
            robot.mouseMove(0,0);//鼠标移动到(0,0)
            robot.delay(500);
            robot.mouseMove(500,600);
            robot.delay(500);
            robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);//按下鼠标左键
            robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);//释放鼠标左键
        }
    
        /**
         * 获得颜色
         */
        public static void colorTest() throws AWTException {
            Robot robot = new Robot();
            Color pixelColor = robot.getPixelColor(500, 600);
            System.out.println(pixelColor);
        }
    }
    
    
    
    展开全文
  • Java常用开发工具有哪些?

    千次阅读 2021-01-14 16:56:58
    Java常用的几个开发工具。下面这些工具或许功能和作用不同,但是有着一个共同的主旨,那就是——它们都是为了给 Java 编码和开发提供卓越的支持。 常用源码编辑工具介绍 Java源代码本质上其实就是普通的文本文件,...
  • The Capable & Ergonomic Java IDE by JetBrains WebStrom(前端开发):Download WebStorm: The Smartest JavaScript IDE by JetBrains STS(Spring开发):Spring | Tools MyEclipse(Java开发):MyEclipse官方...
  • 下面这些工具或许功能和作用不同,但是有着一个共同的主旨,那就是——它们都是为了给 Java 编码和开发提供卓越的支持。 常用源码编辑工具介绍 ava 源代码本质上其实就是普通的文本文件,所以理论上来说任何可以编辑...
  • 连连看外挂 java

    2013-11-05 14:27:37
    基于java开发的页面截图连连看辅助 版权所有--互联网摘取
  • Java常用开发工具介绍

    2019-09-16 15:52:48
    学习Java的同学注意了!!! 学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:456544752 我们一起学Java! 这节课我们来介绍java...
  • java常用的开发工具。都说工欲善其事必先利其器,要想学好java这门语言,选择一款好用顺手的开发工具是必不可少的。另外面试java工作时开发工具的使用也是一个重要的考核点。 要想全面了解java开发工具,我们首先...
  • JAVA封装的外挂SDK

    2012-01-28 12:33:17
    很久以前的收集的,用JAVA封装的外挂开发包,有键盘模拟,鼠标模拟,窗口相关的API
  • 俗话说的好“工欲善其事必先利其器”,要想学好java这门语言,选择一款好用顺手的开发工具是必不可少的。 java初学者常用源码编辑工具介绍 java源代码本质上其实就是普通的文本文件,所以理论上来说任何可以编辑...
  • java调用sap开发包。包含win32、win64、linux环境的开发包。
  • java开发安卓辅助脚本

    2021-06-19 14:05:23
    先来给大家说一个业务场景,假设咱们现在开发一个电商网站,要实现支付订单的功能,流程如下: 创建一个订单之后,如果用户立刻支付了这个订单,我们需要将订单状态更新为“已支付” 扣减相应的商品库存 通知仓储...
  • Java程序开发人员可以选择集成开发环境IDE(IntegratedDevelopmentEnvironment),因为Java是一种开放源码语言。开放源代码免费,商业收费。怎样选择一种适合自己的集成开发环境,或者选择一种符合自身项目开发需求的...
  • java游戏服务器开发基础以下知识在游戏中的应用场景游戏服务器开发游戏项目 基础 java基础 mysql、mongodb、redis三种数据库 熟悉使用maven、Linux、 Git和SVN log4j的使用 以下知识在游戏中的应用场景 常用的...
  • Java的常用开发工具

    2018-11-16 16:13:01
    java常用的开发工具。都说工欲善其事必先利其器,要想学好java这门语言,选择一款好用顺手的开发工具是必不可少的。另外面试java工作时开发工具的使用也是一个重要的考核...
  • JDK(Java开发工具包):https://www.oracle.com/technetwork/java/javase/downloads/index.html IntelliJ IDEA(Java开发) :https://www.jetbrains.com/idea/download WebStrom(前端开发):...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,847
精华内容 2,738
关键字:

java外挂开发

java 订阅