张强的个人博客

Good Luck To You!

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

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

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


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

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


完整源码和项目我已上传百度网盘

链接: https://pan.baidu.com/s/1p0I9vD-hx12FwY1VZAFV4Q

提取码: czwg


下载解压后的目录结构:
20161209214033559.png

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

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

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


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

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

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


本工具开发环境如下:

开发工具:Eclipse

开发语言:Java

开发系统:windows7

JDK版本:1.6


项目所需的第三方包:

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

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


代码实现大致思路如下:

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


项目包目录如下:
20161209211631610.png

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;
    }
}

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

«   2019年10月   »
123456
78910111213
14151617181920
21222324252627
28293031
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
    搜索
    最新留言
      文章归档
      网站收藏
      友情链接
      • RainbowSoft Studio Z-Blog
      • 订阅本站的 RSS 2.0 新闻聚合

      Powered By Z-BlogPHP 1.5.2 Zero

      Copyright Your WebSite.Some Rights Reserved.