[ 转载]
联众升级协议分析
云网(jimzj@21cn.com)
记得刚到大学时,第一件和大家一起玩的就是打牌,相信很多人都会有这个经历;我也是在那时候学会升级(拖拉机)的。
大二时曾经疯狂玩过,所以对升级一直都很情有独衷;但工作后,一方面找不到人,另一方面就算找到人了也不能像以前一样通
宵的去玩。还好,一次看到别人在网上玩联众的升级,呵呵,从此后不怕找不到人了,工作之余可以随时和别人玩一下,过一把
隐;说了这么多,还没有转入正题,不意思。
对于做外挂,以前没有做过,因为没有很多时间,所以也没有在网上去详细的找相关的网站,如果那一位有很多这方面的资
料的话,不防贴出来与大家共享一下。
一、对于外挂,首先我们谈一下数据的获取:
1、对于动作游戏类:可以通过API发命令给窗口或API控制鼠标、键盘等,使游戏里的人物进行流动或者攻击,这个是
对于本地游戏而言的,网上有很多这方面的介绍,在这里就不再写了。
2、截获消息:通过hook技术,获到与游戏相关的数据,之后就看你自己怎么处理这些数据了 :)。
3、拦截socket包:要替换winSock.dll或者winsock32.dll,我们写的替换函数要和原来的函数一致才行,就是说它的函数输出
什么样的,我们也要输出什么样子的函数,而且参数,参数顺序都要一样才行,然后在我们的函数里面调用真正的winSock32.dll里面
的函数就可以了。当游戏进行的时候它会调用我们的动态库,然后从我们的动态库中处理完毕后才跳转到真正动态库的函数地址,
这样我们就可以在里面处理自己的数据了;不过这程方法要自已重新去写如下面的一个例子:
void * pSocketFun = GetProcAddress( i, "WSAStartup" );
WSAStartup1 = (int(_stdcall *)( WORD, LPWSADATA ))pSocketFun;
winSock32.dll里有有这么多的函数,要自己一个一个的替换,有不是很累,这个动态库还是公用的,万一那一个地方写错了,不
是会出很大问题,所以还是觉得这个方法不是很好。
4、直接监听网络数据包:这个方法就和sniffer和comview所用的技术差不多了,不过我们并不要直接去监听到网络层或以下
的数据包,只要到IP层的就可以了;
利用 Raw Socket: 原始套接字
它来发送和接收 IP 层以上的原始数据包,如 ICMP、TCP、UDP...等,一般的游戏数据量不大的话多采用TCP协议传输数据,
如联众游戏的升级就是这样,但如泡泡堂采用的就是UDP发送了,数据量很大。关于这种方法介绍大家看一篇文章,会有很大的帮
助,同时要感谢作者(shadowstar)提供了这么好的文章,我也从中得不少帮助(~_~)。
http://web.nyist.net/~shadowstar/essay/security/sniffer1.html
下面是我做的一段数据接收和分离出来的IP包的程序:
...........
try
{
nIpRevLen = recv( pCtlSocket->m_socket, cIpRevBuff, MAX_COMMAND_SIZE - 24, 0 ) ;
}
catch( ... )
{
}
if( nIpRevLen == SOCKET_ERROR ) continue ;
IP * p_ip = ( IP * )cIpRevBuff ;
TCP * p_tcp = ( TCP * )( cIpRevBuff + IP_HdrLen( p_ip )) ;
if( p_ip->DstAddr != pCtlSocket->addr_in.sin_addr.S_un.S_addr ) continue ; //这句和下一句过滤其它不要的包
if( p_ip->Protocol != IPPROTO_TCP ) continue ;
int nSrcPort = ntohs( p_tcp->SrcPort ) ;
if( nSrcPort != PORT_DODZ ) continue ;
char * pPackConten = ( char * )p_tcp + TCP_HdrLen( p_tcp ) ; //这里就是得到了包的内容了
nPackLen = ntohs( p_ip->TotalLen ) - IP_HdrLen( p_ip ) - TCP_HdrLen( p_tcp ) ; //这个是包的长度
...........
二、数据的协议分析
下面来分析一下联众升级的协议,本来自己接收到数据了,就可以把数据写下来,不过还是用别人的现成工具会更好一点,
在这里我用的是comview3.3来接收数据的,这个工具还是很好用的,建议大家可以下载一个去用一下试一试;下面是一些接收到的数据:
0x0000 05 02 00 00 22 00 00 00-00 20 00 00 C1 00 00 00 ....".... ..?..
0x0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0x0020 06 00 00 00 67 67 2E 68-74 6D 05 02 00 00 23 00 ....gg.htm....#.
0x0030 00 00 01 20 00 00 46 00-00 00 00 00 00 00 00 00 ... ..F.........
0x0040 00 00 00 00 00 00 00 00-00 00 07 00 00 00 67 67 ..............gg
0x0050 2E 68 74 6D 6C .html
像这样的数据,相信让谁都会搞不清楚是什么东西,不过不怀疑有一些天才可以异想天开,不过去从原始数据来分析别人的协
议确实要一些灵感的,:)。好像是在为自己吹嘘,不好意思了..... 不过呢,协议的分析要与实际的操作结合起来,如果你不会玩
升级,很难想像你会很容易分析出来别人的协议来。还好我自己在这方面还不算,还是升级中是一个小官员类的分数据了,呵呵。
我们可以想一下游戏一整个流程,登录、进入游戏室、找到玩家、发牌,扣底、出牌和结束。有了这样一个流程在脑子中可以帮
助想像每一个数据的信息。
我用的是很差的方法去让这个过程和接收到的数据合在一起分析的:
1、启动comview或其它的接收数据包的工具,设置好过滤条件,只接收IP/TCP包,目标的IP是自己的机器,如果不设置这些条件
呵呵,那网络是的大量数据包就全被你吃下来了,到时要从几万个包中找出你所要的数据,太难了吧...
2、接着就启动联众的游戏,进入升级(为了分析这些协议,我总被人家说慢得像乌龟,还失去了很多分:( ),这时你就可要注
意了收集数据了,记下当前打会,什么时候叫牌,反牌,得分,出的牌,很从数据都要记录下来,同时还要想着如何出牌才能赢,要
不真有些对不起和你一起玩的对家了。
3、有了数据一实际上过程的记录,分析协议就有了着手的地方了,我们先看下面的一段数据:
0x0000 00 02 00 80 F0 00 00 00-01 00 00 00 04 00 02 00 ...€?..........
0x0010 00 00 00 00 63 61 6F 77-65 69 5F 30 30 31 30 00 ....ddddd_0010.
0x0020 11 20 00 00 18 00 00 00-67 79 75 67 68 00 00 00 . ......dddd...
从这里可以看到,ddddd_0010(原始数据不是这个,我修改了)与一起的玩的的名称是不是一样呢,如果是一样的就好了,这个可
是服务器返回来的与你一起玩的玩家信息;
如果你做过SCOKET方面的编程,你应该可以知道一个包的大体结构,下面我来说一下:
应用包头标志
包序列号
整个包的长度
CRC校验(或累加和校验)
命令字
数据体长度
数据体
网络上的数据并不是整像我们想像的那样,发一个包出去,就会在对方接下整个包,很多时候会分几次才能接收下来整个完整的包
。我们再看一个包:
0x0000 10 20 00 80 24 00 00 00-D9 54 DF 77 01 00 00 00 . .€$...賂遷....
0x0010 01 00 00 00 00 00 00 00-03 00 00 00 00 00 00 00 ................
0x0020 03 00 00 00 01 00 00 00-01 00 00 00 17 71 40 00 .............q@.
这两个包有什么相同之处,就是包头开始的8个字节,是不是可以看出来一个包的整体结构了,注意网络数据格式转换为机器数据格
式的话要反转一下数据MSDN上可以找到类似这样的函数ntohl、ntohs、 htonl和htons,所以我们在看数据时也要把字倒转一下...
如果你了解的话,和般的80是作为一个回应包的标识,这样我们就可以看到了两个命令字了:
80 00 00 02 十六进制表示:0x80000002
80 00 20 10 0x80002010
这两个命令都不同,可以看到,协议上并没有统计的应用包头标志,直接从命令字开始了。有了上面的概念,接下来的自然就是
长度过,因为第一个包没有完整,我们看第二个包,一般长度用两个字节就可以了,但会有用四个字节的,也就是一个int类型的值,第二
个包的长度不难看到就是0x24,假设长度使用四个字节,那么内容就应该是D9 54 .... 71 40 00,0x24 = 36,我们数据一下,刚好就是
这个长度,呵呵,到现在你和我一样,了解一包的结构形式了,我们正在一步往成功的方向去了...
到了这一步,大家也差不多可以动手自己去分析一下协议了,因为一些其它的因为,我在这里就不再往下分析各个命令字的具体作用
了,不过可以告诉大家0x80000002是用户登录后服务器返回来的所有玩家信息,注意一下,我们在注册联众用户时,最长的登录名称不能
超过19个字节,所以在包就应加上一个结束符,就是20个字节了。
上面的分析只是一个引子,由本人水平有限,有什么错误的地方请大家指出,共同学习。
另外我做的一个联众升级助理V1.0在www.csdn.net中软件(游戏类,其它类型)上发布了,大家可以下载使用,是完全免费的。因为时间有限,没有做完整
的测试,如果发现在什么bug,可以用邮件方式通知我,谢谢!