这篇文章是基于作者于2003年推出的一款叫“Windows信使终结者”的软件而写的,当时没有找到很好的资料(当然参考了很多辅助性的资料),于是自己试着解开信使之谜。
Windows 9X时代的信使消息
使用过Windows 9X系列操作系统的人都知道操作系统自带有一个WinPopup.exe的程序,它可以实现简单的局域网内的文字通信,这就是信使(Messenger)了。它的实现是通过Mailslot技术实现的,实现信使的mailslot名称为"messngr"。只要通过读写这个mailslot就可以实现接收与发送信使消息。消息的结构为:发送方名称+接收方名称+消息正文。字符串均以NULL结束。关于如何操作mailslot可以参考其它文献。
基于NT的Windows操作系统的信使服务
在Win9X下,信使是一个普通的应用程序,只有运行它才能够收发信使消息。基于NT的操作系统把信使做成了系统服务,服务名为"Messenger"。大概2003年的时候,信使服务还被一些人利用发送广告或散发反动言论,当你正在打游戏或看电影的时候,突然弹出一个信使服务的顶层对话框确实是一件很烦的事。不过现在已经很少看到信使的踪影了,大概是不是被网络运营商们给截掉了。不过信使服务还是有一定的用途的,在系统的服务管理器里面可以看到信使服务的描述为“发送和接收系统管理员或者“警报器”服务传递的消息。”,它可以被一些应用程序或一些管理员发送一些有用的信息。
好了,其它不多说了,讲讲它的原理吧。NT的信使服务使用了两种方式:Netbios数据报及Socket数据报,后者也就是UDP了。Netbios可能是被用于局域网的信使通信,而UDP可以在广域网中通信。当时我的第一个版本就是试图通过Netbios与对方建立连接并收发信使消息,但一直没有进展。后来就想直接使用UDP算了,因为它即可以收发局域网的信使消息,也可以收发广域网的。所以本文主要描述了如何使用UDP收发信使消息。
信使服务所使用的UDP端口为135端口。知道了端口,现在关键是在传送信使时所使用的上层协议。通过网络截包软件(我用的是Ethereal)可以发现,信使包被封装到了DCE/RPC包里(而通过Netbios的被封装到SMB包)。当时我对协议的分析还处于一种恐惧的状态,而且找了一些资料都没有把这个DCE/RPC包的结构给出来,于是借助Ethereal硬把它的各个字段给猜测出来,并最终实现了信使的收发,而且随之而来的也就可以在信使的收发上玩一些小把戏。下面就是当时我对网络数据包的分析结果,如果哪位直接有这个协议的官方文档,麻烦给个链接,免得这篇文章误导大家:
(由于技术原因,下面有很多空行,请跳过继续阅读)
字节 |
内容 |
描述 |
1 |
version |
版本 |
1 |
packet type |
Request为0,Response为2 |
1 |
flags1 |
好像为0x08 |
1 |
flags2 |
好像为0x00 |
1 |
Byte Order |
为1 |
1 |
Character |
0(ASCII) |
1 |
Floating-point |
0(IEEE) |
1 |
Serial High |
0x00 |
16 |
Object |
好像全0 |
16 |
Interface |
5a7b91f8-ff00-11d0-a9b2-00c04fb6e6fc |
16 |
Activity |
由发送方自动生成,响应方应取同样的 |
4 |
Server Boot Time |
开机时间 |
4 |
Interface Version |
好像是1 |
4 |
Sequece num |
0 |
2 |
opnum |
0 |
2 |
Interface Hint |
0xffff |
2 |
Activity Hint |
? |
2 |
Packet Length |
DCE/RPC包长度 |
2 |
Packet SN. |
DCE/RPC包序号 |
1 |
Auto proto |
0 |
1 |
Serial Low |
0x00 |
注意里面的Activity是唯一标识此次消息服务的,收到消息后要根据它发送响应包才能使发送方得到接收方已经收到的消息。
上面是DCE/RPC帧结构,信使消息数据就紧接在后面。下面解读信使消息数据结构。
信使信息帧:发送者名称+12字节未知数据+接收者名称+12字节未知数据+信使消息
响应帧:4字节的0
其中,发送者及接收者的名字都是以NULL结尾的字符串,而且是经4字节(包括最后的NULL)对齐的。12字节未知数据结构为:** ** 00 00 00 00 00 00 ** ** 00 00,**表示下一个数据块的长度,如下一个名称长度,信使信息长度等。
有了这些,已经足够写出与信使有关的各种应用了(当然最简单地在NT系统下发送信使消息可以使用NetMessageBufferSend API),如作者2003年写的“信使终结者”就是用来拦截和发送信使消息的。要拦截信使消息,可以先把信使服务关掉,然后自己在135端口监听,或使用rawsoket或截包库截包即可。要发送,也只要向对方的135UDP端口发送数据即可。由于是向接收方发送UDP数据包,因此你可以通过代理发送信使消息(信使终结者带的一个信使发送工具就可以),你甚至可以伪造底层的IP数据包让对方不知道发送方的真实地址。
前面说过,本文是在2003年的基础上写的,由于当时水平所限,可能有更好的方法或官方有这样的文档更清楚地阐明了其原理没有找到。而且现在把它写出来,很多理解都没有当初那么深了,有什么问题请大家指正。
|