魔兽局域网协议UDP部分详细解释

来源:互联网 发布:响应式网站源码下载 编辑:程序博客网 时间:2024/04/30 21:55

魔兽局域网主要有4种消息 
第一种、搜索游戏: 
F7 2F 10 00 50 58 33 57 15 00 00 00 00 00 00 00 ?PX3W 
这个格式比较简单。 
F7 2F 10 00 是格式头部,消息含义的标志。 
50 58 33 57 是PX3W几个字,就是冰封王座的逆序。 
15 00 00 00 是版本号,0x15=21,即是1.21版的冰封王座在搜索游戏。 
00 00 00 00 是某个魔兽的标志,看似无意义,实际很重要。后面会说明。 

魔兽在多种情况下都会发布此消息,例如刚进入局域网,从游戏中退出,从创建的游戏中退出等等。 

第二种、结束游戏: 
F7 33 08 00 00 00 00 00 
F7 33 08 00为消息内容标志,00 00 00 00同第一种消息,后面说明。 
魔兽在收到此消息后会从游戏列表中删除对应IP的游戏。 
魔兽在取消游戏或者开始游戏时会发送此消息。 

第三种、LANTag 
这个是魔兽中传输次数最多的消息。短小但是作用多。 
F7 32 10 00 00 00 00 00 01 00 00 00 00 00 00 00 ? 
F7 32 10 00 消息标志,不多说了。 
00 00 00 00 神秘标志。 
01 00 00 00 忘了,貌似是固定值 
02 00 00 00 空余位置数+1 

那个特殊的标志是什么呢?那个就是魔兽创建游戏的次数。 
它表示了当前是第几次游戏。关闭游戏后重置为0。看似这个是没什么用的标志,但是魔兽程序对收到的消息中这个值不对(和当前系统游戏次数不同)的消息都是无视,例如创建了8次游戏的魔兽服务器(主机),对F7 2F 10 00 50 58 33 57 15 00 00 00 01 00 00 00是没有反映的,F7 2F 10 00 50 58 33 57 15 00 00 00 08 00 00 00才能正常的返回游戏信息。但是作为一个特例,所有主机对00都有响应。但是其中还稍有不同。我们先把这个标志成为tagcount。 

这个LANtag有很多用处。处于等待状态的魔兽收到lantag后会发送一个tagcount和lantag中相同的搜索游戏消息(第一种消息)。已经搜索到对应IP创建的游戏的魔兽会根据lantag改变游戏列表中空余位置的显示。同时tagcount=00的特殊性就体现在这里,搜索到某IP创建的游戏的魔兽对00会返回搜索游戏消息,而不管是从哪个ip发来的,而对从该IP发送过来的tagcount不等于0的lantag无返回消息。 

第四种、游戏信息: 




F7 30 8B 00消息标志,略过。 
58 33 57 15 冰封王座标志,略过。 
15 00 00 00 版本号。 
01 00 00 00 tagcount,请参考上文。 
39 0A E5 01 未知,每次消息都不同 
00 01 03 49 07 01 01 55 01 D1 55 01 0D 65 C3 9B:未知,包含例如是否开图,是否开启裁判等信息。 
E5 BD 93 E5 9C B0 E5 B1 80 E5 9F 9F E7 BD 91 E5 86 85 E7 9A 84 E6 B8 B8 E6 88 8F 20 28 46 6C 00:UTF-8的局域网游戏名称“当地局域网内的游戏 (Fl”。 
4D EB 61 71 73 5D 69 65 73 A1 75 5D 
29 33 29 55 65 75 73 65 6F 61 73 53 75 63 61 6F 
65 2F 77 33 79 B1 01 47 6D 79 69 6F 67 1B 53 6F 
6F 77 01 01 
一段简单加密的信息,地图和创建者信息。加密规则如下。 
从"(Fl/0"后开始往后第10个字节开始,每8个为一个加密组,例如: 
D1 55 01 0D 65 C3 9B 4D为一个加密组,D1为密钥。 
EB 61 71 73 5D 69 65 73为一个加密组,EB为密钥。 
其实是一段简单的奇偶校验加密。 
0xEB=11101011。将二进制字符串逆序取反为00101000,所以,正确字符串为: 
EB-0 61-0 71-1 73-0 5D-1 69-0 65-0 73-0 
其中密钥位舍去,得61 70 73 5C 69 65 73即为aps/ies 
如此解密此部分数据为: 
Maps/iest/(2)EchoIsles.w3x/0FlyingSnow/0/0 
/0为结束符,即二进制00。 
最后以一个00最结束。 
02 00 00 00:游戏总共允许玩家。 
01 00 00 00:未知,似乎是电脑数。 
01 00 00 00:未知,似乎是玩家数。 
01 00 00 00:剩余空位。 
08 00 00 00:未知。似乎是定值。 
E0 17=0x17E0=6112,游戏端口。 
至此分析完毕。 
游戏数据流程是,魔兽发送搜索信息->接受游戏信息->根据Lantag调整空闲人数。 
魔兽启动局域网时会发送一个搜索信息广播(仅当前子网),仅广播一次。 
当新游戏主机加入时,该游戏主机广播一个Lantag,魔兽收到Lantag后向该主机发送搜索消息。游戏主机在创建完游戏等待加入时每隔一段时间广播一个Lantag。游戏主机的空闲位置有任何变化时广播Lantag。 
取消或开始游戏后发送结束消息

最近老有人问我是不是出了改dota英雄技能的外挂,什么月骑无限大,剑圣无限斩,巫妖无限弹之类。
我在这里一并回答一下,并且稍微说说原理。因为我对地图方面其实是一窍不通,如果有说的不对的地方,还请指正。

其实这些现象都是使用了作弊地图导致的。本来魔兽争霸是有一个地图验证的,如果你跟主机的图不同,是进不去的(要下载地图)。但是魔兽对地图中的war3map.j文件是进行bcc(block check character)校验的,bcc不同于md5,bcc一般只是用来排错的,并不是加密算法。所以就有人写出了这样的代码,可以在b文件末尾添加上一些不起作用的字串,来让b文件的bcc校验码等于a文件(具体代码我就不贴出来了,很容易搜到)。于是呢,我们就可以做到随意修改地图中的war3map.j ,然后再处理一下,使之跟原来的war3map.j的bcc校验码相同。再把改过并处理后的war3map.j文件替换原来的,这样做出来的作弊地图,暴雪的验证会因为bcc校验相同,而把它认为和原版图是相同的。达到的效果就是,别人用正版图建主机,你可以进入,你用盗版图建主机,别人用正版图也可以进入。但是别以为可以为所欲为的修改war3map.j ,虽然你突破了验证这一关进入了游戏,但是魔兽的联机机制是没有办法突破的。

在这里稍微谈一下魔兽的联机机制,没兴趣的请略过这一段。魔兽联机时,一直有个同步机制,每个联机的玩家都会同时计算所有数据,一旦有不一致,就会导致掉线,这也是为什么用金山游侠之类的游戏修改器单机时可以改钱,联机时一改就掉线。因为你只能修改你自己的机器上的数据,而无法改别人的,单方面修改的结果就是造成你跟其他人不同,你就会掉线。当然,如果所有人同时修改的话,仍然是不会掉线的,所以现在有一些联机修改器,参加游戏的几个玩家一起开这个修改器,可以在玩rpg时改钱什么的,我几个同学就老是用这种修改器来通关一些很难打的rpg图。顺便说一下,这样玩下来保存的replay是无法正常播放的,因为replay只记录动作,你使用修改器的改动不会被记录,播放replay时会因为你并未像你游戏时那样修改数据,造成replay不合逻辑而出错。再顺便说一下吧,为什么所谓的人品外挂并不能实现。曾有人发帖抱怨,怎么蓝胖子次次放招都多重施法,怎么某人每次都暴击,他们是不是用了人品挂。其实这是不可能的,有人以为魔兽中的随机数据都是由主机计算的,这样主机就可以找到办法来修改随机数,造成每次都对他有利的结果。但是实际中并非如此,随机数也是所有人一起计算的,也就是说魔兽里的随机是个伪随机。在一局游戏一开始时,主机会发给每个玩家一个随机数种子(这个种子很有可能就是主机从建立主机到游戏开始所经历的毫秒数),之后的一整局中,所有的随机数都根据这个随机数种子,依照事先定好的算法计算出来,这样也就保证了所有人计算出同样的“随机”结果。另外,这个随机种子也会记录进replay,这也从一个侧面说明了魔兽里的随机是伪随机,如果是真的随机,replay就无法重现了。说的有点多了,下面回到正题。

因为魔兽联机机制的存在,你要是随意改了war3map.j,例如改成给自己增加10000的钱,但是别人是按照的没有修改的war3map.j,在别人机器中你是没有那么多钱的。这时你买一个8000的物品,在你自己机器上是可以的,因为你有10000的钱,但是在其他人机器上,你钱却根本不够!这样的不合理动作就会造成你跟其他人断开连接。
也就是说,你只能修改那些不会造成冲突的地方。例如有些作弊图可以显示出地图全开的效果,因为这些显示的东西只是在你本地机器上显示出来的,并不会对其他玩家照成冲突。类似这样的修改都是可行的,不会掉线。
那么,为什么会出现这种有变态技能效果的dota作弊图呢?我刚开始也很困惑,这么夸张的改动怎么竟然没有掉线?我跟朋友要了个作弊图玩的replay,在我的机器上,用正版dota地图播放,竟然完全再现了那些变态效果!因为我对地图方面并不了解,所以开始上网找资料,并通过qq向某些搞地图的高人请教,又下载了那个变态版dota作弊图和某平台私自山寨的所谓“原版”dota图,提取出来war3map.j来进行对比。经过n久的努力,总算搞明白他是怎么改出来这种效果的了。
原来是因为dota使用到了game cache,而作弊图是单方面修改了game cache中的数据,然后通过函数同步给了所有的玩家。通俗点说,game cache相当于一个池子,所有玩家共享这块区域,任意一个玩家都可以修改这个池中的数据,也可以发出通知,让所有人都来同步这个池子,这样就变相修改了其他人的数据。举个例子,例如dota里黑曜石的放逐技能,它可以减少一个人的智力,一分钟后再归还给他,dota里关于这个技能的函数,把目标和要归还的智力值记录在game cache中,1分钟之后会再从game cache取出目标和智力值,给目标加上相应的智力值,就完成了归还这个人的智力的过程。但是在作弊图中,这里增加了代码,先进行一个判断,如果黑曜石是本机玩家,会把game cache中记录的目标改成本方随机的一个队友,然后把game cache中记录的智力值改为500,然后通知所有玩家同步game cache中的这两个值,这样就完成了对所有人game chche中这两个值的修改。1分钟一到,dota就会向这个目标“归还”智力,这样,本方的一个玩家就凭空增加了500智力。(那个被减少智力的倒霉玩家就无法被归还了,可怜)
大致的原理就是这样了,具体细节我就不详细叙述了。不过dota用到game cache的地方其实并不多,所以能改的地方也就那几个。这也是为什么作弊图要专门改这几个地方,而不是改成例如加钱或者加攻击力或者直接胜利之类的,不是不想改,而是无法实现。另外,暴雪官方的地图是不会这样使用game cache的,所以不用担心对战地图被改(另外对战图还有暴雪标志的保护)。其他的rpg地图,如果本身没有用到game cache的,也就改不出来什么花样,最多显示个全图之类。

暴雪将会在1.23修补这个地图验证漏洞,目前1.23的补丁已经在测试中了,相信升级之后,这种改图作弊将不复存在。只是不知国内玩家到时是不是还要继续死守bug频出的1.20呢?
强行插入广告一则:浩方平台会再对地图进行自己的验证,md5验证,作弊图是无法通过的。
至于做山寨dota图的某平台嘛,就我目前来看,它是没有任何地图验证的,唉。

 

主要UDP包:
收索包:
内容:F7 2F 10 00 50 58 33 57 15 00 00 00 00 00 00 00
功能:向主机提出收索信息。问别人“你建什么主机?”
在打开魔兽进入局域网的时候,会向当前网段(255.255.255.255)广播这个包。只要条件符合,收到这个包的主机都会返回一个地图信息给他(他:这个收索包的IP端口)
主机包:
内容:F7 32 10 00 00 00 00 00 01 00 00 00 00 00 00 00
功能:告诉别人:“我建主机了,要不要看看。”
建立主机的时候开始,向当前网段广播这个包,每5秒钟一次。收到这包的客户机会发送搜索包。
地图包:
内容:  
F7 30 8C 00 50 58 33 57  14 00 00 00 01 00 00 00  
39 69 C2 00 E5 BD 93 E5  9C B0 E5 B1 80 E5 9F 9F  
E7 BD 91 E5 86 85 E7 9A  84 E6 B8 B8 E6 88 8F 20   
28 76 73 00 00 01 03 49  07 01 01 77 01 B9 79 01   
99 D5 B9 31 4D CB 61 71  73 5D 45 6F 77 19 6F 6D   
6F 61 65 5D 45 2B 6F 75  41 21 41 6D 6D 2B 73 75  
61 73 73 21 77 B1 37 2F  37 31 63 2F 77 23 33 79   
01 77 73 01 01 00 0A 00  00 00 01 00 00 00 01 00 
00 00 0A 00 00 00 1B 00  00 00 E0 17              
功能:“这就是我所建的图,你好好看。”
主机收到搜索包之后就把这个包返回给他,包括所有有用信息。

魔兽的工作流程

魔兽进入局域网的时候会广播一个搜索包,只发送一次。只发送当前网段(255.255.255.255),所以我们的魔兽只能看到本寝室,或者少数几个寝室的几个主机。

建立了了主机的魔兽收到之后就会发送一个包给他,这个包就是地图信息,包括地图信息,主机名,加入了多少人,剩下多少位置,还有一个重要的数据就是游戏的端口。一般魔兽的端口是6112.

建立主机的魔兽会向本地发送一个包,“我建立主机了”

搜到这条消息的魔兽会发送一个搜索包给主机。

主机就发送 地图信息。

收到之后就解析地图,这时候大家就看到了有人建主了                   点击加入· ~  建立tcp连接 一直到推出主机的游戏

ps: 一场游戏下来,和主机发送的包 大概25MB(半小时) 主机收发的包就是 9*25 MB/30 min ;//按照dota计算 一个主+9个客户端的10人游戏。 这样粗略的估计主机的网速要求就是 9*25*1024/30*60=128>100 kb/s 加上一点点别的程序所要的通讯包。要想不卡,主机的网速需要保证这个数吧。


关键技术

1,监听主机(建立了魔兽地图的机器)的地图信息。
      
      有两种方法能获得地图信息,一种是抓包,把所有的和6112端口有关的包都抓过来分析。(个人觉得这样电脑的负担太大了)。现在的多数搜索器都是这样实现的。
      但是Java要实现抓包不是很容易。c++能实现这个功能,可以考虑用c++编译一个dll。Java调用。或者用开源项目。搜搜就能找到。
      
      我用的方法是建立一个线程。每5秒钟发送一个包收索本机是否建立主机。如果自己建立了主机,则会返回一个地图信息包。收到之后告诉其他ip“我建主了”;
      这样客户端就不需要一直发送搜索包了。
      找到了主机,一切都好办了。
 2,告诉别人我建主机了
      如何告诉别人我建立了主机。很简单,建立了主机的魔兽会每5秒钟发送一个包给当前网段,告诉别人我建主机了。
      我们只要把这个包发送到其他ip的6112端口就ok了。就是告诉别人“我建主了”,收到的人就会发送一个包:“看看什么图”,然后主机就会回复一个包,没错这就    是地图信息!
      
 3,解析地图
      不解析地图不会对游戏产生任何影响。因为魔兽接受地图包,自己解析,它很明白这图是什么。但是解析地图,你可以知道主机建立的这个地图是什么,主机叫什么    名字,有几个人加入,有几个电脑。还有几个空位置。主机是什么版本。这些很有用的信息在软件上显示出来时很有用的!
      关于UDP包的解说有好多的文章。大家可以去google上搜索一下,关键字 魔兽 UDP 
      我这里就几点补充。

这个是网上的:

02 00 00 00:游戏总共允许玩家。 
01 00 00 00:未知,似乎是电脑数。 
01 00 00 00:未知,似乎是玩家数。 
01 00 00 00:剩余空位。 
08 00 00 00:未知。似乎是定值。

E0 17=0x17E0=6112,游戏端口。


02 00 00 00:游戏总共允许玩家。 
01 00 00 00:未知,这似乎是定值。 
01 00 00 00:已知,这就是是玩家数。 
01 00 00 00:已知,除电脑外的所有空位。 
08 00 00 00:未知。不断变化着……。

E0 17=0x17E0=6112,游戏端口。

 

  1. all = map[map.length - 22];  
  2. unknown = map[map.length - 18];  
  3. people = map[map.length - 14];  
  4. esidescp= map[map.length - 10];// 这个数是这样计算的:除电脑外的所有位置,包括已经有人的位置,例如总数是10个,加了3个电脑,则这个数就是7,不关那7个位置是否有无人。  

 

// 这个数是这样计算的:除电脑外的所有位置,包括已经有人的位置,例如总数是10个,加了3个电脑,则这个数就是7,不关那7个位置是否有无人。

这里把地图的解析代码贴出来。

 

view plaincopy to clipboardprint?
  1. /** 
  2.  * 魔兽的主机节点(游戏中的“建主”了,也就是建立了什么地图) 
  3.  * 解析主机信息 
  4.  * 生成一个主机节点,包括地图信息,版本,人数,等等 
  5.  *参数:byte[] 地图信息包,InetAddress 包的ip地址,int 延时 
  6.  */  
  7. package xinyu126.common;  
  8. import java.io.UnsupportedEncodingException;  
  9. import java.net.InetAddress;  
  10. import java.util.Arrays;  
  11. import java.util.Vector;  
  12. /** 
  13.  * @author xinyu126 
  14.  *  
  15.  */  
  16. public class WarNode {  
  17.     String serverName;  
  18.     String serverInfo;  
  19.     String mapStr;  
  20.     int all;  
  21.     int besidescp;  
  22.     int people;  
  23.     int unknow;  
  24.     int version;  
  25.     int timeDelay;  
  26.     public InetAddress IP = null;  
  27.     public boolean checked = true;  
  28.     public WarNode(byte[] map, InetAddress IP, int delay) {  
  29.         int i = 0;  
  30.         if (map[0] != (byte0xf7 || map[1] != (byte0x30) {  
  31.             // 这个不是地图信息!  
  32.             return;  
  33.         }  
  34.         this.IP = IP;  
  35.         this.timeDelay = delay;  
  36.         // 第八个是版本,1.20(20) 1.21(21)什么的  
  37.         version = map[8];  
  38.         // 从第二十个开始  
  39.         // 游戏信息,大部分是:“当地局域网内游戏(X……”  
  40.         byte[] t = new byte[32];  
  41.         for (i = 0; i < 32; i++) {  
  42.             t[i] = map[i + 20];  
  43.         }  
  44.         try {  
  45.             serverInfo = new String(t, "UTF-8");  
  46.         } catch (UnsupportedEncodingException e) {  
  47.             e.printStackTrace();  
  48.         }  
  49.           
  50.         // 现在开始解析地图路径和主机的名字  
  51.         i = 69;  
  52.         byte[] mapStr = new byte[64];  
  53.         t = new byte[32];  
  54.         int v = 0;  
  55.         int n = 0;  
  56.         boolean flag = true;  
  57.         do {  
  58.             String mm = "00000000" + Integer.toBinaryString(~map[i]);  
  59.             // System.out.println(mm);  
  60.             for (int j = 1; j < 8; j++) {  
  61.                 int c = map[i + j];  
  62.                 if (c == 0) {  
  63.                     // 如果遇到0x00表示已经结束了  
  64.                     break;  
  65.                 }  
  66.                 int k = '1' == mm.charAt(mm.length() - j - 1) ? 1 : 0;  
  67.                 // System.out.println(k);  
  68.                   
  69.                 if (c == 1) {  
  70.                     // 当遇到第一个 0x01的时候表示地图路径完事了,开始解析主机的名字  
  71.                     flag = false;  
  72.                 }  
  73.                 if (flag) {  
  74.                     // 加到地图上  
  75.                     mapStr[v] = (byte) (c - k);  
  76.                     v++;  
  77.                 } else {  
  78.                     // 加到名字上  
  79.                     // 注意这里:如果名字不够长,这8个字节中不能放下01 01 00这三个字节,则会在后面添上“争霸”这个两个中文“d5  
  80.                     // f9 b1 d5”,然后另起8个字节,放下01 01 00.这个时候要注意去掉这个“争霸”。防止乱码  
  81.                     //   
  82.                     // TODO 暂时这样处理。知道还有很多问题  
  83.                     if (c != (byte0xd5 && c != (byte0xf9 && c != (byte0xb1) {  
  84.                         t[n] = (byte) (c - k);  
  85.                         n++;  
  86.                     }  
  87.                 }                 
  88.             }  
  89.             i += 8;  
  90.         } while (map[i] != 1 && i < map.length - 25);  
  91.         this.mapStr = "M" + new String(Arrays.copyOf(mapStr, v));  
  92.         serverName = new String(Arrays.copyOf(t, n));  
  93.         all = map[map.length - 22];  
  94.         unknow = map[map.length - 18];  
  95.         people = map[map.length - 14];//  
  96.         besidescp = map[map.length - 10];// 这个数是这样计算的:除电脑外的所有位置,包括已经有人的位置,例如总数是10个,加了3个电脑,则这个数就是7,不关那7个位置是否有无人。  
  97.         // System.out.println(serverInfo + "  " + serverName + " " + this.mapStr  
  98.         // + all + " " + computer);  
  99.     }  
  100.     public Vector<String> getInfo() {  
  101.         Vector<String> vv=new Vector<String>();  
  102.         vv.add("1." + version);  
  103.         vv.add(IP.getHostAddress());  
  104.         vv.add(serverName);  
  105.         vv.add(serverInfo);  
  106.         vv.add(mapStr);  
  107.         vv.add("" + (all - besidescp + people) + "|" + all);  
  108.         vv.add(String.valueOf(all - besidescp));  
  109.         vv.add("" + timeDelay);  
  110.         return vv;  
  111.     }  
  112.     public void setTimeDelay(int delay) {  
  113.         this.timeDelay = delay;  
  114.     }  
  115. }  

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 天猫跨店优惠券用了退货怎么办 淘宝店铺没流量没访客怎么办 京东微信和Q端黑号了怎么办? 买不了运费险了怎么办 拼多多5天不发货怎么办 天猫店手机发货成定制机怎么办 天猫退货上门取件退两件怎么办 买二手苹果手机没有账号怎么办 手机淘宝足迹不更新怎么办 淘宝申请退款不想退了怎么办 荣耀3c主板坏了怎么办 荣耀10天气删了怎么办 荣耀7i手机卡顿怎么办 荣耀v9总是自己拨号怎么办 华为荣耀5x很卡怎么办 华为荣耀6plus卡怎么办 华为手机触屏不灵敏怎么办 华为荣耀6x太卡怎么办 华为荣耀7太卡怎么办 荣耀手机开不开机怎么办 华为g750手机开不了机怎么办 华为手机开不了机怎么办 小米手机刷机后激活不了帐号怎么办 魅蓝note5卡顿怎么办 魅蓝note5卡了怎么办 魅蓝note5很卡怎么办 魅蓝note5锁了怎么办 荣耀9开不开机怎么办 4s更新后用不了怎么办 魅蓝3开不了机怎么办 手机不支持联通4g网络怎么办 华为手机出现emui界面怎么办 华为畅玩4x内存不足怎么办 手机电源键掉了怎么办 手机电源键坏了怎么办 小米5s听筒声音小怎么办 荣耀8电源键失灵怎么办 华为荣耀3c卡怎么办 大王卡是2g网络怎么办 联通停用2g副卡怎么办 华为荣耀8忘记解锁密码怎么办