前述:辅助(外挂)的实现方式有很多种、本文采用远程DLL注入的方式实现该功能,当然你也可以是使用获取窗口句柄、进程PID来获取操作内存权限
只是相对来说DLL注入的方式可以过掉许多大型游戏的检测。
目标
image.png创建工程
我们使用VS2017创建一个动态链接库MFC -DLL项目
image.png
创建之后 我们分析当前项目文件
在项目中我们查看源文件这个
image.png
jsDll.cpp
这个文件是整个DLL的入口文件
// jsDll.cpp: 定义 DLL 的初始化例程。
#include "stdafx.h"
#include "jsDll1.h"
#include "MyDigLog.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
BEGIN_MESSAGE_MAP(CjsDll1App, CWinApp)
END_MESSAGE_MAP()
CjsDll1App::CjsDll1App()
{
}
CjsDll1App theApp;
BOOL CjsDll1App::InitInstance()
{
CWinApp::InitInstance();
这里是DLL注入成功之后的主函数,所有的事情放在这里操作
return TRUE;
}
游戏基质的定义
辅助开发游戏基质的查找是并不可少的,但本文的目的不在查找基质,如果需要请查阅相关文章。
这里贴一下网上发布的一些植物大战僵尸的基质文章:植物大战僵尸基质
博主当前的游戏版本是英文原版
- 新建筛选器(文件夹)存放我们的游戏基质
#pragma once
#define start_base 0x006A9EC0; //基础基址
#define Sum_offset1 768; //阳光的一级偏移
#define Sum_offset2 5560;//阳光的二级偏移
- 新建工具箱筛选器(文件夹)存放我们游戏的一些共用的一些函数
//initGame.h
#pragma once
/*
初始化一些共用函数
*/
namespace initGame {
int *P2(int *, int);//计算两级偏移
int *P3(int *, int, int);//计算三级偏移
int *P4(int *, int, int, int);//计算四级偏移
void setSum(int); //修改阳光值
void WriteToMemory();//修改种植物不减阳光
void WriteLengQue();//修改种植物无冷却
};
//initGame.cpp
#include "stdafx.h"
#include "initGame.h"
#include "GameBase.h"
//初始函数的实现
int *initGame::P2(int *p, int offset)
{
return (int *)(*p + offset);
}
int *initGame::P3(int *p, int offset, int offset1)
{
return (int *)(*(int *)(*p + offset) + offset1);
}
int *initGame::P4(int *p, int offset, int offset1, int offset2)
{
return (int *)(*(int *)(*(int *)(*p + offset) + offset1) + offset2);
}
void initGame::setSum(int n)
{
int *ptr_sum = (int *)start_base; //把游戏基址转为指针
// 游戏基质 + 768 +5560 就是阳光值
int *nowSum = initGame::P3(ptr_sum, (int)Sum_offset1, (int)Sum_offset2);
*nowSum = n;
return;
}
- 新建资源(DiaLog)
我们只做三种功能
如果在新建DiaLog找不到工具箱,可在VS2017->视图->工具箱就可找到
当然在做辅助的过程中,你需要一点汇编的基础
在新增按钮或者编辑框的时候我们重新设置他们的属性:ID方便在后面写功能的时候调用
编辑框ID:bjk1
不减阳光按钮:bjyg1
无冷却:wlq1
修改阳光按钮:xgyg1
在DigLog框上右击新建类
新建之后,我们不急着去添加功能,我们现在游戏中显示出这个DIgLog框
回到jsDll.cpp
中
我们添加代码:在入口函数中
// jsDll.cpp: 定义 DLL 的初始化例程。
#include "stdafx.h"
#include "jsDll1.h"
#include "MyDigLog.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
BEGIN_MESSAGE_MAP(CjsDll1App, CWinApp)
END_MESSAGE_MAP()
// CjsDll1App 构造
CjsDll1App::CjsDll1App()
{
}
CjsDll1App theApp;
MyDigLog *mainDiaLog; //创建一个DiaLog的指针
DWORD WINAPI showDigLog(void *p)
{
mainDiaLog = new MyDigLog(); //给这个指针实例化
mainDiaLog->DoModal(); //阻塞的方式显示这个DigLog
delete mainDiaLog; //释放这个指针,具体可以查看我写的C++基础 使用指针实例类需要释放
FreeLibraryAndExitThread(theApp.m_hInstance,1); //释放线程
return 0;
}
BOOL CjsDll1App::InitInstance()
{
CWinApp::InitInstance();
HANDLE MyTheard = ::CreateThread(NULL, NULL,showDigLog, NULL, NULL, NULL);
这里是创建一个线程,让他显示DigLog
return TRUE;
}
然后我们生成方案,找到生成的文件jsDll.dll我这里是在DeBug下生成的方案
然后我们使用注入工具注入进游戏
image.png没有的同学可以在网上找到,或者找我拿 然后注入进去之后,我们就可以看到
image.pngDigLog成功显示了,但是此时我们还没有写入功能,先把这次注入的DLL线程给卸载掉,使用DLL注入工具卸载
功能的编写
-
修改阳光
单机修改阳光
右键按钮添加事件处理
image.png
#include "initGame.h"
void MyDigLog::OnBnClickedxgtg1()
{//修改阳光的按钮被单击
CString str;
//获取编辑框的内容
GetDlgItem(bjk1)->GetWindowText(str);
initGame::setSum(_ttoi(str)); //把CString转为int并调用修改阳光值的函数
return;
}
- 种植物不减阳光
这里需要一点基础汇编知识
通过CE分析:
image.png其中
sub esi,ebx
就是种植物减少阳光的关键代码
这里我们把源汇编改为sub esi,0
或者add esi,ebx
改成add种植物不减反增
注意我们更改为sub esi,0
,他一共会替换8个字节
增加代码在实现函数中
//initGame.cpp
void initGame::WriteToMemory()
{
DWORD oldProtect = NULL;//老的内存权限
LPVOID APIadress = (LPVOID)0x0041BA74;
/*
先改变他的读写权限
VirtualProtectEx
GetCurrentProcess 获取当前进程的句柄 因为是DLL注入到游戏里 这里也就是游戏的句柄
PAGE_EXECUTE 可读写
*/
if (VirtualProtectEx(GetCurrentProcess(), APIadress, 8, PAGE_EXECUTE, &oldProtect))
{//读写权限更改成功后
//需要写入的字节数
CHAR newByte[8] = { (CHAR)0x83,(CHAR)0xEE ,(CHAR)0x00, (CHAR)0x90, (CHAR)0x90, (CHAR)0x90, (CHAR)0x90, (CHAR)0x90 };
WriteProcessMemory(GetCurrentProcess(), APIadress, newByte,8,NULL);
}
VirtualProtectEx(GetCurrentProcess(), APIadress, 8, oldProtect, &oldProtect);//恢复之前的读写权限
}
- 种植物无冷却
这里怎么找冷却基质、冷却的关键汇编代码这里不详细介绍,感兴趣的朋友可以访问植物大战僵尸免冷却思路
增加代码在实现函数中
//initGame.cpp
void initGame::WriteLengQue()
{//修改冷却
DWORD oldProtect = NULL;//老的内存权限
LPVOID APIadress = (LPVOID)0x00487296; //冷却的关键地址
/*
先改变他的读写权限
VirtualProtectEx
GetCurrentProcess 获取当前进程的句柄 因为是DLL注入到游戏里 这里也就是游戏的句柄
PAGE_EXECUTE 可读写
*/
if (VirtualProtectEx(GetCurrentProcess(), APIadress, 1, PAGE_EXECUTE, &oldProtect))
{//读写权限更改成功后
//需要写入的字节数
CHAR newByte[1] = { (CHAR)0x7D };
WriteProcessMemory(GetCurrentProcess(), APIadress, newByte, 1, NULL);
}
VirtualProtectEx(GetCurrentProcess(), APIadress, 1, oldProtect, &oldProtect);//恢复之前的读写权限
}
- 当initGame编写完成之后,我们在DigLog中添加相应的单击事件
void MyDigLog::OnBnClickedbjyg1()
{//不减阳光
initGame::WriteToMemory();
}
void MyDigLog::OnBnClickedwlq1()
{
// TODO: 在此添加控件通知处理程序代码
initGame::WriteLengQue();
}
至此我们功能写完,至于需要添加更多功能,可以自己找基质、汇编代码,如秒杀、一块地种多种植物
网友评论