魔兽搜索器研究,But Failed in 2007

@Author:cjcj  cj.yangjun@gmail.com <c-j.iteye.com>

好几年没碰了...恰好碰到坛子里xinyu同学发布了一个JAVA版,也为这个研究写完最后的完结... 感谢xinyu同学对地图包的分析,才使这个有了归宿.

关于xinyu的帖子见论坛:http://www.iteye.com/topic/503841

 

两款工具

1,lancraft(魔兽搜索器)

2,BattleLan(跨网关连接器)

 

两种原理

1,lancraft是专门针对War3游戏的搜索器工具,通过发送UDP搜索游戏包和转发给本地War3游戏UDP包来建立跨网关连接

2,BattleLan是一个更通用的工具,不仅仅War3游戏,几乎所有需要跨网关的应用程序都可以建立连接,例如飞鸽,Windows共享等等,所以推测它是Hook了Windows的send()方法,将本机发送255.255.255.255的广播包的数据包同时发送给指定IP地址一份.

 

Lancraft建立War3游戏流程

 

-B启动War3,并建图

-A启动War3,开启lancraft工具,填写B的IP

-lancraft开启6110端口向B的War3游戏端口(6112)发送"搜索包"(UDP)

-B的War3游戏收到"搜索包"后,发送"地图信息包"(UDP)给A

-A收到"地图信息包"后,转发给A的War3进程

-A的War3游戏收到"地图信息包"后,看到主机,并进入游戏,此后A和B建立TCP连接

 

A-----搜索包------>B

A<---地图包--------B

A<----TCP连接--->B

 

实现要点

1,发送"搜索包",你必须知道UDP包的内容,这个可以通过抓包工具获得,见附录.

 

2,"地图包"里包含了端口信息."暴雪"公司这样设计让我们不用转发TCP包或者用JAVA伪造一个源端口的UDP包了.游戏连接的端口完全取决于"地图包"的端口信息,而非进程通讯的端口.(不知道我说明白了没)

 

 

一个case

简单写了一个case,可以简单在本机看到效果.代码见附件case.java.

 

运行步骤:

首先启动War3,建图.

运行case.java程序.

本机取消建图.

过10秒钟,你可以在"局域网游戏"里看到自己建立的"主机"

 

测试结果如下(因为没有在学校了,TCP连接测试不太好测,有兴趣的同学可以帮忙测试下):

 


后面是大三那会写的,由于技术的认识问题,难免有错误的地方,但尽量保持原汁原味...

    首先来介绍的是另一款工具BattleLan(跨网关联机工具,利用的SPI注入send方法来达到跨网连接,这款工具02年做的,国内这样的工具还挺少的),它能连接一个校园网内不在同一LAN的工具,我们用来连机打WAR3游戏的。 
    而有款专门连接WAR3的工具叫lancraft,今天突然对这个东西感兴趣了。
    很巧的是在网上找了一个志同道合的兄弟,现在我们自己想做一个类似的出来。工程应该不大,但技术难点应该在本地数据包的拦截。(SPI好象可以做到,具体的就不清楚了)
    lancraft它不象浩方一个有个公共服务器平台来转发和记录TCP包信息。它只需要一方启用lancraft,另一方建立主机,就象2台机器象同一个LAN一样进行游戏了。

    比如 A:172.18.78.61 MASK:255.255.255.0  Agateway:172.18.78.1  
         B: 172.18.84.34 MASK:255.255.255.0  Bgateway:172.18.84.1

B(WAR3主机),A -》lancraft-》填写IP:172.18.84.34-》启动WAR3-》进入主机

    现在了解的程度: 

          1,网关服务器一般是不会进行广播转发的(它已经是在网络层以上的设备了,为了防止广播风暴而禁止转发包),后来发现网关设备是可以转发广播报文的。 
          2,是基于TCP/IP协议做的 
          3,没找到源码
              

    推测基本流程1: WAR3发送UDP(带游戏数据的广播报文)到本网段,lancraft使UDP通过网关设备转发到指定IP的子网(网关设备可能必须支持转发广播包功能),当主机收到UDP后就进行TCP连接。


实现要点:主要知道了是通过转发UDP包,发送定向广播报文
问题:游戏主机所在的子网其他主机是否会收到广播报文

推测基本流程2:通过反复抓包发现BL并不即时发送广播,按照SL的说法是利用WINHOOK监视WSOCK32.DLL,估计使用到SEND方法时BL再发送UDP到指定的目的IP(或者重载SEND等方法)。网关通过NAT把这个包传达到目的地址,目的地址做出反映,使主机被认为是本地子网的机器。

############################################
向另一个子网目标IP(172.18.84.34)UDP包(通过发送
F7 2F 10 00 50 58 33 57  14 00 00 00 00 00 00 00 16byte的UDP数据报文给目的IP,用BIND帮定本地6110端口和发送到目的6112端口)。


代码如下:

// Tools:VC 
// OS: windows xp 
private void btnOK_Click(object sender, EventArgs e) 
        { 
            strName = txtName.Text; 
            try 
            { 
                //Using UDP sockets 
                clientSocket = new Socket(AddressFamily.InterNetwork, 
                    SocketType.Dgram, ProtocolType.Udp); 
                //IP address of the server machine 
                IPAddress ipAddress = IPAddress.Parse("172.18.84.3"); 
                //Server is listening on port 1000 
                IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 6112); 
                epServer = (EndPoint)ipEndPoint; 
                 
                Data msgToSend = new Data (); 
               
                byte[] byteData = msgToSend.ToByte(); 
                 
                //Login to the server 
                clientSocket.BeginSendTo(byteData, 0, byteData.Length, 
                    SocketFlags.None, epServer, new AsyncCallback(OnSend), null); 
            } 
            catch (Exception ex) 
            { 
                MessageBox.Show(ex.Message, "SGSclient", 
                    MessageBoxButtons.OK, MessageBoxIcon.Error); 
            } 
        } 





// 现在写的JAVA代码

	public static void main(String []args){
		
		// 先启动WAR3,并建立主机
		DatagramPacket udpSendPacket;
		// 连接信息
		InetAddress destIp=null;
		DatagramSocket udpSender;
		try {
			udpSender=new DatagramSocket(6110);
			new Thread(new Listener(udpSender)).start();
			destIp=InetAddress.getLocalHost();
			System.out.println(destIp.getHostAddress());
			byte request[][]={
					{(byte)0xf7, 0x2f, 0x10, 0x00, 0x50, 0x58, 0x33, 0x57, 0x14, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00},
					{(byte) 0xf7, 0x2f, 0x10, 0x00, 0x50, 0x58, 0x33, 0x57, 0x14, 0x00, 0x00, 0x00,0x01, 0x00, 0x00, 0x00},
					{(byte) 0xf7, 0x2f, 0x10, 0x00, 0x50, 0x58, 0x33, 0x57, 0x14, 0x00, 0x00, 0x00,0x02, 0x00, 0x00, 0x00},
					{(byte) 0xf7, 0x2f, 0x10, 0x00, 0x50, 0x58, 0x33, 0x57, 0x14, 0x00, 0x00, 0x00,0x03, 0x00, 0x00, 0x00},
					{(byte) 0xf7, 0x2f, 0x10, 0x00, 0x50, 0x58, 0x33, 0x57, 0x14, 0x00, 0x00, 0x00,0x04, 0x00, 0x00, 0x00},
					{(byte) 0xf7, 0x2f, 0x10, 0x00, 0x50, 0x58, 0x33, 0x57, 0x14, 0x00, 0x00, 0x00,0x05, 0x00, 0x00, 0x00},
					{(byte) 0xf7, 0x2f, 0x10, 0x00, 0x50, 0x58, 0x33, 0x57, 0x14, 0x00, 0x00, 0x00,0x06, 0x00, 0x00, 0x00},
					{(byte) 0xf7, 0x2f, 0x10, 0x00, 0x50, 0x58, 0x33, 0x57, 0x14, 0x00, 0x00, 0x00,0x07, 0x00, 0x00, 0x00},
					{(byte) 0xf7, 0x2f, 0x10, 0x00, 0x50, 0x58, 0x33, 0x57, 0x14, 0x00, 0x00, 0x00,0x08, 0x00, 0x00, 0x00},
					{(byte) 0xf7, 0x2f, 0x10, 0x00, 0x50, 0x58, 0x33, 0x57, 0x14, 0x00, 0x00, 0x00,0x09, 0x00, 0x00, 0x00}};
			//byte test[]={(byte)0xf7, 0x2f, 0x10, 0x00, 0x50, 0x58, 0x33, 0x57, 0x14, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00};
			for(int i=0;i<request.length;i++){
			
			udpSendPacket=new DatagramPacket(request[i],request[i].length,destIp,6112);
			
			udpSender.send(udpSendPacket);
			}
			
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	
	}

 

 

附录:
WAR3 UDP 搜索主机9条UDP包如下:
F7 2F 10 00 50 58 33 57  14 00 00 00 00 00 00 00
F7 2F 10 00 50 58 33 57  14 00 00 00 01 00 00 00
F7 2F 10 00 50 58 33 57  14 00 00 00 02 00 00 00
F7 2F 10 00 50 58 33 57  14 00 00 00 03 00 00 00
F7 2F 10 00 50 58 33 57  14 00 00 00 04 00 00 00
F7 2F 10 00 50 58 33 57  14 00 00 00 05 00 00 00
F7 2F 10 00 50 58 33 57  14 00 00 00 06 00 00 00
F7 2F 10 00 50 58 33 57  14 00 00 00 07 00 00 00
F7 2F 10 00 50 58 33 57  14 00 00 00 08 00 00 00
F7 2F 10 00 50 58 33 57  14 00 00 00 09 00 00 00


返回的UDP包内容如下:
[2008-5-12 17:54:11:046]
00000000  F7 30 7C 00 50 58 33 57  14 00 00 00 01 00 00 00   .0|.PX3W ........
00000010  C2 75 5E 00 E5 BD 93 E5  9C B0 E5 B1 80 E5 9F 9F   .u^..... ........
00000020  E7 BD 91 E5 86 85 E7 9A  84 E6 B8 B8 E6 88 8F 20   ........ .......  
00000030  28 73 61 00 00 01 03 49  07 01 01 69 01 E9 69 01   (sa....I ...i..i.
00000040  9D 65 63 A7 4D 8B 61 71  73 5D 29 35 29 45 55 75   .ec.M.aq s])5)EUu
00000050  73 75 6D 65 53 6F 6F 63  6B 2F 77 33 79 3D 01 73   sumeSooc k/w3y=.s
00000060  61 61 61 01 01 00 04 00  00 00 09 00 00 00 01 00   aaa..... ........
00000070  00 00 04 00 00 00 6B 08  00 00 E0 17               ......k. ....

lancraft作者的原文:
    "We basically emulated the LAN function to work
over the internet. It was a hard hack to write
because Blizzard Entertainment implemented a few
protections.
One of them was the port protection.
They wouldn't allow us to take control over the UDP
LAN port. If we did take it, Warcraft III would refuse
to go into LAN mode. We bypassed it by faking the
"Lan tag".

The lan tag is:
F7 32 10 00 01 00 00 00 01 00 00 00 02 00 00 00 .2..............
A sample info request from client:
F7 2F 10 00 33 52 41 57 00 00 00 00 00 00 00 00
Response:
F7 30 6D 00 33 52 41 57 00 00 00 00 01 00 00 00 .0m.3RAW........
49 E1 7F 09 43 6F 6F 6C 65 73 74 27 73 20 47 61 I...Coolest's Ga
6D 65 00 00 01 03 49 07 01 01 A1 01 D1 49 01 A7 me....I......I..
8D 2D 6D 4D 8B 61 71 73 5D 29 33 29 AD 43 6F 6F .-mM.aqs])3).Coo
75 79 43 61 BB 79 2F 77 33 6D 01 43 37 6F 6F 6D uyCa.y/w3m.C7oom
65 73 75 01 01 01 00 0C 00 00 00 09 00 00 00 01 esu.............
00 00 00 02 00 00 00 55 00 00 00 E0 17 .......U.....
Then we -21 from the end of the packet (that's the
correct CRC), and we copy that and add to
F7 32 10 00 01 00 00 00 01 00 00 00 0C 00 00 00
and BOOM, it works."

网上有人已经翻译过了,大概的意思就是有个CRC验证。 基本上好象是根据主机建立游戏的次数来决定的。
后来抓了详细的包后发现lancraft确实是从6110发送了请求游戏包到6112,也确实返回了信息,但建立TCP连接的是另一个端口,那么这些TCP包是怎么传给WAR3进程的就不得而知了。 看来lancraft只能到此为止了,自己也无能为力了~

今天有幸能和VSZONE(正在做的一个游戏平台)的作者聊过之后,觉得自己功力不够,我还是网络盲,去补补底层通讯再来。

现在有2个难点:
1,进程间通讯,需要6110到6112(经过后来发现WAR3会自动连接"地图包"中指定IP地址+端口,TCP通讯无需我们处理)
2,重载send receive方法,加入指定的IP信息包,按照广播的方式发送出去!(这个是BattleLan需要做的,而魔兽搜索器却没有那么底层) 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值