1、基于HTTP(XML Web Services吧?)进行获取系统配置、更新程序、注册用户
2、基于HTTPS进行登录时密码验证
3、应用层协议是SIP协议,但不是标准的,估计是自创的?所有交互过程如发消息、短信通过SIP协议进行。
关于SIP,有巨多的RFC描述,飞信的SIP协议栈实现的是TCP、HTTP承载
1.TCP承载方式:连接服务器(目前是221.130.45.203)的8080端口,这时在客户端的“网络设置”中显示的是“TCP直接连接”,SIP信令直接就放在TCP的包中。
2.HTTP承载方式:连接服务器(目前是221.130.45.203)的80端口,采用POST方式,将信令包在POST请示中,这时在客户端的“网络设置”中显示的是“HTTP直接连接”
因为是TCP和HTTP承载,所以其包格式是非常清楚的,那么注意力就可以直接放到SIP协议或SIP信令上,详细的内容稍后再写。
总的来说,飞信协议是比较简单的,不对,准确地说法是比较规范和清晰,但协议本身是复杂的,另外:
1. 飞信的协议是明文,这一点如同其兄弟MSN,是不如QQ和RTX的,因此,通过飞信的交谈过程是可轻易截获的,通过很简单的工具,就可以截到同一网段上所 有人的交谈,估计会有人写Fetion Chat Sniffer的,就跟MSN一样,假如有一天Fetion有那么流行......要不我写一个?:)
2.协议效率比较低,我加了近200人,一次登录过程要传递的数据量居然超过了230K,我靠。
3.状态有问题,presence处理得不太好好象,我在线别人却看到我离线,真是奇怪,而且一会儿发一个presence一会儿发一个,讨厌啊。
以下分析均基于飞信的这一版本:Fetion 2006 beta 版本 2.1.0.0。
作协议分析时,一抓包,就发现飞信工作时连的是221.130.45.203这个服务器。那这个IP地址从哪来的呢?会变吗?飞信的客户端程序中并 没有配置服务器地址这一说。固定一个IP?不会吧,一面向全国的系统,不可能用一个IP地址。用一个固定域名解析出来的多IP地址中的一个吗?抓出它访问 DNS的包一看,它就只在开始时解析过一次域名:nav.fetion.com.cn,这个域名的IP是221.130.45.201——听说开发飞信的 人就是微软开发MSN的人,所以啥都跟MSN一样,你看那飞信的主界面元素,你能找一个位置和功能跟MSN不一样的吗?连解析域名这点都跟MSN一样,没 意思啊,印象中MSN也是一开始就解析一个地址,好象是Messenger.msn.com?如果想在局域网内封锁MSN,就把这个域名给指向 127.0.0.1,MSN就傻了。
既然只解析过nav.fetion.com.cn,那么221.130.45.203这个工作服务器(SIP的Proxy Server)地址,就应该是nav.fetion.com.cn返回来的了。确实是,但只是第一次登录时返回,并保存在了本地。后面再登录时,如果版本 不更新,是不会再返回这些系统配置信息的。所以,除第一次外,再抓包是看不到这些配置信息的。
本地配置文件并没放在Fetion的程序目录中,而是放到了%USERPROFILE%\Application\Fetion目录下。这个目录下有 configuration.dat和飞信的用户目录,每个飞信用户目录下还有configuration.dat、contacts.dat、 userinfo.dat这三个配置文件,看名字就知道是与用户相关的系统配置文件、好友列表文件、用户的个人信息文件。
这些文件全是XML格式的,所以可以用Notepad打开,不过,你打开后就会发现,这些文件的内容全被加密了,变态啊,这些文件有什么好加密的呢。
我们如何获得这里头的信息呢?
方法有两个:
一、我们让Fetion不要加密这些文件的内容,方法是:修改FetionFx.EXE文件。用ildasm,将FeionFX.EXE反汇编出 来,将其中的Imps.Client.Pc.PersistentManager.EncodeMode1和 Imps.Client.Pc.PersistentManager.DecodeMode1这两个函数改掉,将这两个函数体改成以下内容:
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
即,立即将参数返回。然后再用ilasm工具重新汇编生成FetionFX.EXE文件,覆盖掉以前那个,然后,再运行飞信,所有配置文件就不会再加密了。
二、构造一个请求,给nav.fetion.com.cn,让它返回。请求的内容很简单,抓一下包就会知道,取系统配置的请求过程是:
xxx.xxx.xxx.xxx:xxxx >>>>>>>> 221.130.45.201:80
POST /nav/getsystemconfig.aspx HTTP/1.1
User-Agent: IIC2.0/PC 2.1.0.0
Host: nav.fetion.com.cn
Content-Length: 233
Connection: Keep-Alive
--------------------------------------
xxx.xxx.xxx.xxx:xxxx <<<<<<<< 221.130.45.201:80
HTTP/1.1 100 Continue
--------------------------------------
xxx.xxx.xxx.xxx:xxxx >>>>>>>> 221.130.45.201:80
<config><user mobile-no="139xxxxxxxx" /><client type="PC" version="2.1.0.0" platform="W5.1" /><servers version="12" /><service-no version="1" /><parameters version="4" /><hints version="4" /><http-applications version="5" /></config>
将以上内容中的从servers version开始的version全置为"0",服务器就会返回配置信息。注意,配置信息全是UTF-8编码的。用nc就可构造一个http请求发过去,服务器立马就返回了。
推荐用方法一,因为这样可以看和修改所有配置信息,而方法二仅有系统配置信息。
与我们关注的服务器地址相关的信息在飞信用户目录下的configuration.dat中,一看就明白是啥:
....
<sipc-proxy>221.130.45.203:8080</sipc-proxy> 这就是我们关心的TCP直接连接时的服务器地址
<http-tunnel>HTTP://221.130.45.203/ht/sd.aspx</http-tunnel> HTTP直接连接时的入口地址
<get-pic-code>HTTP://221.130.45.201/nav/GetPicCode.aspx</get-pic-code> 注册时,取验证代码图片的URL
<get-system-status>HTTP://221.130.45.201/nav/GetSystemStatus.aspx</get-system-status> 取系统状态啦
....
这个配置信息放到飞信用户目录下是有原因的,就象SIP协议支持的,登录的服务器是可以分用户群的,不同的用户可以登录不同的Proxy Server,每个飞信用户(手机)可以分别登录到本省的Proxy Server,就如同现在的手机和电话网络一样。
其实这些配置内容没什么啊,为什么要加密呢?而且随便构造一个http请求,就可以获得这些内容的。 最变态的是通过飞信的交谈内容不加密不变换,却把无关紧要配置文件加密了。
另外,用户的密码就保存在Application Data\Fetion目录下的Configuration.dat中,当然这个密码进行了变换,遗憾的是,在程序中是还原出了用户密码的,因此,用户密 码别人是可以轻易获得的。幸好丢了可以手机找回。但这仍然是个非常不安全的因素。
作者:nathan
飞信老是断线,这点互联网上很多用户都有提及。我待的地方就老断,一说是跟网络有关系,一说是飞信本身有问题。近一两天跟踪看了看,发现断得可真是恐怖,一天断20-30次的都有。可有一次在家通过ADSL上呢,好象又还好。难道是时间的关系? 但白天碰到的多次断线我感觉是服务器的问题,理由是通过Sniffer,我明确地看到了服务器端发过来的TCP RST的包,也就是说服务器对这个TCP连接做了CLOSE的操作。 让我们看看sniffer记录了什么,来看一次断线的记录(这是OmniPeek的PacketVisualizer Data):
..... 9451 12:46:48.661 > IP L= 40 TCP .A.... S= 4522 L= 0 10994=A W=64367 TCP Invalid Checksum 9452 12:46:51.181 << IP L= 119 TCP .AP... 4522=A L= 79 S= 10994 W=65402 9453 12:46:51.182 >> IP L= 115 TCP .AP... S= 4522 L= 75 11073=A W=64288 TCP Invalid Checksum 9454 12:46:51.343 < IP L= 40 TCP .A.... 4597=A L= 0 S= 11073 W=65327 9455 12:53:38.501 > IP L= 98 TCP .AP... S= 4597 L= 58 11073=A W=64288 TCP Invalid Checksum 9456 12:53:38.532 < IP L= 40 TCP ...R.. L= 0 S= 11073 W= 0 从记录中我们看到,12:53:38,客户机发了9455号包到服务器,而服务器回了一个RST包(9456号包),从TCP的序列号看,通信过程都是正常的,否则RST包的Sequence就不会是11073了。9455的包的内容是: R fetion.com.cn SIP-C/2.0
F: 565248767 I: 1 Q: 4 R 这是一个向SIP Proxy Server注册的SIP请求。我猜测是客户端有几分钟没收到服务器的任何消息(通常服务器在不停地给客户端发presence消息),客户端就向服务器 发起一个注册请求,这时服务器应该将所有用户列表向飞信的客户端返回,然而,服务器却回了一个字:滚!;) 然后,飞信就痛苦地开始了重新登录过程,然后你的好友就看到你又缓缓地从他屏幕的右下角慢慢地爬了上来,冤啊。
一个半天可以记录到10多次这样的断线,每次均是以如此方式结束:客户端发一个请求到服务器,服务器回以RST。是网络问题吗?我想应该不 是,TCP的交互过程是正常的,MSN也是同时用TCP连着的,它也不断。我认为是飞信服务器的用户状态机处理有问题,莫名其妙地把活动的用户给干掉 了。:)
飞信自己应该知道这种情况的啊,Fetion本身的日志文件中是这么记录的: ....
<Summary>通信层异常</Summary> <Detail>System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接。 .... 可怜的飞信。 |
等着在淘宝上淘来的升级部件邮寄的时侯还是回到飞信吧,以下分析仍基于Fetion 2006 beta 2.1.0.0。
飞信所使用的协议版本标记是"SIP-C/2.0",协议栈中标记的版权信息是"Copyright (c) 2004-2006 China Mobile Limited. All rights reserved.",(再次说明飞信开发了很久了嘛;))。抓协议包初看的印象是,它基于IETF(Internet Engineering Task Force)所制定的标准SIP协议作了一丁点调整。关于标准的SIP协议,请参见IETF或RFC3261以及其它一些对它进行扩展的RFC,内容实在 是太多了,不过如果有点基础的话,估计看个半小时的RFC就明白了个大概。另外,飞信照着微软做的,所以看微软的实时通信协议的说明也一样:Look。
一个SIP的请求消息的格式是:请求行+消息头+空行+消息体,请求行的格式是:SIP方法+空格+接受方uri+空格+SIP协议版本,如:
INVITE sip:bob@biloxi.com SIP/2.0
接下来是消息头部,消息头的格式跟http头格式一样,也是Field Name:Field Value的形式,如:
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds
Max-Forwards: 70
To: Bob <sip:bob@biloxi.com>
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710@pc33.atlanta.com
CSeq: 314159 INVITE
Contact: <sip:alice@pc33.atlanta.com>
Content-Type: application/sdp
Content-Length: 142
IETF SIP中对这些Header Field均有专门的定义,见RFC3261以及IETF的SIP草案文档。Fetion的SIP-C/2.0协议中用到的Header Field有:
Authorization 缩写为"A"
CallID "I"
Contact "M"
ContentEncoding "E"
ContentLength "L"
ContentType "C"
CSeq "Q"
Date "D"
EndPoints "EP"
Event "N"
Expires "X"
From "F"
MessageID "XI"
ReferredBy "RB"
ReferTo "RT"
Require "RQ"
RosterManager "RM"
Source "SO"
Supported "K"
To "T"
Unsupported "UK"
WWWAuthenticate "W"
以上这些头域很多在RFC并没有定义,只在IETF的协议草案中有定义,如Event。SIP消息头后,由一个空行分隔,接下来就是SIP的消息体。消息 体通过是用SDP协议描述的,见RFC2327,当然也有直接文本或XML表示的信息,消息体的格式按RFC中的定义,应由头部的Content- Type来决定,但飞信好象不是,具体是怎么定义,还没深入去研究,留待下次吧。
飞信所支持的SIP方法(SIP Method)有以下几种:
1. Ack方法。在Fetion的SIP-C/2.0中,缩写为"A",以下是一个Ack消息,会话(Session)发起方用以向SIP Proxy确认会话的开始:
A fetion.com.cn SIP-C/2.0
I: 16
Q: 1 A
T: sip:987654321@fetion.com.cn;p=1234
F: 123456789
其中:123456789是发起方的SIP地址,这个显然没按SIP标准来表达,只是用了一个飞信号码。sip:987654321@fetion.com.cn,这个是按标准表达的对方地址。
2.BENotify方法(Fetion缩写为"BN"),这不是个标准的SIP方法,既没在RFC中定义,也没出现在IETF的协议草案中,这是微软在其LCS中定义的:BENOTIFY ("best effort" notify)enhances server performance by eliminating the response requirement. Otherwise, a BENOTIFY request has the same behavior as NOTIFY. Applications that require NOTIFY support need to implement similar processing for BENOTIFY."(见MSDN)。就是个不需要回复的NOTIFY,微软扩展出这个方法是为了支持大量用户。以下是飞信的一个BENotify消息,表示用户987654321的在线状态的变化:
BN 123456789 SIP-C/2.0
Q: 13 BN
N: presence
X: xxxx
I: 9
L: xxx
<events><event type="PresenceChanged"><presence uri="sip:987654321@fetion.com.cn;p=xxxx"><basic value="100" device-这个utf8字符串的MD5字符串,即为response.
以上就是飞信的身分验证过程,我还没来得及写代码测试,应该就是这样子。另外,如果知道用户的URI,是否可以不用注册到SSIPortal?这个需要测试才知道,我看飞信中好象还对注册到SSIPortal的Session做了Keep Logon。
好啦,分析到现在我们可以做一个飞信的客户端了,哈,谁有兴趣? ;)