Java外挂开发之内存修改器(类似CE)

最近闲着蛋疼,无聊之中用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;
	}
}



  • 36
    点赞
  • 160
    收藏
    觉得还不错? 一键收藏
  • 28
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值