Java外挂开发之内存修改器(类似CE)
最近闲着蛋疼,⽆聊之中⽤CE耍了⼀哈游戏,发现挺好⽤的,于是就想,我⾃⼰能不能写个内存修改器呢?于是乎,这个软件就诞⽣了!当然我只会Java,C++嘛,了解了解,嘿嘿,所以这个⼯具也是⽤Java写的
这个⼯具在写内存搜索时,简直累死了,最开始暴⼒搜索,效率慢的要死,经过三天的不懈努⼒,终于搞定这搜索功能!这也是整个⼯具最难的部分,⾄少我是这么认为的
微软的MSDN都被我翻了⼜翻 - - !
完整源码和项⽬我已上传csdn
下载解压后的⽬录结构:
第⼀个是源代码:⽤Eclipse导⼊即可,记得修改Build Path
第⼆个是打包好的Jar,如果电脑安装了Java,就可以直接运⾏
第三个是打包好的exe安装程序,可以在没有安装Java的电脑上运⾏
不多说了,先上⼀张效果图: (这⾥⽤植物⼤战僵⼫做实验,4399的⼩游戏)
原来阳光是150,被我改成1024了
先说说这个软件的使⽤步骤吧,与CE⽤法差不多,先打开游戏进程,输⼊搜索的游戏值(⽐如这⾥改阳光,所以输⼊150),然后开始搜索,搜索完成后,种⼀柱植物,或者捡⼀个阳光,总之让阳光值发⽣变化,然后再点击搜索变化,地址就出来啦,最后,⿏标点击,输⼊修改值,点击写⼊内存就可以咯如果搜索变化没有,就多搜两次哦
本⼯具开发环境如下:
开发⼯具:Eclipse
开发语⾔:Java
开发系统:windows7
JDK版本:1.6
项⽬所需的第三⽅包:
代码实现⼤致思路如下:
获取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, to    {
//创建⼀个令牌特权,初始化为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.Value(), 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>();
//创建当前系统进程快照,返回快照句柄,具体参考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
{
//创建进程结构体,⽤于保存进程的相关信息,具体参考ity.Process中的描述
PROCESSENTRY32 lppe = new PROCESSENTRY32();
//根据快照句柄遍历系统进程
while(Kernel32_DLL.INSTANCE.Process32Next(processHandle, lppe))
{
Process temp = new Process();
temp.SzExeFileStr());
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位进程,那么久获取系统的内存范围
Value()==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.dBaseAddr);
if(Kernel32_DLL.INSTANCE.Module32Next(handleModule, lpme))
{
range.dBaseAddr);
}
}
/
/执⾏结果返回值
executeResult.setValue(range);
//执⾏结果
lastError = Kernel32_DLL.INSTANCE.GetLastError();
MinValue() == 0 && lastError!=0)
{
executeResult.setLastError(lastError);
executeResult.setMessage("Module32Next失败,错误代码:"+lastError);
}
}
finally
{
//释放快照
Kernel32_DLL.INSTANCE.CloseHandle(handleModule);
}
return executeResult;
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。