游戏外挂的编写原理(三)
2005-03-18 09:11
645 查看
(5).将ActiveKey项目中的ActiveKey.h头文件加入到Simulate项目中,并在
Stdafx.h中加入#includeActiveKey.h。
(6).在按钮单击事件函数输入如下代码:
void CSimulateDlg::OnButton1()
{
// TODO: Add your control notification handler code here
if( !bSetup )
{
m_hook.Start();//激活全局钩子。
}
else
{
m_hook.Stop();//撤消全局钩子。
}
bSetup = !bSetup;
}
(7).编译项目,并运行程序,单击按钮激活外挂。
(8).启动画笔程序,选择文本工具并将笔的颜色设置为红色,将鼠标放在任意位置
后,按F10键,画笔程序自动移
动鼠标并写下一个红色的大写R。图一展示了按F10键前的画笔程序的状态,图二展示了
按F10键后的画笔程序的状态。
图一:按F10前状态(001.jpg)
图二:按F10后状态(002.jpg)
五、封包技术
通过对动作模拟技术的介绍,我们对游戏外挂有了一定程度上的认识,也学会了使
用动作模拟技术来实现简单的
动作模拟型游戏外挂的制作。这种动作模拟型游戏外挂有一定的局限性,它仅仅只能解
决使用计算机代替人力完成那
么有规律、繁琐而无聊的游戏动作。但是,随着网络游戏的盛行和复杂度的增加,很多
游戏要求将客户端动作信息及
时反馈回服务器,通过服务器对这些动作信息进行有效认证后,再向客户端发送下一步
游戏动作信息,这样动作模拟
技术将失去原有的效应。为了更好地“外挂”这些游戏,游戏外挂程序也进行了升级换
代,它们将以前针对游戏用户
界面层的模拟推进到数据通讯层,通过封包技术在客户端挡截游戏服务器发送来的游戏
控制数据包,分析数据包并修
改数据包;同时还需按照游戏数据包结构创建数据包,再模拟客户端发送给游戏服务
器,这个过程其实就是一个封包
的过程。
封包的技术是实现第二类游戏外挂的最核心的技术。封包技术涉及的知识很广泛,
实现方法也很多,如挡截
WinSock、挡截API函数、挡截消息、VxD驱动程序等。在此我们也不可能在此文中将所
有的封包技术都进行详细介绍,
故选择两种在游戏外挂程序中最常用的两种方法:挡截WinSock和挡截API函数。
1. 挡截WinSock
众所周知,Winsock是Windows网络编程接口,它工作于Windows应用层,它提供与
底层传输协议无关的高层数据传
输编程接口。在Windows系统中,使用WinSock接口为应用程序提供基于TCP/IP协议的网
络访问服务,这些服务是由
Wsock32.DLL动态链接库提供的函数库来完成的。
由上说明可知,任何Windows基于TCP/IP的应用程序都必须通过WinSock接口访问网
络,当然网络游戏程序也不例
外。由此我们可以想象一下,如果我们可以控制WinSock接口的话,那么控制游戏客户
端程序与服务器之间的数据包也
将易如反掌。按着这个思路,下面的工作就是如何完成控制WinSock接口了。由上面的
介绍可知,WinSock接口其实是
由一个动态链接库提供的一系列函数,由这些函数实现对网络的访问。有了这层的认
识,问题就好办多了,我们可以
制作一个类似的动态链接库来代替原WinSock接口库,在其中实现WinSock32.dll中实现
的所有函数,并保证所有函数
的参数个数和顺序、返回值类型都应与原库相同。在这个自制作的动态库中,可以对我
们感兴趣的函数(如发送、接
收等函数)进行挡截,放入外挂控制代码,最后还继续调用原WinSock库中提供的相应
功能函数,这样就可以实现对网
络数据包的挡截、修改和发送等封包功能。
下面重点介绍创建挡截WinSock外挂程序的基本步骤:
(1) 创建DLL项目,选择Win32 Dynamic-Link Library,再选择An empty DLL
project。
(2) 新建文件wsock32.h,按如下步骤输入代码:
① 加入相关变量声明:
HMODULE hModule=NULL; //模块句柄
char buffer[1000]; //缓冲区
FARPROC proc; //函数入口指针
② 定义指向原WinSock库中的所有函数地址的指针变量,因WinSock库共提供70多
个函数,限于篇幅,在此就只选
择几个常用的函数列出,有关这些库函数的说明可参考MSDN相关内容。
//定义指向原WinSock库函数地址的指针变量。
SOCKET (__stdcall *socket1)(int ,int,int);//创建Sock函数。
int (__stdcall *WSAStartup1)(WORD,LPWSADATA);//初始化WinSock库函数。
int (__stdcall *WSACleanup1)();//清除WinSock库函数。
int (__stdcall *recv1)(SOCKET ,char FAR * ,int ,int );//接收数据函数。
int (__stdcall *send1)(SOCKET ,const char * ,int ,int);//发送数据函
数。
int (__stdcall *connect1)(SOCKET,const struct sockaddr *,int);//创建连
接函数。
int (__stdcall *bind1)(SOCKET ,const struct sockaddr *,int );//绑定函
数。
......其它函数地址指针的定义略。
(3) 新建wsock32.cpp文件,按如下步骤输入代码:
① 加入相关头文件声明:
#include <windows.h>
#include <stdio.h>
#include "wsock32.h"
② 添加DllMain函数,在此函数中首先需要加载原WinSock库,并获取此库中所有
函数的地址。代码如下:
BOOL WINAPI DllMain (HANDLE hInst,ULONG ul_reason_for_call,LPVOID
lpReserved)
{
if(hModule==NULL){
//加载原WinSock库,原WinSock库已复制为wsock32.001。
hModule=LoadLibrary("wsock32.001");
}
else return 1;
//获取原WinSock库中的所有函数的地址并保存,下面仅列出部分代码。
if(hModule!=NULL){
//获取原WinSock库初始化函数的地址,并保存到WSAStartup1中。
proc=GetProcAddress(hModule,"WSAStartup");
WSAStartup1=(int (_stdcall *)(WORD,LPWSADATA))proc;
//获取原WinSock库消除函数的地址,并保存到WSACleanup1中。
proc=GetProcAddress(hModule i,"WSACleanup");
WSACleanup1=(int (_stdcall *)())proc;
//获取原创建Sock函数的地址,并保存到socket1中。
proc=GetProcAddress(hModule,"socket");
socket1=(SOCKET (_stdcall *)(int ,int,int))proc;
//获取原创建连接函数的地址,并保存到connect1中。
proc=GetProcAddress(hModule,"connect");
connect1=(int (_stdcall *)(SOCKET ,const struct sockaddr
*,int ))proc;
//获取原发送函数的地址,并保存到send1中。
proc=GetProcAddress(hModule,"send");
send1=(int (_stdcall *)(SOCKET ,const char * ,int ,int ))proc;
//获取原接收函数的地址,并保存到recv1中。
proc=GetProcAddress(hModule,"recv");
recv1=(int (_stdcall *)(SOCKET ,char FAR * ,int ,int ))proc;
......其它获取函数地址代码略。
}
else return 0;
return 1;
}
③ 定义库输出函数,在此可以对我们感兴趣的函数中添加外挂控制代码,在所有
的输出函数的最后一步都调用原
WinSock库的同名函数。部分输出函数定义代码如下:
//库输出函数定义。
//WinSock初始化函数。
int PASCAL FAR WSAStartup(WORD wVersionRequired, LPWSADATA
lpWSAData)
{
//调用原WinSock库初始化函数
return WSAStartup1(wVersionRequired,lpWSAData);
}
//WinSock结束清除函数。
int PASCAL FAR WSACleanup(void)
{
return WSACleanup1(); //调用原WinSock库结束清除函数。
}
//创建Socket函数。
SOCKET PASCAL FAR socket (int af, int type, int protocol)
{
//调用原WinSock库创建Socket函数。
return socket1(af,type,protocol);
}
//发送数据包函数
int PASCAL FAR send(SOCKET s,const char * buf,int len,int flags)
{
//在此可以对发送的缓冲buf的内容进行修改,以实现欺骗服务器。
外挂代码......
//调用原WinSock库发送数据包函数。
return send1(s,buf,len,flags);
}
//接收数据包函数。
int PASCAL FAR recv(SOCKET s, char FAR * buf, int len, int flags)
{
//在此可以挡截到服务器端发送到客户端的数据包,先将其保存到buffer中。
strcpy(buffer,buf);
//对buffer数据包数据进行分析后,对其按照玩家的指令进行相关修改。
外挂代码......
//最后调用原WinSock中的接收数据包函数。
return recv1(s, buffer, len, flags);
}
.......其它函数定义代码略。
(4)、新建wsock32.def配置文件,在其中加入所有库输出函数的声明,部分声明代
码如下:
LIBRARY "wsock32"
EXPORTS
WSAStartup @1
WSACleanup @2
recv @3
send @4
socket @5
bind @6
closesocket @7
connect @8
......其它输出函数声明代码略。
Stdafx.h中加入#includeActiveKey.h。
(6).在按钮单击事件函数输入如下代码:
void CSimulateDlg::OnButton1()
{
// TODO: Add your control notification handler code here
if( !bSetup )
{
m_hook.Start();//激活全局钩子。
}
else
{
m_hook.Stop();//撤消全局钩子。
}
bSetup = !bSetup;
}
(7).编译项目,并运行程序,单击按钮激活外挂。
(8).启动画笔程序,选择文本工具并将笔的颜色设置为红色,将鼠标放在任意位置
后,按F10键,画笔程序自动移
动鼠标并写下一个红色的大写R。图一展示了按F10键前的画笔程序的状态,图二展示了
按F10键后的画笔程序的状态。
图一:按F10前状态(001.jpg)
图二:按F10后状态(002.jpg)
五、封包技术
通过对动作模拟技术的介绍,我们对游戏外挂有了一定程度上的认识,也学会了使
用动作模拟技术来实现简单的
动作模拟型游戏外挂的制作。这种动作模拟型游戏外挂有一定的局限性,它仅仅只能解
决使用计算机代替人力完成那
么有规律、繁琐而无聊的游戏动作。但是,随着网络游戏的盛行和复杂度的增加,很多
游戏要求将客户端动作信息及
时反馈回服务器,通过服务器对这些动作信息进行有效认证后,再向客户端发送下一步
游戏动作信息,这样动作模拟
技术将失去原有的效应。为了更好地“外挂”这些游戏,游戏外挂程序也进行了升级换
代,它们将以前针对游戏用户
界面层的模拟推进到数据通讯层,通过封包技术在客户端挡截游戏服务器发送来的游戏
控制数据包,分析数据包并修
改数据包;同时还需按照游戏数据包结构创建数据包,再模拟客户端发送给游戏服务
器,这个过程其实就是一个封包
的过程。
封包的技术是实现第二类游戏外挂的最核心的技术。封包技术涉及的知识很广泛,
实现方法也很多,如挡截
WinSock、挡截API函数、挡截消息、VxD驱动程序等。在此我们也不可能在此文中将所
有的封包技术都进行详细介绍,
故选择两种在游戏外挂程序中最常用的两种方法:挡截WinSock和挡截API函数。
1. 挡截WinSock
众所周知,Winsock是Windows网络编程接口,它工作于Windows应用层,它提供与
底层传输协议无关的高层数据传
输编程接口。在Windows系统中,使用WinSock接口为应用程序提供基于TCP/IP协议的网
络访问服务,这些服务是由
Wsock32.DLL动态链接库提供的函数库来完成的。
由上说明可知,任何Windows基于TCP/IP的应用程序都必须通过WinSock接口访问网
络,当然网络游戏程序也不例
外。由此我们可以想象一下,如果我们可以控制WinSock接口的话,那么控制游戏客户
端程序与服务器之间的数据包也
将易如反掌。按着这个思路,下面的工作就是如何完成控制WinSock接口了。由上面的
介绍可知,WinSock接口其实是
由一个动态链接库提供的一系列函数,由这些函数实现对网络的访问。有了这层的认
识,问题就好办多了,我们可以
制作一个类似的动态链接库来代替原WinSock接口库,在其中实现WinSock32.dll中实现
的所有函数,并保证所有函数
的参数个数和顺序、返回值类型都应与原库相同。在这个自制作的动态库中,可以对我
们感兴趣的函数(如发送、接
收等函数)进行挡截,放入外挂控制代码,最后还继续调用原WinSock库中提供的相应
功能函数,这样就可以实现对网
络数据包的挡截、修改和发送等封包功能。
下面重点介绍创建挡截WinSock外挂程序的基本步骤:
(1) 创建DLL项目,选择Win32 Dynamic-Link Library,再选择An empty DLL
project。
(2) 新建文件wsock32.h,按如下步骤输入代码:
① 加入相关变量声明:
HMODULE hModule=NULL; //模块句柄
char buffer[1000]; //缓冲区
FARPROC proc; //函数入口指针
② 定义指向原WinSock库中的所有函数地址的指针变量,因WinSock库共提供70多
个函数,限于篇幅,在此就只选
择几个常用的函数列出,有关这些库函数的说明可参考MSDN相关内容。
//定义指向原WinSock库函数地址的指针变量。
SOCKET (__stdcall *socket1)(int ,int,int);//创建Sock函数。
int (__stdcall *WSAStartup1)(WORD,LPWSADATA);//初始化WinSock库函数。
int (__stdcall *WSACleanup1)();//清除WinSock库函数。
int (__stdcall *recv1)(SOCKET ,char FAR * ,int ,int );//接收数据函数。
int (__stdcall *send1)(SOCKET ,const char * ,int ,int);//发送数据函
数。
int (__stdcall *connect1)(SOCKET,const struct sockaddr *,int);//创建连
接函数。
int (__stdcall *bind1)(SOCKET ,const struct sockaddr *,int );//绑定函
数。
......其它函数地址指针的定义略。
(3) 新建wsock32.cpp文件,按如下步骤输入代码:
① 加入相关头文件声明:
#include <windows.h>
#include <stdio.h>
#include "wsock32.h"
② 添加DllMain函数,在此函数中首先需要加载原WinSock库,并获取此库中所有
函数的地址。代码如下:
BOOL WINAPI DllMain (HANDLE hInst,ULONG ul_reason_for_call,LPVOID
lpReserved)
{
if(hModule==NULL){
//加载原WinSock库,原WinSock库已复制为wsock32.001。
hModule=LoadLibrary("wsock32.001");
}
else return 1;
//获取原WinSock库中的所有函数的地址并保存,下面仅列出部分代码。
if(hModule!=NULL){
//获取原WinSock库初始化函数的地址,并保存到WSAStartup1中。
proc=GetProcAddress(hModule,"WSAStartup");
WSAStartup1=(int (_stdcall *)(WORD,LPWSADATA))proc;
//获取原WinSock库消除函数的地址,并保存到WSACleanup1中。
proc=GetProcAddress(hModule i,"WSACleanup");
WSACleanup1=(int (_stdcall *)())proc;
//获取原创建Sock函数的地址,并保存到socket1中。
proc=GetProcAddress(hModule,"socket");
socket1=(SOCKET (_stdcall *)(int ,int,int))proc;
//获取原创建连接函数的地址,并保存到connect1中。
proc=GetProcAddress(hModule,"connect");
connect1=(int (_stdcall *)(SOCKET ,const struct sockaddr
*,int ))proc;
//获取原发送函数的地址,并保存到send1中。
proc=GetProcAddress(hModule,"send");
send1=(int (_stdcall *)(SOCKET ,const char * ,int ,int ))proc;
//获取原接收函数的地址,并保存到recv1中。
proc=GetProcAddress(hModule,"recv");
recv1=(int (_stdcall *)(SOCKET ,char FAR * ,int ,int ))proc;
......其它获取函数地址代码略。
}
else return 0;
return 1;
}
③ 定义库输出函数,在此可以对我们感兴趣的函数中添加外挂控制代码,在所有
的输出函数的最后一步都调用原
WinSock库的同名函数。部分输出函数定义代码如下:
//库输出函数定义。
//WinSock初始化函数。
int PASCAL FAR WSAStartup(WORD wVersionRequired, LPWSADATA
lpWSAData)
{
//调用原WinSock库初始化函数
return WSAStartup1(wVersionRequired,lpWSAData);
}
//WinSock结束清除函数。
int PASCAL FAR WSACleanup(void)
{
return WSACleanup1(); //调用原WinSock库结束清除函数。
}
//创建Socket函数。
SOCKET PASCAL FAR socket (int af, int type, int protocol)
{
//调用原WinSock库创建Socket函数。
return socket1(af,type,protocol);
}
//发送数据包函数
int PASCAL FAR send(SOCKET s,const char * buf,int len,int flags)
{
//在此可以对发送的缓冲buf的内容进行修改,以实现欺骗服务器。
外挂代码......
//调用原WinSock库发送数据包函数。
return send1(s,buf,len,flags);
}
//接收数据包函数。
int PASCAL FAR recv(SOCKET s, char FAR * buf, int len, int flags)
{
//在此可以挡截到服务器端发送到客户端的数据包,先将其保存到buffer中。
strcpy(buffer,buf);
//对buffer数据包数据进行分析后,对其按照玩家的指令进行相关修改。
外挂代码......
//最后调用原WinSock中的接收数据包函数。
return recv1(s, buffer, len, flags);
}
.......其它函数定义代码略。
(4)、新建wsock32.def配置文件,在其中加入所有库输出函数的声明,部分声明代
码如下:
LIBRARY "wsock32"
EXPORTS
WSAStartup @1
WSACleanup @2
recv @3
send @4
socket @5
bind @6
closesocket @7
connect @8
......其它输出函数声明代码略。
相关文章推荐
- 游戏外挂的编写原理
- 网络游戏外挂编写原理
- 游戏外挂的基本编写原理(转)
- 游戏外挂的基本编写原理
- 游戏辅助原理与制作第五课--------编写植物大战僵尸修改阳光外挂
- 游戏外挂的编写原理(一)
- 网络游戏外挂编写原理
- 游戏外挂的编写原理(二)
- 网络游戏外挂编写原理(一)
- 游戏外挂的编写原理
- 游戏外挂的编写原理(四)
- 游戏外挂的编写原理和思路
- 【转载】游戏外挂的编写原理和思路
- 网络游戏外挂编写原理(二)
- 网络游戏外挂编写原理(二)
- 【转】编写游戏外挂原理 (c语言)
- 游戏外挂的编写原理(异域の蜗牛注:此转帖为部份内容,只作为一个大概的原理入门,代码部份略去)
- 游戏外挂的编写原理(五)
- 游戏外挂的编写原理1
- 网络游戏外挂编写原理