内蒙古防雷:网络游戏外挂编程原理(热键,dll替换)

来源:百度文库 编辑:中财网 时间:2024/05/01 23:26:07
 
一、 前言 
所谓游戏外挂,其实是一种游戏外辅程序,它可以协助玩家自动产生游戏动作、修 
改游戏网络数据包以及修改游 
戏内存数据等,以实现玩家用最少的时间和金钱去完成功力升级和过关斩将。虽然,现 
在对游戏外挂程序的"合法" 
身葜谒捣诅。谡饫镂也幌攵源朔⒈砣魏胃鋈艘饧檬奔淙ニ得饕磺邪伞?/p> 
不管游戏外挂程序是不是"合法"身份,但是它却是具有一定的技术含量的,在这 
些小小程序中使用了许多高端 
技术,如拦截Sock技术、拦截API技术、模拟键盘与鼠标技术、直接修改程序内存技术 
等等。本文将对常见的游戏外挂 
中使用的技术进行全面剖析。 
二、认识外挂 
游戏外挂的历史可以追溯到单机版游戏时代,只不过当时它使用了另一个更通俗易 
懂的名字??游戏修改器。它可 
以在游戏中追踪锁定游戏主人公的各项能力数值。这样玩家在游戏中可以达到主角不掉 
血、不耗费魔法、不消耗金钱 
等目的。这样降低了游戏的难度,使得玩家更容易通关。 
随着网络游戏的时代的来临,游戏外挂在原有的功能之上进行了新的发展,它变得 
更加多种多样,功能更加强大 
,操作更加简单,以至有些游戏的外挂已经成为一个体系,比如《石器时代》,外挂品 
种达到了几十种,自动战斗、 
自动行走、自动练级、自动补血、加速、不遇敌、原地遇敌、快速增加经验值、按键精 
灵……几乎无所不包。 
游戏外挂的设计主要是针对于某个游戏开发的,我们可以根据它针对的游戏的类型 
可大致可将外挂分为两种大类 
。 
一类是将游戏中大量繁琐和无聊的攻击动作使用外挂自动完成,以帮助玩家轻松搞 
定攻击对象并可以快速的增加 
玩家的经验值。比如在《龙族》中有一种工作的设定,玩家的工作等级越高,就可以驾 
驭越好的装备。但是增加工作 
等级却不是一件有趣的事情,毋宁说是重复枯燥的机械劳动。如果你想做法师用的杖, 
首先需要做基本工作--?砍树。 
砍树的方法很简单,在一棵大树前不停的点鼠标就可以了,每10000的经验升一级。这 
就意味着玩家要在大树前不停的 
点击鼠标,这种无聊的事情通过"按键精灵"就可以解决。外挂的"按键精灵"功能可以让 
玩家摆脱无趣的点击鼠标的工 
作。 
另一类是由外挂程序产生欺骗性的网络游戏封包,并将这些封包发送到网络游戏服 
务器,利用这些虚假信息欺骗 
服务器进行游戏数值的修改,达到修改角色能力数值的目的。这类外挂程序针对性很 
强,一般在设计时都是针对某个 
游戏某个版本来做的,因为每个网络游戏服务器与客户端交流的数据包各不相同,外挂 
程序必须要对欺骗的网络游戏 
服务器的数据包进行分析,才能产生服务器识别的数据包。这类外挂程序也是当前最流 
利的一类游戏外挂程序。 
另外,现在很多外挂程序功能强大,不仅实现了自动动作代理和封包功能,而且还 
提供了对网络游戏的客户端程 
序的数据进行修改,以达到欺骗网络游戏服务器的目的。我相信,随着网络游戏商家的 
反外挂技术的进展,游戏外挂 
将会产生更多更优秀的技术,让我们期待着看场技术大战吧...... 
三、外挂技术综述 
可以将开发游戏外挂程序的过程大体上划分为两个部分: 
前期部分工作是对外挂的主体游戏进行分析,不同类型的外挂分析主体游戏的内容 
也不相同。如外挂为上述谈到 
的外挂类型中的第一类时,其分析过程常是针对游戏的场景中的攻击对象的位置和分布 
情况进行分析,以实现外挂自 
动进行攻击以及位置移动。如外挂为外挂类型中的第二类时,其分析过程常是针对游戏 
服务器与客户端之间通讯包数 
据的结构、内容以及加密算法的分析。因网络游戏公司一般都不会公布其游戏产品的通 
讯包数据的结构、内容和加密 
算法的信息,所以对于开发第二类外挂成功的关键在于是否能正确分析游戏包数据的结 
构、内容以及加密算法,虽然 
可以使用一些工具辅助分析,但是这还是一种坚苦而复杂的工作。 
后期部分工作主要是根据前期对游戏的分析结果,使用大量的程序开发技术编写外 
挂程序以实现对游戏的控制或 
修改。如外挂程序为第一类外挂时,通常会使用到鼠标模拟技术来实现游戏角色的自动 
位置移动,使用键盘模拟技术 
来实现游戏角色的自动攻击。如外挂程序为第二类外挂时,通常会使用到挡截Sock和挡 
截API函数技术,以挡截游戏服 
务器传来的网络数据包并将数据包修改后封包后传给游戏服务器。另外,还有许多外挂 
使用对游戏客户端程序内存数 
据修改技术以及游戏加速技术。 
本文主要是针对开发游戏外挂程序后期使用的程序开发技术进行探讨,重点介绍的 
如下几种在游戏外挂中常使用 
的程序开发技术: 
● 动作模拟技术:主要包括键盘模拟技术和鼠标模拟技术。 
● 封包技术:主要包括挡截Sock技术和挡截API技术。 
四、动作模拟技术 
我们在前面介绍过,几乎所有的游戏都有大量繁琐和无聊的攻击动作以增加玩家的 
功力,还有那些数不完的迷宫 
,这些好像已经成为了角色游戏的代名词。现在,外挂可以帮助玩家从这些繁琐而无聊 
的工作中摆脱出来,专注于游 
戏情节的进展。外挂程序为了实现自动角色位置移动和自动攻击等功能,需要使用到键 
盘模拟技术和鼠标模拟技术。 
下面我们将重点介绍这些技术并编写一个简单的实例帮助读者理解动作模拟技术的实现 
过程。 
1. 鼠标模拟技术 

几乎所有的游戏中都使用了鼠标来改变角色的位置和方向,玩家仅用一个小小的鼠 
标,就可以使角色畅游天下。 
那么,我们如何实现在没有玩家的参与下角色也可以自动行走呢。其实实现这个并不 
难,仅仅几个Windows API函数就 
可以搞定,让我们先来认识认识这些API函数。 
(1) 模拟鼠标动作API函数mouse_event,它可以实现模拟鼠标按下和放开等动作。 
VOID mouse_event( 
DWORD dwFlags, // 鼠标动作标识。 
DWORD dx, // 鼠标水平方向位置。 
DWORD dy, // 鼠标垂直方向位置。 
DWORD dwData, // 鼠标轮子转动的数量。 
DWORD dwExtraInfo // 一个关联鼠标动作辅加信息。 
); 
其中,dwFlags表示了各种各样的鼠标动作和点击活动,它的常用取值如下: 
MOUSEEVENTF_MOVE 表示模拟鼠标移动事件。 
MOUSEEVENTF_LEFTDOWN 表示模拟按下鼠标左键。 
MOUSEEVENTF_LEFTUP 表示模拟放开鼠标左键。 
MOUSEEVENTF_RIGHTDOWN 表示模拟按下鼠标右键。 
MOUSEEVENTF_RIGHTUP 表示模拟放开鼠标右键。 
MOUSEEVENTF_MIDDLEDOWN 表示模拟按下鼠标中键。 
MOUSEEVENTF_MIDDLEUP 表示模拟放开鼠标中键。 
(2)、设置和获取当前鼠标位置的API函数。获取当前鼠标位置使用GetCursorPos() 
函数,设置当前鼠标位置使用 
SetCursorPos()函数。 
BOOL GetCursorPos( 
LPPOINT lpPoint // 返回鼠标的当前位置。 
); 
BOOL SetCursorPos( 
int X, // 鼠标的水平方向位置。 
int Y //鼠标的垂直方向位置。 
); 
通常游戏角色的行走都是通过鼠标移动至目的地,然后按一下鼠标的按钮就搞定 
了。下面我们使用上面介绍的API 
函数来模拟角色行走过程。 
CPoint oldPoint,newPoint; 
GetCursorPos(&oldPoint); //保存当前鼠标位置。 
newPoint.x = oldPoint.x+40; 
newPoint.y = oldPoint.y+10; 
SetCursorPos(newPoint.x,newPoint.y); //设置目的地位置。 
mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);//模拟按下鼠标右键。 
mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);//模拟放开鼠标右键。 
2. 键盘模拟技术 
在很多游戏中,不仅提供了鼠标的操作,而且还提供了键盘的操作,在对攻击对象 
进行攻击时还可以使用快捷键 
。为了使这些攻击过程能够自动进行,外挂程序需要使用键盘模拟技术。像鼠标模拟技 
术一样,Windows API也提供了 
一系列API函数来完成对键盘动作的模拟。 
模拟键盘动作API函数keydb_event,它可以模拟对键盘上的某个或某些键进行按下 
或放开的动作。 
VOID keybd_event( 
BYTE bVk, // 虚拟键值。 
BYTE bScan, // 硬件扫描码。 
DWORD dwFlags, // 动作标识。 
DWORD dwExtraInfo // 与键盘动作关联的辅加信息。 
); 
其中,bVk表示虚拟键值,其实它是一个BYTE类型值的宏,其取值范围为1-254。有 
关虚拟键值表请在MSDN上使用 
关键字"Virtual-Key Codes"查找相关资料。bScan表示当键盘上某键被按下和放开 
时,键盘系统硬件产生的扫描码 
,我们可以MapVirtualKey()函数在虚拟键值与扫描码之间进行转换。dwFlags表示各种 
各样的键盘动作,它有两种取 
值:KEYEVENTF_EXTENDEDKEY和KEYEVENTF_KEYUP。 
下面我们使用一段代码实现在游戏中按下Shift+R快捷键对攻击对象进行攻击。 
keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0),0,0); //按下CTRL 
键。 
keybd_event(0x52,MapVirtualKey(0x52,0),0,0);//键下R键。 
keybd_event(0x52,MapVirtualKey(0x52,0), KEYEVENTF_KEYUP,0);//放开R键。 
keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0), 
KEYEVENTF_KEYUP,0);//放开CTRL键。 
3. 激活外挂 
上面介绍的鼠标和键盘模拟技术实现了对游戏角色的动作部分的模拟,但要想外挂 
能工作于游戏之上,还需要将 
其与游戏的场景窗口联系起来或者使用一个激活键,就象按键精灵的那个激活键一样。 
我们可以用GetWindow函数来枚 
举窗口,也可以用Findwindow函数来查找特定的窗口。另外还有一个FindWindowEx函数 
可以找到窗口的子窗口,当游 
戏切换场景的时候我们可以用FindWindowEx来确定一些当前窗口的特征,从而判断是否 
还在这个场景,方法很多了, 
比如可以GetWindowInfo来确定一些东西,比如当查找不到某个按钮的时候就说明游戏 
场景已经切换了等等办法。当使 
用激活键进行关联,需要使用Hook技术开发一个全局键盘钩子,在这里就不具体介绍全 
局钩子的开发过程了,在后面 
的实例中我们将会使用到全局钩子,到时将学习到全局钩子的相关知识。 
4. 实例实现 
通过上面的学习,我们已经基本具备了编写动作式游戏外挂的能力了。下面我们将 
创建一个画笔程序外挂,它实 
现自动移动画笔字光标的位置并写下一个红色的"R"字。以这个实例为基础,加入相 
应的游戏动作规则,就可以实现 
一个完整的游戏外挂。这里作者不想使用某个游戏作为例子来开发外挂(因没有游戏商 
家的授权啊!),如读者感兴 
趣的话可以找一个游戏试试,最好仅做测试技术用。 
首先,我们需要编写一个全局钩子,使用它来激活外挂,激活键为F10。创建全局 
钩子步骤如下: 
(1).选择MFC AppWizard(DLL)创建项目ActiveKey,并选择MFC Extension DLL 
(共享MFC拷贝)类型。 
(2).插入新文件ActiveKey.h,在其中输入如下代码: 
#ifndef _KEYDLL_H 
#define _KEYDLL_H 
class AFX_EXT_CLASS CKeyHook:public CObject 

public: 
CKeyHook(); 
~CKeyHook(); 
HHOOK Start(); //安装钩子 
BOOL Stop(); //卸载钩子 
}; 
#endif 
(3).在ActiveKey.cpp文件中加入声明"#include ActiveKey.h"。 
(4).在ActiveKey.cpp文件中加入共享数据段,代码如下: 
//Shared data section 
#pragma data_seg("sharedata") 
HHOOK glhHook=NULL; //钩子句柄。 
HINSTANCE glhInstance=NULL; //DLL实例句柄。 
#pragma data_seg() 
(5).在ActiveKey.def文件中设置共享数据段属性,代码如下: 
SETCTIONS 
shareddata READ WRITE SHARED 
(6).在ActiveKey.cpp文件中加入CkeyHook类的实现代码和钩子函数代码: 
//键盘钩子处理函数。 
extern "C" LRESULT WINAPI KeyboardProc(int nCode,WPARAM wParam,LPARAM 
lParam) 

if( nCode >= 0 ) 

if( wParam == 0X79 )//当按下F10键时,激活外挂。 

//外挂实现代码。 
CPoint newPoint,oldPoint; 
GetCursorPos(&oldPoint); 
newPoint.x = oldPoint.x+40; 
newPoint.y = oldPoint.y+10; 
SetCursorPos(newPoint.x,newPoint.y); 
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);//模拟按下鼠标左键。 
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);//模拟放开鼠标左键。 
keybd_event(VK_SHIFT,MapVirtualKey(VK_SHIFT,0),0,0); //按下SHIFT键。 
keybd_event(0x52,MapVirtualKey(0x52,0),0,0);//按下R键。 
keybd_event(0x52,MapVirtualKey(0x52,0),KEYEVENTF_KEYUP,0);//放开R键。 
keybd_event(VK_SHIFT,MapVirtualKey(VK_SHIFT,0),KEYEVENTF_KEYUP,0);//放开 
SHIFT键。 
SetCursorPos(oldPoint.x,oldPoint.y); 


return CallNextHookEx(glhHook,nCode,wParam,lParam); 

CKeyHook::CKeyHook(){} 
CKeyHook::~CKeyHook() 

if( glhHook ) 
Stop(); 

//安装全局钩子。 
HHOOK CKeyHook::Start() 

glhHook = SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,glhInstance,0);//设置键 
盘钩子。 
return glhHook; 

//卸载全局钩子。 
BOOL CKeyHook::Stop() 

BOOL bResult = TRUE; 
if( glhHook ) 
bResult = UnhookWindowsHookEx(glhHook);//卸载键盘钩子。 
return bResult; 

(7).修改DllMain函数,代码如下: 
extern "C" int APIENTRY 
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) 

//如果使用lpReserved参数则删除下面这行 
UNREFERENCED_PARAMETER(lpReserved); 
if (dwReason == DLL_PROCESS_ATTACH) 

TRACE0("NOtePadHOOK.DLL Initializing!\n"); 
//扩展DLL仅初始化一次 
if (!AfxInitExtensionModule(ActiveKeyDLL, hInstance)) 
return 0; 
new CDynLinkLibrary(ActiveKeyDLL); 
//把DLL加入动态MFC类库中 
glhInstance = hInstance; 
//插入保存DLL实例句柄 

else if (dwReason == DLL_PROCESS_DETACH) 

TRACE0("NotePadHOOK.DLL Terminating!\n"); 
//终止这个链接库前调用它 
AfxTermExtensionModule(ActiveKeyDLL); 

return 1; 

(8).编译项目ActiveKey,生成ActiveKey.DLL和ActiveKey.lib。 
接着,我们还需要创建一个外壳程序将全局钩子安装了Windows系统中,这个外壳 
程序编写步骤如下: 
(1).创建一个对话框模式的应用程序,项目名为Simulate。 
(2).在主对话框中加入一个按钮,使用ClassWizard为其创建CLICK事件。 
(3).将ActiveKey项目Debug目录下的ActiveKey.DLL和ActiveKey.lib拷贝到 
Simulate项目目录下。 
(4).从"工程"菜单中选择"设置",弹出Project Setting对话框,选择Link标 
签,在"对象/库模块"中输入 
ActiveKey.lib。 
(5).将ActiveKey项目中的ActiveKey.h头文件加入到Simulate项目中,并在 
Stdafx.h中加入#include 
ActiveKey.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 
#include 
#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 
......其它输出函数声明代码略。 
)、从"工程"菜单中选择"设置",弹出Project Setting对话框,选择Link标 
签,在"对象/库模块"中输入 
Ws2_32.lib。 
(6)、编译项目,产生wsock32.dll库文件。 
(7)、将系统目录下原wsock32.dll库文件拷贝到被外挂程序的目录下,并将其改名 
为wsock.001;再将上面产生的 
wsock32.dll文件同奖吹奖煌夤页绦虻哪柯枷隆V匦缕舳蜗烦绦颍耸庇蜗烦绦?br> 将先加载我们自己制作的 
wsock32.dll文件,再通过该库文件间接调用原WinSock接口函数来实现访问网络。上面 
我们仅仅介绍了挡载WinSock的 
实现过程,至于如何加入外挂控制代码,还需要外挂开发人员对游戏数据包结构、内 
容、加密算法等方面的仔细分析 
(这个过程将是一个艰辛的过程),再生成外挂控制代码。关于数据包分析方法和技 
巧,不是本文讲解的范围,如您 
感兴趣可以到网上查查相关资料。 
2.6) 在ActiveKey.cpp中加入头文件声明 "#include "wsock32.h"。 从"工程"菜 
单中选择"设置",弹出 
Project Setting对话框,选择Link标签,在"对象/库模块"中输入Ws2_32..lib。 
(7) 重新编译ActiveKey项目,产生ActiveKey.dll文件,将其拷贝到Simulate.exe 
目录下。运行Simulate.exe并 
启动全局钩子。激活任意应用程序,按F11键后,运行此程序中可能调用MessageBoxA函 
数的操作,看看信息框是不是 
有所变化。同样,如此程序正在接收网络数据包,就可以实现封包功能了。 
六、结束语 
除了以上介绍的几种游戏外挂程序常用的技术以外,在一些外挂程序中还使用了游戏数据修改技术、游戏加速技术等。在这篇文章里,就不逐一介绍