很多人都对网游外挂的制作很感兴趣,在这篇文章里,我向大家简单介绍一下一款网游外挂的大致制作流程。
首先,我想说明几点:
第一、这篇文章并不是具体教你如何写外挂,只是带你大致浏览一下网游外挂的制作流程,并就其中的一些关键技术点加以简单说明。大家可以用看故事书的心情来阅读此文,了解一下网游外挂制作过程中的一些原理。
第二、我对网游数据的破解不是很懂,通常一个网游外挂制作团队内都有一名破解高手坐镇。所以碰到破解方面的问题我就只能一笔带过了。
第三、这篇文章的原始档案以及相关资源你可以访问以下地址:
制作网游外挂的第一步就是选定一款游戏。目标游戏不是乱选的,里面也有很多讲究。
第一点,选择自己熟悉的游戏类型。如果你之前已经做过网游外挂,那选择一款类似的游戏会给你节省很大的时间,如果是第一次制作的话,那也选一款自己熟悉的游戏类型。
第二点,尽量不要选择热门的游戏,因为热门的游戏往往意味着竞争对手的增多,除非你对自己的技术以及营销手段很有信心。
第三点,不要小看玩家人数少的游戏,游戏规模小,竞争也小。一款游戏,只要你能形成吃独食的场面,再加上营销搞得好的话,其中的利润将超过你的想象。但要注意,最好不要碰上因为游戏规模过小导致游戏厂商把游戏关闭的衰事。
第四点,尽量选择尚在测试期内的游戏,这使得你有充足的时间制作外挂,同时也要观察该款游戏在市面上是否有其他外挂出现。这样等游戏正式上线时,你的外挂也差不多可以推出了。
2.1 确定要制作的网游外挂类型
目标网游选定好之后,你首先要做的第一件事就是确定你要制作的网游外挂类型。
网游外挂虽然统称为外挂,但细分的话可以分为以下二类:内挂和脱机外挂。
内挂就是在游戏内呼出的网游外挂,它依赖于网游客户端,所使用到的技术主要包括鼠标和键盘的模拟,内存特殊变量区域的搜索,或者是挂钩游戏的收包函数和模拟游戏的发包函数。
脱机外挂就是指不依赖于客户端,能独立模拟客户端和游戏服务器进行通讯的网游外挂。脱机外挂的实现方式只有一种,就是模拟网游客户端的收包和发包过程。
总体而言,内挂的整体制作难度比脱机外挂要简单一些,但脱机外挂制作要比内挂更有趣,而且用起来也更方便,不必启动庞大的客户端程序。
因为之前制作的几款都是脱机外挂,所以下面主要是以脱机外挂的制作流程为主进行讲解。
2.2 网络截包工具(Microsoft Network Monitor)的使用简介
目标网游的初步分析最主要的工作是分析游戏初始阶段网游客户端和服务器之间的数据通讯。这一阶段主要是指从输入用户名和密码开始登录游戏到玩家人物出现在游戏场景中这个阶段。这是开始阶段最关键的一个步骤,如果你能够成功破解网游数据通讯部分的加密,并用DEMO程序成功模拟整个登录过程,那你几乎就已经成功了一半了。如果无法破解加密的话,那就需要赶快重新选定一款游戏了。
关于初步分析,首先要确定网游客户端和服务器之间的大致通讯过程,最起码你要知道客户端连接的是哪一个服务器,连接的端口是多少,在登录的过程中发送和接受了几个包?而要了解这些东西,你就要使用到网络截包工具了。
我使用的是Microsoft Network Monitor V3.1,简单好用。
下面,我简单介绍一下该软件的使用方法。
安装好程序之后,运行程序,点击【Start Page】页的【Create a new capture tab】按钮,创建一个新的数据捕获会话,点击工具栏上绿色的开始按钮,就可以开始捕获网络数据了。整个程序的界面如下图所示:
各个窗口的作用如下:
Network Conversations下面有二项:
My Traffic代表本机作为发送方或者接收方参与的网络数据包。选中该项后,Frame Summary中将仅仅列出与本机相关的网络数据包。
Other Traffic 则是网络上其他机器之间的网络数据包。因为正好在拦截期内经过本机,所以被顺道拦截了下来。
Capture Filter 是设定拦截数据时的过滤器。
Display Filter 是对拦截结果的过滤设定。
Select Networks 是设定需要拦截本机上的那一个网络。
Aliases用于设定友好名。
Frame Summary 中列出的是符合条件的所有网络数据包
Frame Details则是当前选中的网络数据包的详细结构
Hex Details 则是当前选中网络数据包的二进制格式
3 分析初始阶段C/S网络数据通讯
简单介绍了网络截包工具的使用之后,下面我们就开始初步分析了。
在这篇文章里,我以某款网络游戏作为假定目标。(具体是哪一款,大家就不要深究了。)
首先在【aliases】窗口中将本地客户端和游戏服务器分别命名为:MyComputer和GameServer。注意不要忘了点击【apply】按钮。
然后在【Display Filter】中输入如下语句,仅显示游戏客户端和服务器之间的数据包。数据包类型为TCP是因为网游通讯的协议是TCP协议。
下图中的数据包列表就是目标网游从输入用户名和密码登录游戏到人物出现在游戏中(然后立即退出。)这一阶段客户端和服务器之间的所有往来的数据包。(大家如果不是看得很清楚的话,建议大家放大了看。)
图中红线标识的三个包代表了一个连接的过程。注意它的TCP Flags的变化。
MyComputer è GameServer .S...... 客户端请求建立连接
MyComputer ? GameServer .S..A... 服务器同意建立连接
MyComputer è GameServer ....A... 连接建立
以上三个包称为建立TCP连接的三段式握手。当你调用Socket类的Connect方法时就会产生上面的三个TCP包。
图中蓝线标识的是连接断开的过程。
MyComputer è GameServer F...A... 客户端请求断开连接
MyComputer ? GameServer ....A... 服务器同意断开请求
MyComputer ? GameServer F...A... 服务器请求断开连接
MyComputer è GameServer ....A... 客户端同意断开请求
调用Socket类的Disconnect方法时就会产生上面的四个TCP包。
从上图中我们不难看出在验证用户名和密码的过程中,客户端和服务器之间总共连接了二次,所以在之后的外挂程序编写过程中,我们同样也要连接二次。
TCP Flag为...PA...表示该TCP包内带有数据,而....A...则是回应包,用于回应上一个包的发送方:我已经收到你上一个包了,它本身不带数据。所以一般一个...PA...包都有一个对应的....A...包(例如编号为266和269),但如果回应的时候,发现正好有数据要发送,则可以将回应包掺杂在发送包中发送过去(例如编号为273的回应包就掺杂在275这个包内)。
下面观察客户端和服务器之间的实际数据往来。
1. 客户端连接到服务器
2. MyComputer ? GameServer 服务器给客户端发送7字节的数据
3. MyComputer è GameServer 客户端给服务器发送90字节的数据
4. MyComputer ? GameServer 服务器给客户端发送65字节的数据
5. MyComputer ? GameServer 服务器给客户端发送48字节的数据
6. MyComputer è GameServer 客户端给服务器发送48字节的数据
7. MyComputer ? GameServer 服务器给客户端发送208字节的数据
8. 服务器断开连接
9. ……
以上就是第一次连接的大致过程。观察每个包内的具体传输数据是没有意义的,因为网游之间的通讯肯定是加密的,你每次拦截下来的数据都会不一样。通常游戏服务器给客户端发送的第一个包都是KEY包(例如上面的7字节的包),客户端在接收到KEY包之后执行相应的数据加密初始化。所以接下来的任务就是根据已掌握的数据通讯规律,对游戏客户端的加密算法进行破解了。
2.4 游戏加密算法破解
网络游戏所使用的网络通讯函数肯定也是微软操作系统所提供的标准API函数,所以通常在接受网络数据的API函数中下一个断点,当接收到第一个7字节包时,断点激活,然后逐渐跟进去,查看游戏客户端是如何处理该段数据的,然后我们在外挂中依样画葫芦,进行同样的处理。整个破解过程相当的枯燥无聊,因为面对的都是汇编代码。
由于破解不是很熟悉,所以只能大致的说一下。
2.5 DEMO制作
破解完成之后,就要制作一个能够登录游戏的DEMO了,用于确认游戏加密算法的破解是否成功。
至于选择何种编程语言和工具制作外挂则没有限定,常用的如VC,Delphi,VB…等都可以,具体的编程在此就不具体说明了,可以根据个人的喜好所选择,
下面谈谈网游中数据通讯的基本单位:指令包。
所谓指令包就是代表了一个最基本含义的数据包。比如游戏人物向左移动时,游戏客户端就会向服务器发送一个指令包(人物走路包),通知服务器更新游戏人物的坐标。当游戏人物周围出现一个新的怪物时,服务器会向客户端发送一个指令包(怪物出现包),通知客户端在画面上绘制出该怪物。所以,可以说指令包就是客户端和服务器之间所使用的通讯语言,而外挂的工作就是解析该种语言,然后模拟客户端和服务器端进行通讯。
各个游戏定义的指令包的格式都不一样,但一般一个指令包通常含有以下几个元素:
XX XX XX XX XX XX XX ...
XX XX 红色部分通常与该指令包的长度相关。他可能是指整个指令包的长度,也可能是指他余下部分指令的长度,这需要根据游戏的具体情况来确定。
之所以专门要用一定空间来说明指令包的长度,这是由SOCKET通讯的机制所决定的。
SOCKET连接建立好之后,通过SOCKET连接读取到的数据并不是以指令包为分割的。有可能一个TCP包中正好包含一条指令包,也有可能仅仅包含指令包的一部分(如下图所示)。所以这时候就要根据指令包长度将收到的网络数据截取成单个的指令包。
有一点需要指出的是:刚开始的几个数据包不一定遵循一定的规律,这时候就需要进行特殊处理(因为在开头,所以也比较好处理),而之后的数据包肯定是遵循指令包格式的,不然就乱套了。
XX XX 蓝色部分通常称为指令包标识,用于说明该指令包是属于哪一种类型。比如怪物攻击包,玩家的移动包……,游戏客户端根据收到的相应指令包采取不同的动作。事实上,在客户端程序的内部就是一个很大的Switch语句,用来处理不同的指令包,如下所示:
Switch(指令包类型) { Case 移动包: 绘制相关人物的移动; break; Case 攻击包: 绘制A攻击B的画面; break; … }
XX XX XX 部分是指令包详细的信息,该部分随着不同的指令包而有不同的格式。比如,如果是玩家移动包的话,他就会在此部分详细说明是哪个ID在移动,移动点是从哪儿到哪儿。
DEMO成功制作完成的话,那我们就已经成功了一小半了。接下去的工作主要分为动态和静态二个方面。动态方面是根据已掌握的指令包格式,逐个分析游戏中的各个基本指令。静态方面则是从游戏客户端中解析出相应的资源。
3.1 监控网游客户端的发送包和接受包
要分析网游指令,首先就要得到网游指令的数据样本。那么如何得到网游指令的数据样本呢?
首先想到的是使用网络截包工具,这种方式在网游发展早期的话还有一定的可行性,因为那时候网游大部分采用明文通讯,而现在的网游数据通讯肯定是加密的,所以使用网络截包工具截获到的数据毫无意义。
既然无法使用通用的工具,那我们只能把目光移向游戏客户端了,因为在游戏客户端内处理的肯定是未加密的数据。
像之前的加密破解一样,跟踪游戏对网络数据的处理过程,分别找到游戏中对解密后的指令包的处理函数入口和游戏对要发送指令包进行加密的函数入口这二个地方,然后修改这二处地方入口点的汇编指令,使之先调用我们编写的函数,然后再调用原始的过程。在我们自己编写的函数内部,分别记录下接收到的指令包和要发送的指令包(如下图)。这样,网游客户端的发送包和接受包的监控就完成了。
3.2 分析网游指令的通用方法
能够获得网游指令样本数据之后,接下去就是实际的分析过程了。
一般而言,根据指令包所起的不同作用,可以将游戏指令包分为不同类别:
连接相关指令包 用于与游戏建立连接以及退出游戏时的指令包
玩家属性相关指令包 与玩家本身状态相关的指令包,在刚进入游戏系统时,服务器会发送过来大量的关于玩家角色基本信息的指令包。
环境相关指令包 由于告知玩家周围怪物/NPC/其他玩家状况的指令包
移动相关指令包 与走路相关的指令包
战斗相关指令包 与战斗相关的指令包
交易相关指令包 与交易相关的指令包
……
制作一款外挂,如果只要求基本功能的话,分析20,30个指令包应该就差不多了,如果要求功能比较完善的话,至多50个指令包也就差不多了。
具体分析的方法也很简单,无非是排除干扰因素,逐个击破,以及重复试验,确保分析结果正确。
下面的贴图是我对某一款游戏的28个指令包的具体分析,该款工具在我的站点上提供下载,大家感兴趣的话可以下载来看看,有个感性的认识。
3.4 网游资源解析
游戏资源主要是指包含在网游客户端内的与游戏相关的数据资源:其中最重要的是地图资源,其他的资源包括NPC的位置坐标啊,地图传送点的坐标啊,等等。
3.4.1 地图资源解析
地图资源的解析是外挂制作中很重要的一个方面,寻路算法以及地图间的自动移动等都要依赖于地图资源。
外挂中所使用的地图资源不完全等同于游戏中使用的地图资源。游戏中使用的地图资源包含有更多的信息,而外挂所使用的地图称之为BOOL地图,它仅仅包含一项信息:指定的某一点是可移动点还是障碍点。
例如上图就是某个游戏地图所对应的BOOL地图,其中蓝色部分代表不可移动区域,白色部分代表可移动区域。(另外绿色的点是通过解析其他的资源文件获得的NPC的坐标点,红色点是传送点。)
那么如何获得游戏地图所对应的地图资源呢?通常在网游客户端的程序安装目录内会存在一个类似map或者res之类的目录。地图资源处在其中的可能性很大,而且地图资源本身的文件格式也比较明显,通常它都是以如下的格式存在的:
前面N个字节的地图头信息中肯定包含了地图的宽度信息和高度信息,设宽度和高度分别为W和H。后面的部分通常都是地图点信息。地图上的一个点通常由n个字节所构成,整个地图文件的大小由此计算而得: N + (W*H*n)。
所以判断是否是地图文件很简单,只要看一下文件的头,然后查看一下文件的大小。如果有一组文件满足上面的规律的话,那基本上可以肯定是地图资源文件了。
接下来就是要把游戏地图转化为BOOL地图。前面提到地图文件中地图上的一个点通常有n个字节所构成,里面含有很多丰富的信息,而BOOL地图所关心的是否是可移动点的信息通常仅需要用1位即可表示。(注意是位,1个字节有8位,所以n个字节总共有8n位)将一张游戏地图中所有点的该位信息收集起来组成的新的地图就是BOOL地图。它标示了地图中那些区域玩家是可移动的,那些区域是不可移动的,为后面的寻路算法提供了基础数据。
原理明白了,接下去就是写一个程序解析地图资源。大致步骤如下:
1. 打开一个地图文件
2. 读入地图文件的头信息,解析出地图宽度和高度
3. 读入地图点信息,对每一个点所代表的n字节数据执行位操作,提炼出其中某一位的信息,保存到自己的结构中。(此处我建议大家采用BMP格式的数据来保存提炼出来的位信息,好处有三点:一是保存完之后,直接可以用图片浏览工具查看结果,不必自己再写一个绘制的程序,二是使用BMP格式保存的话,保存的数据容量也小,三是在外挂中显示地图时可以将BMP图片直接作为背景图片贴在窗口上。)
由于之前你尚无法确定n字节中的哪一位代表了点的是否可移动属性,所以每一位你都要取一遍组成一幅地图,然后查看哪一幅和游戏地图最接近。多读几个地图文件做实验,很容易就可以确认下来的。
3.4.2 其他资源的解析
地图资源的解析是通过了解物理磁盘上地图文件的保存格式,然后自己写程序解析出来的,使用这种方法还可以解析其他很多资源信息。大家可以仔细观察游戏的安装目录,根据子目录和文件的名字可以分析出很多有用的信息。
但目前游戏厂商也越来越狡猾了,保存在磁盘上的资源文件通常进行了变形(压缩或者加密),使你无法通过简单的分析获得你所需要的信息。
一种解决办法就是观察游戏是如何处理变型的资源文件的。因为在游戏中资源肯定是以原始形式存在的,通常都是在游戏初始化的时候,从磁盘上读入变形的资源文件,然后将其恢复为原始状态的资源形式,我们就跟踪该段的处理过程,然后自己模仿写一段程序将变形资源恢复为原始资源形式。
另外一种方法就是直接从游戏的内存中读取有用的资源信息。该方法的理论依据就是:资源信息在游戏中肯定是明文形态,而且是被有序组织的。比如,如果你想要获得所有游戏物品的信息列表,你可以随意选择一个物品名称,然后在游戏的内存中查找他的位置。所有的物品在游戏内存中肯定是以某种链表的形式存在的,你只要找到了一个,就可以顺藤摸瓜,找到该链表的头,然后自己写一个程序,读写游戏的内存空间,将整个游戏的物品列表全部读取出来。
5.1 寻路算法
外挂中最有名的,也最重要的一个算法就是寻路算法了。所谓寻路算法就是指给定一张地图数据,以及起始点和目标点,然后利用算法计算出一条路径来。它所依赖的数据基础是BOOL地图,这个我们在之前的讲述中已经成功获得了。下面讲一下具体的算法。
常用的寻路算法实现有二种,一种是A*算法,还有一种等高线算法。还记得在大学里面学过遍历图的二种算法吗,一种是深度优先,一种是广度优先。A*算法就对应了深度优先算法,而等高线算法则对应了广度优先算法。
A*算法是最常用的寻路算法了,不过它也有个很大的缺陷,那就是计算出来的路径通常是贴边的,所以如果你在游戏中观察用外挂控制的人物的走动的话,你会发现他通常是沿着障碍物的边走动的,走动起来显得很不自然。
A*算法和等高线算法在网上都有很多例子,在我的站点上也提供了这二个算法的实现(C++版)。下面这张图显示的是A*算法和等高算法的具体应用。
另外一点需要指出的是,寻路算法以及之前提到的BOOL地图的解析针对的都是2D的网游,那些纯3D的网游中的人物采用的是碰撞模型,由于没怎么接触过,所以这方面具体如何处理不是很清楚。
顺便提一下游戏中的走路。目前的2D网游中对于人物走动的处理方式主要有二种:一种是直接向服务器发送玩家要到达的目标地址,还有一种是以当前的坐标点为基点,给服务器发送相应的偏移量。
直接发送目标地址的方式,如果网游服务器端做的不够严谨的话(没有对玩家要移动的地址和玩家当前地址之间的距离进行校验),可能会存在瞬移的BUG可供外挂利用。(以前我就曾经碰到过一款有瞬移BUG的网游,利用外挂飞来飞去,飞得太猛了,后来就被游戏开发商给修正了。)
发送偏移量的移动方式见下图,●是当前玩家所在的位置,如果玩家需要向上(即向北)移动一步的话,则向服务器发送偏移量7,如果要向斜向角(即西南方向)移动一步的话,则发送偏移量4。很明显,发送偏移量的移动方式不存在瞬移的可能性。
5.2 其他算法
外挂中除了寻路算法之外,还有其他的一些算法应用,比如地图间移动算法:在已知各个地图间传送点的情况下,计算出从地图A移动到地图B所要经过的所有地图,这同样是一个经典的图论算法问题。
此外还有打怪时如何搜索最近怪物的算法,以及最有效的自动战斗的算法,这些算法要根据每款游戏的实际情况而进行相应的变动。
网游外挂产业真的是一个很有趣的领域,他主要是包含二个方面:技术和营销。
技术方面,网游外挂所涉及的技术之广并不逊色于一款网游所涉及的技术。其中技术难度最大的还是破解方面,据闻中国几大顶尖的破解组织高手大部分都与外挂破解有或多或少的联系。近几年随着大部分的游戏都运用了NProtect,在与NProtect的逐渐斗法过程中,战场从RING3层逐渐转移到系统内核层,也着实培养出了一批对于Window内核有深刻理解的高手,国人之幸啊。
讨论网游的技术是一个很有趣的话题,但个人认为更有趣的方面在于网游外挂的营销。由于近几年网游外挂制作团队的大量涌现。同一款游戏常常有着好几家外挂在互相竞争。这时候的外挂营销就像一个硝烟弥漫的战场,你不仅要与外挂同行竞争,还要和游戏发行商互相斗法,同时随着近几年相关法律的健全,你还要小心自己不要被相关政府部分盯上。
在与同行竞争的过程中,不仅要比拼技术(游戏采用了更严密的保护手段,你还要能破解它),比拼反应时间(游戏客户端有了更新,你要迅速反应),更要比拼营销手段,推出各种各样的优惠套餐,尽可能的拉拢住更多的客户,比如,如果外挂单月的收费是20,则半年只要100,全年只要180,这样表面上你好像少收了钱,但实际上你把客户和你牢牢的绑定住了,即使竞争对手推出更好更便宜的外挂,你也不用害怕,因为你有足够的时间来反应。类似的手段还有很多,这主要看你的营销水平了。
同时还要处理好与竞争对手之间的关系,能很快消灭对手的,则绝不留情。明显不如对手,且对手满怀敌意的,则干脆开放免费版,让大家都不好受。势均力敌的,能结成同盟的最好达成价格联盟,避免互相砍价给彼此造成损失。互相敌视的,则要尽量给竞争对手下绊子,比如攻击对手的站点啊,到他的论坛上面捣乱啊……,总之就是想尽办法击败对手,取得一家独大的场面,一旦你能在一款游戏里面吃独食,形成垄断,那外挂的价格就随你定了。够你爽的。
外挂的营销就像一个群雄并起的战国时代,大家各施手段,各凭本事,看谁能笑到最后。这里面发生过很多有趣的故事。不过近几年相关法律越来越严格了,所以并不建议大家踏入这个泥水潭。