目录:
☆ DCE/MS RPC架构简介
☆ BIND操作简介
1) "BIND Over TCP"简介
2) "BIND Over Transaction"简介
3) "BIND Over Write AndX"简介
4) "BIND Over ..."扩展
5) SMB_COM_TRANSACTION2与SMB_COM_NT_TRANSACTION
☆ PFC_OBJECT_UUID标志位
☆ MS02-045/Q326830
☆ WildPackets Free Filters for Detecting Malicious Worms/Viruses
☆ /pipe/epmapper
☆ 135/UDP相关讨论
1) XP SP1的msgsvc.dll(5.1.2600.1309)
2) 中文2000的msgsvc.dll(5.0.2195.4874)
3) 通过135/UDP访问MGMT
4) 通过135/UDP访问EPM
☆ Windows网络服务最小化
☆ MS05-040/KB893756
☆ DriverStudio Remote Control服务
☆ 参考资源
--------------------------------------------------------------------------
☆ DCE/MS RPC架构简介
本节属于科普性质,文字描述不那么规范,将就着看吧。
一个RPC服务可以绑定多种协议序列,也可以只绑定某一种协议序列,这是实现相关
的,没有定式。某接口绑定N种协议序列,就意味着有N条途径可以访问该接口。可以
用135dump.exe、ifids.exe等工具查询这类信息。
+-- ncacn_ip_tcp(动态TCP口)
|
DCE/MS RPC--+-- ncadg_ip_udp(动态UDP口)
|
+-- ncacn_np(固定的139、445/TCP口)
|
+-- ... ...(其它协议序列)
可以将DCE/MS RPC看作一层,这一层可以在不同的协议序列上跑,比如上面列出的三
种。实际上还有其它协议序列可用,但不常见,这里就不罗嗦了。
ncacn_ip_tcp与ncadg_ip_udp用到了动态端口,它们会向EPM接口注册所用动态端口,
而客户端可以向EPM接口查询服务端注册过的信息。如果客户端有其它手段提前知道
服务端所用动态端口,就可以省去向EPM接口查询的操作。
一般碰上的是版本5的RPC,ncacn_ip_tcp、ncacn_np等用的就是V5。而ncadg_ip_udp
用的则是版本4的RPC。V4与V5的差别很大。你在现实环境中很难观察到V4。历史上某
些版本的net send命令会用到V4,MS02-045/Q326830补丁取消了Messenger服务绑定
的ncadg_ip_udp协议序列,现在更难在现实环境中观察到V4了。
EPM接口本身是一个RPC服务,同样有多种协议序列可用来访问这个接口。
ncacn_np协议序列用到了SMB协议,DCE/MS RPC层位于SMB层上,SMB层再位于TCP层上。
有些文字会介绍说139/TCP口的通信是SMB层位于NBT层上,NBT层位于TCP层上。这一
点对于旁路协议分析来讲,没有必要区分,可以将NBT层那四字节划入SMB层。再简单
点说,旁路协议分析时,可以认为139、445/TCP仅仅是端口不同,没有其它区别。
SMB协议可以由多种命令来承载DCE/MS RPC层数据,同样是139、445/TCP上的通信,
因不同的SMB命令而导致不同的SMB层解码。
无论用哪种协议序列,用哪种SMB命令,访问一个RPC接口的典型步骤是:
a) Bind
b) Request
不同的协议序列、不同SMB命令就对应不同的Bind Over ...、Request Over ...。
分层解码后到了DCE/MS RPC这一层,就都一样了。
做DCE/MS RPC协议分析时,首先就应该关注Bind操作。
--------- --------- -------------- -------
动态TCP口 动态UDP口 139、445/TCP口 ... ...
----+---- ----+---- --------+----- ----+--
| | | |
| | ----+---- ----+--
| | SMB层解码 ... ...
| | ----+---- ----+--
| | | |
+-----------+--------+------+-----------+
|
-----+----------
DCE/MS RPC层解码
-----+----------
|
----------+--------------
RPC层各命令相关的首部解码
----------+--------------
|
+--------+--------+-----+-+------------+---------+--------+
| | | | | | |
-+-- --+-- ---+--- ---+---- ----+--- --+-- ---+---
Bind Fault Request Response Bind_ack AUTH3 ... ...
---- ----- ---+--- ---+---- -------- ----- -------
| |
+-----+-+
|
+-------+-+-----+-------+
| | | |
---+--- ---+--- ---+--- ---+---
Opnum 0 Opnum 1 ... ... Opnum N
---+--- ---+--- ---+--- ---+---
| | | |
+-------+---+---+-------+
|
-----+-------
stub data解码
-------------
在用Ethereal研究DCE/MS RPC协议时,经常看到所谓的stub data,这实际是RPC解码
关键所在。对于这些stub data的解码是IDL文件相关的,不同的IDL文件对应不同的
stub data解码。不同的RPC服务都有着各自不同的IDL文件,因此对stub data的解码
只能是具体问题具体分析,没有捷径可走。
☆ BIND操作简介
1) "BIND Over TCP"简介
一个最简单、常见的Bind_ack报文的例子如下(SMB_37_0.cap):
--------------------------------------------------------------------------
Transmission Control Protocol, Src Port: 4166 (4166), Dst Port: 135 (135), Len: 72
DCE RPC Bind, Fragment: Single, FragLen: 72, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind (11)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 72
Auth Length: 0
Call ID: 1
Max Xmit Frag: 5840
Max Recv Frag: 5840
Assoc Group: 0x00000000
Num Ctx Items: 1
Context ID: 0
Num Trans Items: 1
Interface UUID: e1af8308-5d1f-11c9-91a4-08002b14a0fa
Interface Ver: 3
Interface Ver Minor: 0
Transfer Syntax: 8a885d04-1ceb-11c9-9fe8-08002b104860
Syntax ver: 2
0030 05 00 0b 03 10 00 00 00 48 00 ........H.
0040 00 00 01 00 00 00 d0 16 d0 16 00 00 00 00 01 00 ................
0050 00 00 00 00 01 00 08 83 af e1 1f 5d c9 11 91 a4 ...........]....
0060 08 00 2b 14 a0 fa 03 00 00 00 04 5d 88 8a eb 1c ..+........]....
0070 c9 11 9f e8 08 00 2b 10 48 60 02 00 00 00 ......+.H`....
Transmission Control Protocol, Src Port: 135 (135), Dst Port: 4166 (4166), Len: 60
DCE RPC Bind_ack, Fragment: Single, FragLen: 60, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind_ack (12)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 60
Auth Length: 0
Call ID: 1
Max Xmit Frag: 5840
Max Recv Frag: 5840
Assoc Group: 0x00012bee
Scndry Addr len: 4
Scndry Addr: 135
Num results: 1
Ack result: Acceptance (0)
Transfer Syntax: 8a885d04-1ceb-11c9-9fe8-08002b104860
Syntax ver: 2
0030 05 00 0c 03 10 00 00 00 3c 00 ........<.
0040 00 00 01 00 00 00 d0 16 d0 16 ee 2b 01 00 04 00 ...........+....
0050 31 33 35 00 00 00 01 00 00 00 00 00 00 00 04 5d 135............]
0060 88 8a eb 1c c9 11 9f e8 08 00 2b 10 48 60 02 00 ..........+.H`..
0070 00 00 ..
--------------------------------------------------------------------------
试图绑定DCE/MS RPC Endpoint Mapper Interface UUID时引发上述报文。
Auth Length一般情况下为0,但并非总为0。关于这个字段,参看MSDN中如下函数:
RpcServerRegisterAuthInfo
RpcBindingInqAuthClient
RpcBindingSetAuthInfo
Auth Length为0的情况下,Bind(11)报文的RPC层大小固定为72。
Bind_ack(12)报文的RPC层大小变动较大,一是受Auth Length的影响,二是受Scndry
Addr的影响,Scndry Addr后面的Num results要求对齐在四字节边界上。当Scndry
Addr对应字符串表示的端口号时,Scndry Addr len最大等于6,即"65535"所占字节
数,包括结尾的NUL字符。由于Num results四字节对齐的缘故,"65535"不会比"135"
多占任何字节,因此当Scndry Addr对应字符串表示的端口号时,Auth Length为0的
情况下,Bind_ack(12)报文的RPC层大小固定为60。这种情形很常见,ncacn_ip_tcp
协议序列对应的BIND操作多半是这种情形,换句话说,BIND Over TCP多半是这种情
形。但是,ncacn_np协议序列对应的BIND操作就不是这种情形。
收到Bind_ack(12)报文并不意味着BIND操作成功,要检查Ack result字段:
0 Acceptance
2 Provider rejection
应该还有其它值,但那不重要。解析Bind_ack报文时,务必判断Ack result字段是否
等于Acceptance(0),此时意味着BIND操作成功。以前一直以为收到Bind_nak(13)报
文才意味着BIND操作失败,不想近日做实验时意外地发现结论错误。
一个解码陷阱源于Ack result在Scndry Addr之后。ncacn_ip_tcp协议序列下Ack
result在RPC层的偏移可以认为是固定的+0x024,ncacn_np协议序列下这个偏移就变
了。可移植的解决方案是无论哪种协议序列,先取Scndry Addr len,再考虑四字节
对齐的事,动态计算Ack result的偏移。这个方案不受Auth Length的影响,认证相
关的数据位于尾部。另一个方案是先获取Auth Length,并确保收到的是完整的非畸
型的Bind_ack报文,然后从尾部倒推偏移-Auth Length-0x018。这个方案并不比前一
个方案更有优势,看个人喜好了。为此修正了一批早期编写的代码。
下面是一个Provider rejection(2)的例子(SMB_37_1.cap):
--------------------------------------------------------------------------
Transmission Control Protocol, Src Port: 60367 (60367), Dst Port: 135 (135), Len: 72
DCE RPC Bind, Fragment: Single, FragLen: 72, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind (11)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 72
Auth Length: 0
Call ID: 1
Max Xmit Frag: 4280
Max Recv Frag: 4280
Assoc Group: 0x00000000
Num Ctx Items: 1
Context ID: 0
Num Trans Items: 1
Interface UUID: ffffffff-ffff-ffff-ffff-ffffffffffff
Interface Ver: 0
Interface Ver Minor: 0
Transfer Syntax: 8a885d04-1ceb-11c9-9fe8-08002b104860
Syntax ver: 2
0040 05 00 0b 03 10 00 00 00 48 00 00 00 01 00 ........H.....
0050 00 00 b8 10 b8 10 00 00 00 00 01 00 00 00 00 00 ................
0060 01 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
0070 ff ff 00 00 00 00 04 5d 88 8a eb 1c c9 11 9f e8 .......]........
0080 08 00 2b 10 48 60 02 00 00 00 ..+.H`....
Transmission Control Protocol, Src Port: 135 (135), Dst Port: 60367 (60367), Len: 60
DCE RPC Bind_ack, Fragment: Single, FragLen: 60, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind_ack (12)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 60
Auth Length: 0
Call ID: 1
Max Xmit Frag: 4280
Max Recv Frag: 4280
Assoc Group: 0x00012bf6
Scndry Addr len: 4
Scndry Addr: 135
Num results: 1
Ack result: Provider rejection (2)
Ack reason: Abstract syntax not supported (1)
Transfer Syntax: 00000000-0000-0000-0000-000000000000
Syntax ver: 0
0040 05 00 0c 03 10 00 00 00 3c 00 00 00 01 00 ........<.....
0050 00 00 b8 10 b8 10 f6 2b 01 00 04 00 31 33 35 00 .......+....135.
0060 00 00 01 00 00 00 02 00 01 00 00 00 00 00 00 00 ................
0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..............
--------------------------------------------------------------------------
此次Ack result等于Provider rejection(2)时,Ack reason字段开始有意义,另一
明显变化是Transfer Syntax字段。
Bind_ack(12)报文的RPC层大小与协议序列有关,但与Ack result、Ack reason字段
无关,这是两个短整型,始终占去4字节。因此上述Bind_ack(12)报文的RPC层大小仍
等于60。
向135/TCP发送Bind报文试图绑定不存在的接口UUID,就引发出如上Bind_ack报文。
这是一次实验意外出错后的结果,现实环境中这样的报文相当罕见,折腾DCE/MS RPC
这么久,还是第一次看到,为此修正了一批早期编写的代码。
2) "BIND Over Transaction"简介
当Bind(11)由SMB命令Trans(0x25)承载时,即"BIND Over Transaction"。
这是枚举Windows 2000共享时抓取的报文(SMB_37_2.cap):
--------------------------------------------------------------------------
Transmission Control Protocol, Src Port: 52635 (52635), Dst Port: 139 (139), Len: 160
NetBIOS Session Service
Message Type: Session message
Flags: 0x00
.... ...0 = Add 0 to length
Length: 156
SMB (Server Message Block Protocol)
SMB Header
Server Component: SMB
Response in: 2
SMB Command: Trans (0x25)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x08
0... .... = Request/Response: Message is a request to the server
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc001
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only
...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs
.... 0... .... .... = Extended Security Negotiation: Extended security negotiation is not supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .0.. = Security Signatures: Security signatures are not supported
.... .... .... ..0. = Extended Attributes: Extended attributes are not supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Process ID High: 0
Signature: 0000000000000000
Reserved: 0000
Tree ID: 2048
Process ID: 23643
User ID: 2048
Multiplex ID: 63744
Trans Request (0x25)
Word Count (WCT): 16
Total Parameter Count: 0
Total Data Count: 72
Max Parameter Count: 0
Max Data Count: 1024
Max Setup Count: 0
Reserved: 00
Flags: 0x0000
.... .... .... ..0. = One Way Transaction: Two way transaction
.... .... .... ...0 = Disconnect TID: Do NOT disconnect TID
Timeout: Return immediately (0)
Reserved: 0000
Parameter Count: 0
Parameter Offset: 84
Data Count: 72
Data Offset: 84
Setup Count: 2
Reserved: 00
Byte Count (BCC): 89
Transaction Name: /PIPE/
Padding: 0000
SMB Pipe Protocol
Function: TransactNmPipe (0x0026)
FID: 0x4000
DCE RPC Bind, Fragment: Single, FragLen: 72, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind (11)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 72
Auth Length: 0
Call ID: 1
Max Xmit Frag: 4280
Max Recv Frag: 4280
Assoc Group: 0x00000000
Num Ctx Items: 1
Context ID: 0
Num Trans Items: 1
Interface UUID: 4b324fc8-1670-01d3-1278-5a47bf6ee188
Interface Ver: 3
Interface Ver Minor: 0
Transfer Syntax: 8a885d04-1ceb-11c9-9fe8-08002b104860
Syntax ver: 2
0040 00 00 00 9c ff 53 4d 42 25 00 00 00 00 08 .....SMB%.....
0050 01 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
0060 5b 5c 00 08 00 f9 10 00 00 48 00 00 00 00 04 00 [/.......H......
0070 00 00 00 00 00 00 00 00 00 00 00 54 00 48 00 54 ...........T.H.T
0080 00 02 00 26 00 00 40 59 00 00 5c 00 50 00 49 00 ...&..@Y../.P.I.
0090 50 00 45 00 5c 00 00 00 00 00 05 00 0b 03 10 00 P.E./...........
00a0 00 00 48 00 00 00 01 00 00 00 b8 10 b8 10 00 00 ..H.............
00b0 00 00 01 00 00 00 00 00 01 00 c8 4f 32 4b 70 16 ...........O2Kp.
00c0 d3 01 12 78 5a 47 bf 6e e1 88 03 00 00 00 04 5d ...xZG.n.......]
00d0 88 8a eb 1c c9 11 9f e8 08 00 2b 10 48 60 02 00 ..........+.H`..
00e0 00 00 ..
--------------------------------------------------------------------------
SMB Command字段表明此次RPC通信由Transaction承载。RPC层的Bind(11)报文仍占72
字节。本例与"BIND Over Tcp"的情形相比,一是RPC层的承载者由TCP变成了SMB,二
是接口UUID变了,除此之外,并无区别。微软很好地实现了协议分层处理。
Bind(11)报文对于DCE/MS RPC协议分析来讲,至关重要,直接体现在暴露了接口UUID。
在Google中搜索"4b324fc8-1670-01d3-1278-5a47bf6ee188",重点推荐:
Well-known DCE RPC named pipes endpoints
[url]http://www.hsc.fr/ressources/articles/win_net_srv/ch04s05s03.html[/url]
这里有一张表"Named pipes used by DCE RPC servers",列举了部分接口UUID对应
的服务或进程,协议分析爱好者可以参看。
接口UUID即上述显示中的Interface UUID字段,不要与Transfer Syntax字段混淆了。
分析DCE/MS RPC通信时,没有接口UUID寸步难行。后续的Request(0)报文中的Opnum
是接口UUID相关的,A接口的0号调用与B接口的0号调用显然是两个独立的调用。有时
会碰上求助者提供了CAP文件,居然只有Request(0)报文,没有Bind(11)报文,分析
者将很难进行有效分析。
那么怎么针对接口UUID设置过滤规则呢?先要搞清楚层次关系,我们可能碰上不同的
承载,就目前举例来讲,已经出现了TCP、SMB两种。
"BIND Over Tcp"对应协议序列ncacn_ip_tcp,目标端口理论上可以是任意TCP端口。
在设置端口过滤时,只能是具体问题具体分析,后面会单独讲这个问题。抛开端口不
谈,Interface UUID字段在TCP数据区(注意我的用词)的偏移是固定的+0x020,由于
UUID大小固定,后面版本字段在TCP数据区的偏移也是固定的。真正设置过滤规则时,
还可以对Version、Packet type、Transfer Syntax字段进行过滤,减少误报。
前面提到了"在TCP数据区的偏移",意味着我假设手头的工具可以正确定位TCP数据区,
即剥掉IP首部、TCP首部之后的TCP数据区。你不能简单地从IP首部+40,要考虑可能
出现的IP选项、TCP选项。从协议分层的理念来讲,定位在TCP数据区的偏移也是合理
的。
"BIND Over Transaction"对应协议序列ncacn_np,目标端口理论上只有两个,139与
445/TCP,很容易设置端口过滤。一般必须同时观察这两个端口上的通信过程。A时刻
抓取的报文可能用了139/TCP,B时刻抓取的报文可能用了445/TCP。这不是RPC层的问
题,而是SMB层的问题。SMB层的实现最早只用到139/TCP,后来增加了445/TCP,微软
保持向后兼容性,宏观上139与445是竞争关系。抛开端口不谈,Interface UUID字段
在RPC层(注意我的用词)的偏移是固定的+0x020,由于UUID大小固定,后面版本字段
在RPC层的偏移也是固定的。真正设置过滤规则时,还可以对Version、Packet type、
Transfer Syntax字段进行过滤,减少误报。
前面提到了"在RPC层的偏移",意味着我假设手头的工具可以正确定位RPC层。剥掉IP
首部、TCP首部可能好理解也好操作,大家都熟了,剥掉SMB层可能不太熟。看前面显
示的Data Offset字段,字段值加上4即RPC层在TCP数据区的偏移,SMB层就这样简单
地被剥掉了。别高兴得太早,Data Offset字段本身在TCP数据区的偏移是随SMB命令
而改变的,就Trans(0x25)而言,偏移是61。有人要问了,我先过滤出Trans(0x25),
再直接假设RPC层在TCP数据区的偏移是+0x058,不就得了。嘿,这是有问题的。注意
看上面显示中的Padding字段,该字段的长度与值不固定!可能你抓了1000次包,都
没看到Padding字段的长度有变化,但第1001次你敢保证仍不变吗?事实上我最初写
代码时就是这样假设的,结果后来针对不同OS测试时意外出错,调试了半天才得到现
在的结论。
写程序时可以精确过滤并定位各个偏移,用协议分析工具时就得变通一下了。先过滤
先过滤出Trans(0x25),再直接假设RPC层在TCP数据区的偏移是+0x058,进而针对RPC
层各字段进行过滤。因为Padding字段长度有变毕竟是极少数事件,万一哪天你细心
地碰上了,可以针对性地增加另一类过滤,然后逻辑或一下。
下面是前述Bind(11)报文的响应报文:
--------------------------------------------------------------------------
Transmission Control Protocol, Src Port: 139 (139), Dst Port: 52635 (52635), Len: 128
NetBIOS Session Service
Message Type: Session message
Flags: 0x00
.... ...0 = Add 0 to length
Length: 124
SMB (Server Message Block Protocol)
SMB Header
Server Component: SMB
Response to: 1
Time from request: 0.000545000 seconds
SMB Command: Trans (0x25)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x88
1... .... = Request/Response: Message is a response to the client/redirector
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc001
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only
...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs
.... 0... .... .... = Extended Security Negotiation: Extended security negotiation is not supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .0.. = Security Signatures: Security signatures are not supported
.... .... .... ..0. = Extended Attributes: Extended attributes are not supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Process ID High: 0
Signature: 0000000000000000
Reserved: 0000
Tree ID: 2048
Process ID: 23643
User ID: 2048
Multiplex ID: 63744
Trans Response (0x25)
Word Count (WCT): 10
Total Parameter Count: 0
Total Data Count: 68
Reserved: 0000
Parameter Count: 0
Parameter Offset: 56
Parameter Displacement: 0
Data Count: 68
Data Offset: 56
Data Displacement: 0
Setup Count: 0
Reserved: 00
Byte Count (BCC): 69
Padding: 00
SMB Pipe Protocol
Function: TransactNmPipe (0x0026)
FID: 0x4000
DCE RPC Bind_ack, Fragment: Single, FragLen: 68, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind_ack (12)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 68
Auth Length: 0
Call ID: 1
Max Xmit Frag: 4280
Max Recv Frag: 4280
Assoc Group: 0x00011135
Scndry Addr len: 13
Scndry Addr: /PIPE/ntsvcs
Num results: 1
Ack result: Acceptance (0)
Transfer Syntax: 8a885d04-1ceb-11c9-9fe8-08002b104860
Syntax ver: 2
0040 00 00 00 7c ff 53 4d 42 25 00 00 00 00 88 ...|.SMB%.....
0050 01 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
0060 5b 5c 00 08 00 f9 0a 00 00 44 00 00 00 00 00 38 [/.......D.....8
0070 00 00 00 44 00 38 00 00 00 00 00 45 00 00 05 00 ...D.8.....E....
0080 0c 03 10 00 00 00 44 00 00 00 01 00 00 00 b8 10 ......D.........
0090 b8 10 35 11 01 00 0d 00 5c 50 49 50 45 5c 6e 74 ..5...../PIPE/nt
00a0 73 76 63 73 00 00 01 00 00 00 00 00 00 00 04 5d svcs...........]
00b0 88 8a eb 1c c9 11 9f e8 08 00 2b 10 48 60 02 00 ..........+.H`..
00c0 00 00 ..
--------------------------------------------------------------------------
协议序列为ncacn_np时,Scndry Addr len、Scndry Addr字段明显有变,以至RPC层
大小不再是60,但你也不能说它固定是68,显然因Scndry Addr的内容而变。要小心
获取Ack result字段在RPC层的偏移。
分析响应报文时同样需要正确定位RPC层。这次Data Offset字段本身在TCP数据区的
偏移是51(不再是61),该字段的值加4后即RPC层在TCP数据区的偏移。
用协议分析工具时可以先过滤出Trans(0x25),再直接假设RPC层在TCP数据区的偏移
是+0x03C,进而针对RPC层各字段进行过滤。
SMB_37_3.cap的显示就不文本化了,与SMB_37_1.cap类似。发送Bind报文试图绑定不
存在的接口UUID,引发Provider rejection(2)报文。区别在于承载者由TCP变成SMB,
其它分析不变。这个包不可能在身边的环境中抓到,我用程序发出来的,提供在此仅
用于研究,大家自己打开了看。
3) "BIND Over Write AndX"简介
当Bind(11)由SMB命令Write AndX(0x2f)承载时,即"BIND Over Write AndX"。
可以简单地将Transaction理解成Write/Read的合成命令,区别在于前者处理小数据
量的通信,后者处理大数据量的通信。至于多少算小多少算大,你我都不必关心细节。
它们之间的关系远非如此简单,与本文关系不大,不纠缠了。
前面说过,SMB层的实现同时用到了139、445/TCP,二者之间是竞争关系。此次出于
演示目的,我用程序手工发送报文,指定使用445/TCP。下面是一次枚举共享操作中
出现的报文(SMB_37_4.cap):
--------------------------------------------------------------------------
Transmission Control Protocol, Src Port: 37665 (37665), Dst Port: 445 (445), Len: 140
NetBIOS Session Service
Message Type: Session message
Length: 136
SMB (Server Message Block Protocol)
SMB Header
Server Component: SMB
Response in: 2
SMB Command: Write AndX (0x2f)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x08
0... .... = Request/Response: Message is a request to the server
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc001
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only
...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs
.... 0... .... .... = Extended Security Negotiation: Extended security negotiation is not supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .0.. = Security Signatures: Security signatures are not supported
.... .... .... ..0. = Extended Attributes: Extended attributes are not supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Process ID High: 0
Signature: 0000000000000000
Reserved: 0000
Tree ID: 2048
Process ID: 38271
User ID: 2048
Multiplex ID: 25139
Write AndX Request (0x2f)
Word Count (WCT): 14
AndXCommand: No further commands (0xff)
Reserved: 00
AndXOffset: 0
FID: 0x4000
Offset: 0
Reserved: FFFFFFFF
Write Mode: 0x0008
.... .... .... 1... = Message Start: This is the START of a MESSAGE (pipe)
.... .... .... .0.. = Write Raw: DON'T use WriteRawNamedPipe (pipe)
.... .... .... ..0. = Return Remaining: DON'T return remaining (pipe/dev)
.... .... .... ...0 = Write Through: Write through not requested
Remaining: 72
Data Length High (multiply with 64K): 0
Data Length Low: 72
Data Offset: 64
High Offset: 0
Byte Count (BCC): 73
Padding: 00
DCE RPC Bind, Fragment: Single, FragLen: 72, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind (11)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 72
Auth Length: 0
Call ID: 1
Max Xmit Frag: 4280
Max Recv Frag: 4280
Assoc Group: 0x00000000
Num Ctx Items: 1
Context ID: 0
Num Trans Items: 1
Interface UUID: 4b324fc8-1670-01d3-1278-5a47bf6ee188
Interface Ver: 3
Interface Ver Minor: 0
Transfer Syntax: 8a885d04-1ceb-11c9-9fe8-08002b104860
Syntax ver: 2
0040 00 00 00 88 ff 53 4d 42 2f 00 00 00 00 08 .....SMB/.....
0050 01 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
0060 7f 95 00 08 33 62 0e ff 00 00 00 00 40 00 00 00 ....3b......@...
0070 00 ff ff ff ff 08 00 48 00 00 00 48 00 40 00 00 .......H...H.@..
0080 00 00 00 49 00 00 05 00 0b 03 10 00 00 00 48 00 ...I..........H.
0090 00 00 01 00 00 00 b8 10 b8 10 00 00 00 00 01 00 ................
00a0 00 00 00 00 01 00 c8 4f 32 4b 70 16 d3 01 12 78 .......O2Kp....x
00b0 5a 47 bf 6e e1 88 03 00 00 00 04 5d 88 8a eb 1c ZG.n.......]....
00c0 c9 11 9f e8 08 00 2b 10 48 60 02 00 00 00 ......+.H`....
Transmission Control Protocol, Src Port: 445 (445), Dst Port: 37665 (37665), Len: 51
NetBIOS Session Service
Message Type: Session message
Length: 47
SMB (Server Message Block Protocol)
SMB Header
Server Component: SMB
Response to: 1
Time from request: 0.000601000 seconds
SMB Command: Write AndX (0x2f)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x88
1... .... = Request/Response: Message is a response to the client/redirector
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc001
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only
...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs
.... 0... .... .... = Extended Security Negotiation: Extended security negotiation is not supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .0.. = Security Signatures: Security signatures are not supported
.... .... .... ..0. = Extended Attributes: Extended attributes are not supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Process ID High: 0
Signature: 0000000000000000
Reserved: 0000
Tree ID: 2048
Process ID: 38271
User ID: 2048
Multiplex ID: 25139
Write AndX Response (0x2f)
Word Count (WCT): 6
AndXCommand: No further commands (0xff)
Reserved: 00
AndXOffset: 47
FID: 0x4000
Count Low: 72
Remaining: 65535
Count High (multiply with 64K): 0
Reserved: 0000
Byte Count (BCC): 0
0040 00 00 00 2f ff 53 4d 42 2f 00 00 00 00 88 .../.SMB/.....
0050 01 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
0060 7f 95 00 08 33 62 06 ff 00 2f 00 48 00 ff ff 00 ....3b.../.H....
0070 00 00 00 00 00 .....
--------------------------------------------------------------------------
对于139/TCP来说,TCP数据区前4字节算是NBT层的。对于445/TCP来说,TCP数据区前
4字节不算是NBT层的,直接交给SMB层的代码处理了,但在旁路解码处理时,不必关
心这些细节,方便起见,仍称这4字节为NBT层数据。
对比SMB_37_2.cap与SMB_37_4.cap中NBT层的解码,后者已经没有了Flags字段,而
Length字段由17-bits扩展到24-bits。
Write AndX(0x2f)承载的RPC层仍占72字节,与前面两小节相比没有任何区别,作为
承载者的SMB层本身却发生重大变化。SMB Command变成Write AndX(0x2f),对SMB层
的解码也就变了,Data Offset字段本身在TCP数据区的偏移变成59。Data Length等
于72,正好是RPC层的大小,RPC层是做为SMB层数据区出现的!
至此已经很清晰地感受到协议分层处理这个事实。在讨论DCE/MS RPC时,应将SMB层
看作与TCP层一样的传输层,RPC层可以在这些传输层中选择一个作为承载者。至于传
输层内部如何实现,不关RPC层的事。
用协议分析工具时可以先过滤出Write AndX(0x2f),再直接假设RPC层在TCP数据区的
偏移是+0x044,进而针对RPC层各字段进行过滤。
与前面两小节相比,另一个重要变化是Bind_ack(12)报文并未随Write AndX(0x2f)的
响应报文出现,此时必须显式调用Read AndX(0x2e)读取Bind_ack(12):
--------------------------------------------------------------------------
Transmission Control Protocol, Src Port: 37665 (37665), Dst Port: 445 (445), Len: 63
NetBIOS Session Service
Message Type: Session message
Length: 59
SMB (Server Message Block Protocol)
SMB Header
Server Component: SMB
Response in: 4
SMB Command: Read AndX (0x2e)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x08
0... .... = Request/Response: Message is a request to the server
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc001
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only
...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs
.... 0... .... .... = Extended Security Negotiation: Extended security negotiation is not supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .0.. = Security Signatures: Security signatures are not supported
.... .... .... ..0. = Extended Attributes: Extended attributes are not supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Process ID High: 0
Signature: 0000000000000000
Reserved: 0000
Tree ID: 2048
Process ID: 39203
User ID: 2048
Multiplex ID: 46171
Read AndX Request (0x2e)
Word Count (WCT): 12
AndXCommand: No further commands (0xff)
Reserved: 00
AndXOffset: 0
FID: 0x4000
Offset: 0
Max Count Low: 32767
Min Count: 32767
Remaining: 32767
High Offset: 0
Byte Count (BCC): 0
0040 00 00 00 3b ff 53 4d 42 2e 00 00 00 00 08 ...;.SMB......
0050 01 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
0060 23 99 00 08 5b b4 0c ff 00 00 00 00 40 00 00 00 #...[.......@...
0070 00 ff 7f ff 7f ff ff ff ff ff 7f 00 00 00 00 00 ................
0080 00 .
Transmission Control Protocol, Src Port: 445 (445), Dst Port: 37665 (37665), Len: 132
NetBIOS Session Service
Message Type: Session message
Length: 128
SMB (Server Message Block Protocol)
SMB Header
Server Component: SMB
Response to: 3
Time from request: 0.000471000 seconds
SMB Command: Read AndX (0x2e)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x88
1... .... = Request/Response: Message is a response to the client/redirector
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc001
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only
...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs
.... 0... .... .... = Extended Security Negotiation: Extended security negotiation is not supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .0.. = Security Signatures: Security signatures are not supported
.... .... .... ..0. = Extended Attributes: Extended attributes are not supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Process ID High: 0
Signature: 0000000000000000
Reserved: 0000
Tree ID: 2048
Process ID: 39203
User ID: 2048
Multiplex ID: 46171
Read AndX Response (0x2e)
Word Count (WCT): 12
AndXCommand: No further commands (0xff)
Reserved: 00
AndXOffset: 0
FID: 0x4000
Remaining: 0
Data Compaction Mode: 0
Reserved: 0000
Data Length Low: 68
Data Offset: 60
Data Length High (multiply with 64K): 0
Reserved: 000000000000
Byte Count (BCC): 69
Padding: 00
DCE RPC Bind_ack, Fragment: Single, FragLen: 68, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind_ack (12)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 68
Auth Length: 0
Call ID: 1
Max Xmit Frag: 4280
Max Recv Frag: 4280
Assoc Group: 0x00024b67
Scndry Addr len: 13
Scndry Addr: /PIPE/ntsvcs
Num results: 1
Ack result: Acceptance (0)
Transfer Syntax: 8a885d04-1ceb-11c9-9fe8-08002b104860
Syntax ver: 2
0040 00 00 00 80 ff 53 4d 42 2e 00 00 00 00 88 .....SMB......
0050 01 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
0060 23 99 00 08 5b b4 0c ff 00 00 00 00 00 00 00 00 #...[...........
0070 00 44 00 3c 00 00 00 00 00 00 00 00 00 00 00 45 .D.<...........E
0080 00 00 05 00 0c 03 10 00 00 00 44 00 00 00 01 00 ..........D.....
0090 00 00 b8 10 b8 10 67 4b 02 00 0d 00 5c 50 49 50 ......gK..../PIP
00a0 45 5c 6e 74 73 76 63 73 00 00 01 00 00 00 00 00 E/ntsvcs........
00b0 00 00 04 5d 88 8a eb 1c c9 11 9f e8 08 00 2b 10 ...]..........+.
00c0 48 60 02 00 00 00 H`....
--------------------------------------------------------------------------
Bind_ack(12)报文随Read AndX(0x2e)的响应报文出现。Data Offset字段本身在TCP
数据区的偏移是49。
用协议分析工具时可以先过滤出Read AndX(0x2e),再直接假设RPC层在TCP数据区的
偏移是+0x040,进而针对RPC层各字段进行过滤。重复提醒,Padding字段长度不固定,
偏移+0x040只是权宜之计,如能动态根据Data Offset字段的值计算偏移最好不过。
前两小节的BIND操作只涉及一来一回两个报文,本小节的BIND操作却涉及四个报文,
麻烦了许多。一般"BIND Over Transaction"都能安全替代"BIND Over Write AndX",
自己写程序实现BIND操作时不必选用后者。但是在协议分析过程中,却有可能同时碰
上二者。
扯远一点。当出现一些DCE/MS RPC类蠕虫时,会有公司或个人提供一些定制后的过滤
规则。从我们前期的短小分析来看,这些过滤规则面临一些难题,或者说因协议分析
工具自身能力不足带来的难题。一是动态端口,这个现在仍不急着讲。二是从协议层
次上精确定位RPC层,我不清楚现有工具中哪个可以识别了SMB Command之后动态定位
Data Offset字段本身在TCP数据区的偏移,动态根据Data Offset字段的值计算RPC层
在TCP数据区的偏移,同时以这个偏移为基准定位其它RPC层的协议字段。更多时候这
些公开发布的过滤规则就像我前面介绍的那样,做了一些重大假设,比如填充域长度
固定,只考虑"BIND Over Write AndX",不考虑"BIND Over Transaction"等等。针对
蠕虫的某一特定实例,做这样的重大假设是可以的,其作者不太可能变态到同时实现
了两种BIND操作,随机挑着用。但我今天这么公开提到了,难说下次蠕虫作者不这样
干。真要出现这样的局面,只好设置多套过滤,逻辑或一下。总有人抱怨过滤规则不
工作,那是因为出现了蠕虫变种、Exploit变种等等,违背了原过滤规则所做的重大
假设。这时应抓取样本报文,自行设置过滤规则。话说回来,协议分析工具做这种事
确实太勉为其难了,交互式分析工具严重依赖于人的参与,这也导致NIDS、NIPS必然
出场。NIDS、NIPS是程序实现的解码分析,灵活得多。
协议分析工具、NIDS、NIPS的相同点是都要做协议分层解码,都要逐层剥离,一旦中
间某层解码失败,作为负载出现的后续层次都将解码失败。DCE/MS RPC由SMB承载时,
首先要对SMB层进行解码才好继续进行后续分析。Ethereal是目前我所用过的协议分
析工具中对SMB层解码最深入的一个,推荐使用。而Samba是目前我所见过的对SMB层
Hacking最深的开源项目,远比Ethereal深入,甚至可以说不在一个层次。即使现在
部份Windows源码泄露,也还是值得研读Samba源码。
协议分层越多,解码越麻烦,也越容易忽略许多例外情形。换句话说,很多工具、程
序只考虑到最常见的情形,多多少少、有意无意做了一些假设,当例外情形出现违背
了这些假设,问题就来了。Ethereal对SMB层解码太深,历史上出现过的问题就很多,
我敢打赌,到现在还有问题。至于Samba么,一样的,在Samba项目的历史上出现过很
多现在也鲜为人知的趣事,这群天才们从无到有Hacking SMB,那还是Windows的早期,
Samba与Windows通信时搞出个BSOD实在是太普通了。要是搁在现在,不成了大漏洞、
大新闻么。当时的环境、氛围与现在太不同,最终多半是安静地通知微软并协助修补
了事。有个叫Luke Kenneth Casson Leighton的人,此人是半路加盟Samba Team的,
也算是天才,很强悍,后来因个人理念冲突与Samba Team分道扬镳,再后来加入ISS
的XForce小组继续从事SMB协议分析。他写过一本书:
<<DCE/RPC OVER SMB - SAMBA AND WINDOWS NT DOMAIN INTERNALS>>
99年出的。因为Ethereal已经得到相当程度的加强,这书搁到现在算不上稀世奇珍了,
但仍可从中找到一些Ethereal至今未做解码的内容,Samba早在99年之前就解码了!
他在该书中提到一件事,NT 4 SP4之前有一个与Auth Length字段相关的BUG,微软成
功地在保持了向后兼容性的前提下修正了BUG,作者称之为"quite a feat"。在该书
中看到多处历史上悄悄修补过的SMB层BUG,叹息啊,没赶上好时光,也没那群天才们
的实力,同时相当佩服微软保持向后兼容性的强悍。
其它协议分析工具对SMB层解码相比Ethereal就太浅了,但同时也少了很多麻烦,比
如Iris这个小不点,当成玩具就可以了,不会擦枪走火的。不要迷信商业版协议分析
软件,一样的,解码越深死得越快,不解码或只简单解码活下来的机会更大。snort、
tcpdump死得不比Ethereal少。ISS的商业版NIDS很强,对SMB层的解码分析能力是我
接触过的同型产品中最强的一个,没办法,人家的XForce小组中就有好几个前Samba
Team的人。但这同时意味着解码风险增加,已经出过几次问题了。想像一下,假设我
知道某竞争对手的产品对SMB层解码很强,就针对性地制造畸型SMB报文,会如何。不
过放心啦,国内的NIDS、NIPS没这水平,想搞它们都没机会。这事有点讽刺,就跟傻
也是一种幸福一样。
SMB_37_5.cap与SMB_37_3.cap类似。发送Bind报文试图绑定不存在的接口UUID,引发
Provider rejection(2)报文。承载者都是SMB,但这次是"BIND Over Write AndX"。
同样这个包不可能在身边的环境中抓到,我用程序发出来的,提供在此仅用于研究。
这一节只起对比作用,结果由技术文章写成八卦话题了,就当灌水吧。
4) "BIND Over ..."扩展
怀疑另外两个SMB命令NT Trans(0xa0)、Trans2(0x32)也可以承载Bind(11),虽然我
在现实环境中尚未抓包观察到,最近也没时间写程序测试,记录于此,仅作备忘。
对此有两份文档([3]、[4])可供参考:
<<NT LAN Manager SMB File Sharing Protocol Extensions>>
3.2 NT Transact SMB
4.5.1 NT Transact
<<Implementing CIFS>>
2.9.4 Transaction SMBs
这三种Transaction命令的差别相当小。如果我写恶意程序,一定会尝试另两种Trans
命令,尽可能地规避IDS嘛。
5) SMB_COM_TRANSACTION2与SMB_COM_NT_TRANSACTION
在上一小节我提到这两个命令,并且怀疑它们亦可用于承载Bind(11)。拖了些日子,
昨天翻看draft-leach-cifs-v1-spec-02.txt([11]),发现原来的简单想象有问题。
参看如下小节:
3.13.1 SMB_COM_TRANSACTION and SMB_COM_TRANSACTION2 Formats
6.2 SMB_COM_TRANSACTION2 Subcommand codes
3.13.2 SMB_COM_NT_TRANSACTION Formats
6.3 SMB_COM_NT_TRANSACTION Subcommand Codes
4.6.1 NT_TRANSACT_IOCTL
SMB_COM_TRANSACTION2(0x32)请求包的格式与SMB_COM_TRANSACTION(0x25)非常像,
但是这次Setup Count由2变成了1。原来的Setup[]对应:
Setup[0] Function: TransactNmPipe (0x0026)
Setup[1] FID: 0x4000
现在的Setup[]对应:
Setup[0] Subcommand:
原来有"Transaction Name: /PIPE/"字段,现在没有这个字段。这实际意味着二者的
编码解码完全不同了,SMB_COM_TRANSACTION2的具体功能与Subcommand紧密相关,无
法承载抽象的Bind(11)。
在cmd中执行start //<ip>/<share>,抓取SMB_37_6.cap:
--------------------------------------------------------------------------
Transmission Control Protocol, Src Port: 3268, Dst Port: 445, Len: 80
NetBIOS Session Service
Message Type: Session message
Length: 76
SMB (Server Message Block Protocol)
SMB Header
Server Component: SMB
Response in: 2
SMB Command: Trans2 (0x32)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x18
0... .... = Request/Response: Message is a request to the server
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...1 .... = Canonicalized Pathnames: Pathnames are canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc807
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only
...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs
.... 1... .... .... = Extended Security Negotiation: Extended security negotiation is supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .1.. = Security Signatures: Security signatures are supported
.... .... .... ..1. = Extended Attributes: Extended attributes are supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Process ID High: 0
Signature: 0000000000000000
Reserved: 0000
Tree ID: 2052
Process ID: 1576
User ID: 2049
Multiplex ID: 3584
Trans2 Request (0x32)
Word Count (WCT): 15
Total Parameter Count: 8
Total Data Count: 0
Max Parameter Count: 2
Max Data Count: 40
Max Setup Count: 0
Reserved: 00
Flags: 0x0000
.... .
☆ DCE/MS RPC架构简介
☆ BIND操作简介
1) "BIND Over TCP"简介
2) "BIND Over Transaction"简介
3) "BIND Over Write AndX"简介
4) "BIND Over ..."扩展
5) SMB_COM_TRANSACTION2与SMB_COM_NT_TRANSACTION
☆ PFC_OBJECT_UUID标志位
☆ MS02-045/Q326830
☆ WildPackets Free Filters for Detecting Malicious Worms/Viruses
☆ /pipe/epmapper
☆ 135/UDP相关讨论
1) XP SP1的msgsvc.dll(5.1.2600.1309)
2) 中文2000的msgsvc.dll(5.0.2195.4874)
3) 通过135/UDP访问MGMT
4) 通过135/UDP访问EPM
☆ Windows网络服务最小化
☆ MS05-040/KB893756
☆ DriverStudio Remote Control服务
☆ 参考资源
--------------------------------------------------------------------------
☆ DCE/MS RPC架构简介
本节属于科普性质,文字描述不那么规范,将就着看吧。
一个RPC服务可以绑定多种协议序列,也可以只绑定某一种协议序列,这是实现相关
的,没有定式。某接口绑定N种协议序列,就意味着有N条途径可以访问该接口。可以
用135dump.exe、ifids.exe等工具查询这类信息。
+-- ncacn_ip_tcp(动态TCP口)
|
DCE/MS RPC--+-- ncadg_ip_udp(动态UDP口)
|
+-- ncacn_np(固定的139、445/TCP口)
|
+-- ... ...(其它协议序列)
可以将DCE/MS RPC看作一层,这一层可以在不同的协议序列上跑,比如上面列出的三
种。实际上还有其它协议序列可用,但不常见,这里就不罗嗦了。
ncacn_ip_tcp与ncadg_ip_udp用到了动态端口,它们会向EPM接口注册所用动态端口,
而客户端可以向EPM接口查询服务端注册过的信息。如果客户端有其它手段提前知道
服务端所用动态端口,就可以省去向EPM接口查询的操作。
一般碰上的是版本5的RPC,ncacn_ip_tcp、ncacn_np等用的就是V5。而ncadg_ip_udp
用的则是版本4的RPC。V4与V5的差别很大。你在现实环境中很难观察到V4。历史上某
些版本的net send命令会用到V4,MS02-045/Q326830补丁取消了Messenger服务绑定
的ncadg_ip_udp协议序列,现在更难在现实环境中观察到V4了。
EPM接口本身是一个RPC服务,同样有多种协议序列可用来访问这个接口。
ncacn_np协议序列用到了SMB协议,DCE/MS RPC层位于SMB层上,SMB层再位于TCP层上。
有些文字会介绍说139/TCP口的通信是SMB层位于NBT层上,NBT层位于TCP层上。这一
点对于旁路协议分析来讲,没有必要区分,可以将NBT层那四字节划入SMB层。再简单
点说,旁路协议分析时,可以认为139、445/TCP仅仅是端口不同,没有其它区别。
SMB协议可以由多种命令来承载DCE/MS RPC层数据,同样是139、445/TCP上的通信,
因不同的SMB命令而导致不同的SMB层解码。
无论用哪种协议序列,用哪种SMB命令,访问一个RPC接口的典型步骤是:
a) Bind
b) Request
不同的协议序列、不同SMB命令就对应不同的Bind Over ...、Request Over ...。
分层解码后到了DCE/MS RPC这一层,就都一样了。
做DCE/MS RPC协议分析时,首先就应该关注Bind操作。
--------- --------- -------------- -------
动态TCP口 动态UDP口 139、445/TCP口 ... ...
----+---- ----+---- --------+----- ----+--
| | | |
| | ----+---- ----+--
| | SMB层解码 ... ...
| | ----+---- ----+--
| | | |
+-----------+--------+------+-----------+
|
-----+----------
DCE/MS RPC层解码
-----+----------
|
----------+--------------
RPC层各命令相关的首部解码
----------+--------------
|
+--------+--------+-----+-+------------+---------+--------+
| | | | | | |
-+-- --+-- ---+--- ---+---- ----+--- --+-- ---+---
Bind Fault Request Response Bind_ack AUTH3 ... ...
---- ----- ---+--- ---+---- -------- ----- -------
| |
+-----+-+
|
+-------+-+-----+-------+
| | | |
---+--- ---+--- ---+--- ---+---
Opnum 0 Opnum 1 ... ... Opnum N
---+--- ---+--- ---+--- ---+---
| | | |
+-------+---+---+-------+
|
-----+-------
stub data解码
-------------
在用Ethereal研究DCE/MS RPC协议时,经常看到所谓的stub data,这实际是RPC解码
关键所在。对于这些stub data的解码是IDL文件相关的,不同的IDL文件对应不同的
stub data解码。不同的RPC服务都有着各自不同的IDL文件,因此对stub data的解码
只能是具体问题具体分析,没有捷径可走。
☆ BIND操作简介
1) "BIND Over TCP"简介
一个最简单、常见的Bind_ack报文的例子如下(SMB_37_0.cap):
--------------------------------------------------------------------------
Transmission Control Protocol, Src Port: 4166 (4166), Dst Port: 135 (135), Len: 72
DCE RPC Bind, Fragment: Single, FragLen: 72, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind (11)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 72
Auth Length: 0
Call ID: 1
Max Xmit Frag: 5840
Max Recv Frag: 5840
Assoc Group: 0x00000000
Num Ctx Items: 1
Context ID: 0
Num Trans Items: 1
Interface UUID: e1af8308-5d1f-11c9-91a4-08002b14a0fa
Interface Ver: 3
Interface Ver Minor: 0
Transfer Syntax: 8a885d04-1ceb-11c9-9fe8-08002b104860
Syntax ver: 2
0030 05 00 0b 03 10 00 00 00 48 00 ........H.
0040 00 00 01 00 00 00 d0 16 d0 16 00 00 00 00 01 00 ................
0050 00 00 00 00 01 00 08 83 af e1 1f 5d c9 11 91 a4 ...........]....
0060 08 00 2b 14 a0 fa 03 00 00 00 04 5d 88 8a eb 1c ..+........]....
0070 c9 11 9f e8 08 00 2b 10 48 60 02 00 00 00 ......+.H`....
Transmission Control Protocol, Src Port: 135 (135), Dst Port: 4166 (4166), Len: 60
DCE RPC Bind_ack, Fragment: Single, FragLen: 60, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind_ack (12)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 60
Auth Length: 0
Call ID: 1
Max Xmit Frag: 5840
Max Recv Frag: 5840
Assoc Group: 0x00012bee
Scndry Addr len: 4
Scndry Addr: 135
Num results: 1
Ack result: Acceptance (0)
Transfer Syntax: 8a885d04-1ceb-11c9-9fe8-08002b104860
Syntax ver: 2
0030 05 00 0c 03 10 00 00 00 3c 00 ........<.
0040 00 00 01 00 00 00 d0 16 d0 16 ee 2b 01 00 04 00 ...........+....
0050 31 33 35 00 00 00 01 00 00 00 00 00 00 00 04 5d 135............]
0060 88 8a eb 1c c9 11 9f e8 08 00 2b 10 48 60 02 00 ..........+.H`..
0070 00 00 ..
--------------------------------------------------------------------------
试图绑定DCE/MS RPC Endpoint Mapper Interface UUID时引发上述报文。
Auth Length一般情况下为0,但并非总为0。关于这个字段,参看MSDN中如下函数:
RpcServerRegisterAuthInfo
RpcBindingInqAuthClient
RpcBindingSetAuthInfo
Auth Length为0的情况下,Bind(11)报文的RPC层大小固定为72。
Bind_ack(12)报文的RPC层大小变动较大,一是受Auth Length的影响,二是受Scndry
Addr的影响,Scndry Addr后面的Num results要求对齐在四字节边界上。当Scndry
Addr对应字符串表示的端口号时,Scndry Addr len最大等于6,即"65535"所占字节
数,包括结尾的NUL字符。由于Num results四字节对齐的缘故,"65535"不会比"135"
多占任何字节,因此当Scndry Addr对应字符串表示的端口号时,Auth Length为0的
情况下,Bind_ack(12)报文的RPC层大小固定为60。这种情形很常见,ncacn_ip_tcp
协议序列对应的BIND操作多半是这种情形,换句话说,BIND Over TCP多半是这种情
形。但是,ncacn_np协议序列对应的BIND操作就不是这种情形。
收到Bind_ack(12)报文并不意味着BIND操作成功,要检查Ack result字段:
0 Acceptance
2 Provider rejection
应该还有其它值,但那不重要。解析Bind_ack报文时,务必判断Ack result字段是否
等于Acceptance(0),此时意味着BIND操作成功。以前一直以为收到Bind_nak(13)报
文才意味着BIND操作失败,不想近日做实验时意外地发现结论错误。
一个解码陷阱源于Ack result在Scndry Addr之后。ncacn_ip_tcp协议序列下Ack
result在RPC层的偏移可以认为是固定的+0x024,ncacn_np协议序列下这个偏移就变
了。可移植的解决方案是无论哪种协议序列,先取Scndry Addr len,再考虑四字节
对齐的事,动态计算Ack result的偏移。这个方案不受Auth Length的影响,认证相
关的数据位于尾部。另一个方案是先获取Auth Length,并确保收到的是完整的非畸
型的Bind_ack报文,然后从尾部倒推偏移-Auth Length-0x018。这个方案并不比前一
个方案更有优势,看个人喜好了。为此修正了一批早期编写的代码。
下面是一个Provider rejection(2)的例子(SMB_37_1.cap):
--------------------------------------------------------------------------
Transmission Control Protocol, Src Port: 60367 (60367), Dst Port: 135 (135), Len: 72
DCE RPC Bind, Fragment: Single, FragLen: 72, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind (11)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 72
Auth Length: 0
Call ID: 1
Max Xmit Frag: 4280
Max Recv Frag: 4280
Assoc Group: 0x00000000
Num Ctx Items: 1
Context ID: 0
Num Trans Items: 1
Interface UUID: ffffffff-ffff-ffff-ffff-ffffffffffff
Interface Ver: 0
Interface Ver Minor: 0
Transfer Syntax: 8a885d04-1ceb-11c9-9fe8-08002b104860
Syntax ver: 2
0040 05 00 0b 03 10 00 00 00 48 00 00 00 01 00 ........H.....
0050 00 00 b8 10 b8 10 00 00 00 00 01 00 00 00 00 00 ................
0060 01 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
0070 ff ff 00 00 00 00 04 5d 88 8a eb 1c c9 11 9f e8 .......]........
0080 08 00 2b 10 48 60 02 00 00 00 ..+.H`....
Transmission Control Protocol, Src Port: 135 (135), Dst Port: 60367 (60367), Len: 60
DCE RPC Bind_ack, Fragment: Single, FragLen: 60, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind_ack (12)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 60
Auth Length: 0
Call ID: 1
Max Xmit Frag: 4280
Max Recv Frag: 4280
Assoc Group: 0x00012bf6
Scndry Addr len: 4
Scndry Addr: 135
Num results: 1
Ack result: Provider rejection (2)
Ack reason: Abstract syntax not supported (1)
Transfer Syntax: 00000000-0000-0000-0000-000000000000
Syntax ver: 0
0040 05 00 0c 03 10 00 00 00 3c 00 00 00 01 00 ........<.....
0050 00 00 b8 10 b8 10 f6 2b 01 00 04 00 31 33 35 00 .......+....135.
0060 00 00 01 00 00 00 02 00 01 00 00 00 00 00 00 00 ................
0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..............
--------------------------------------------------------------------------
此次Ack result等于Provider rejection(2)时,Ack reason字段开始有意义,另一
明显变化是Transfer Syntax字段。
Bind_ack(12)报文的RPC层大小与协议序列有关,但与Ack result、Ack reason字段
无关,这是两个短整型,始终占去4字节。因此上述Bind_ack(12)报文的RPC层大小仍
等于60。
向135/TCP发送Bind报文试图绑定不存在的接口UUID,就引发出如上Bind_ack报文。
这是一次实验意外出错后的结果,现实环境中这样的报文相当罕见,折腾DCE/MS RPC
这么久,还是第一次看到,为此修正了一批早期编写的代码。
2) "BIND Over Transaction"简介
当Bind(11)由SMB命令Trans(0x25)承载时,即"BIND Over Transaction"。
这是枚举Windows 2000共享时抓取的报文(SMB_37_2.cap):
--------------------------------------------------------------------------
Transmission Control Protocol, Src Port: 52635 (52635), Dst Port: 139 (139), Len: 160
NetBIOS Session Service
Message Type: Session message
Flags: 0x00
.... ...0 = Add 0 to length
Length: 156
SMB (Server Message Block Protocol)
SMB Header
Server Component: SMB
Response in: 2
SMB Command: Trans (0x25)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x08
0... .... = Request/Response: Message is a request to the server
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc001
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only
...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs
.... 0... .... .... = Extended Security Negotiation: Extended security negotiation is not supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .0.. = Security Signatures: Security signatures are not supported
.... .... .... ..0. = Extended Attributes: Extended attributes are not supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Process ID High: 0
Signature: 0000000000000000
Reserved: 0000
Tree ID: 2048
Process ID: 23643
User ID: 2048
Multiplex ID: 63744
Trans Request (0x25)
Word Count (WCT): 16
Total Parameter Count: 0
Total Data Count: 72
Max Parameter Count: 0
Max Data Count: 1024
Max Setup Count: 0
Reserved: 00
Flags: 0x0000
.... .... .... ..0. = One Way Transaction: Two way transaction
.... .... .... ...0 = Disconnect TID: Do NOT disconnect TID
Timeout: Return immediately (0)
Reserved: 0000
Parameter Count: 0
Parameter Offset: 84
Data Count: 72
Data Offset: 84
Setup Count: 2
Reserved: 00
Byte Count (BCC): 89
Transaction Name: /PIPE/
Padding: 0000
SMB Pipe Protocol
Function: TransactNmPipe (0x0026)
FID: 0x4000
DCE RPC Bind, Fragment: Single, FragLen: 72, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind (11)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 72
Auth Length: 0
Call ID: 1
Max Xmit Frag: 4280
Max Recv Frag: 4280
Assoc Group: 0x00000000
Num Ctx Items: 1
Context ID: 0
Num Trans Items: 1
Interface UUID: 4b324fc8-1670-01d3-1278-5a47bf6ee188
Interface Ver: 3
Interface Ver Minor: 0
Transfer Syntax: 8a885d04-1ceb-11c9-9fe8-08002b104860
Syntax ver: 2
0040 00 00 00 9c ff 53 4d 42 25 00 00 00 00 08 .....SMB%.....
0050 01 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
0060 5b 5c 00 08 00 f9 10 00 00 48 00 00 00 00 04 00 [/.......H......
0070 00 00 00 00 00 00 00 00 00 00 00 54 00 48 00 54 ...........T.H.T
0080 00 02 00 26 00 00 40 59 00 00 5c 00 50 00 49 00 ...&..@Y../.P.I.
0090 50 00 45 00 5c 00 00 00 00 00 05 00 0b 03 10 00 P.E./...........
00a0 00 00 48 00 00 00 01 00 00 00 b8 10 b8 10 00 00 ..H.............
00b0 00 00 01 00 00 00 00 00 01 00 c8 4f 32 4b 70 16 ...........O2Kp.
00c0 d3 01 12 78 5a 47 bf 6e e1 88 03 00 00 00 04 5d ...xZG.n.......]
00d0 88 8a eb 1c c9 11 9f e8 08 00 2b 10 48 60 02 00 ..........+.H`..
00e0 00 00 ..
--------------------------------------------------------------------------
SMB Command字段表明此次RPC通信由Transaction承载。RPC层的Bind(11)报文仍占72
字节。本例与"BIND Over Tcp"的情形相比,一是RPC层的承载者由TCP变成了SMB,二
是接口UUID变了,除此之外,并无区别。微软很好地实现了协议分层处理。
Bind(11)报文对于DCE/MS RPC协议分析来讲,至关重要,直接体现在暴露了接口UUID。
在Google中搜索"4b324fc8-1670-01d3-1278-5a47bf6ee188",重点推荐:
Well-known DCE RPC named pipes endpoints
[url]http://www.hsc.fr/ressources/articles/win_net_srv/ch04s05s03.html[/url]
这里有一张表"Named pipes used by DCE RPC servers",列举了部分接口UUID对应
的服务或进程,协议分析爱好者可以参看。
接口UUID即上述显示中的Interface UUID字段,不要与Transfer Syntax字段混淆了。
分析DCE/MS RPC通信时,没有接口UUID寸步难行。后续的Request(0)报文中的Opnum
是接口UUID相关的,A接口的0号调用与B接口的0号调用显然是两个独立的调用。有时
会碰上求助者提供了CAP文件,居然只有Request(0)报文,没有Bind(11)报文,分析
者将很难进行有效分析。
那么怎么针对接口UUID设置过滤规则呢?先要搞清楚层次关系,我们可能碰上不同的
承载,就目前举例来讲,已经出现了TCP、SMB两种。
"BIND Over Tcp"对应协议序列ncacn_ip_tcp,目标端口理论上可以是任意TCP端口。
在设置端口过滤时,只能是具体问题具体分析,后面会单独讲这个问题。抛开端口不
谈,Interface UUID字段在TCP数据区(注意我的用词)的偏移是固定的+0x020,由于
UUID大小固定,后面版本字段在TCP数据区的偏移也是固定的。真正设置过滤规则时,
还可以对Version、Packet type、Transfer Syntax字段进行过滤,减少误报。
前面提到了"在TCP数据区的偏移",意味着我假设手头的工具可以正确定位TCP数据区,
即剥掉IP首部、TCP首部之后的TCP数据区。你不能简单地从IP首部+40,要考虑可能
出现的IP选项、TCP选项。从协议分层的理念来讲,定位在TCP数据区的偏移也是合理
的。
"BIND Over Transaction"对应协议序列ncacn_np,目标端口理论上只有两个,139与
445/TCP,很容易设置端口过滤。一般必须同时观察这两个端口上的通信过程。A时刻
抓取的报文可能用了139/TCP,B时刻抓取的报文可能用了445/TCP。这不是RPC层的问
题,而是SMB层的问题。SMB层的实现最早只用到139/TCP,后来增加了445/TCP,微软
保持向后兼容性,宏观上139与445是竞争关系。抛开端口不谈,Interface UUID字段
在RPC层(注意我的用词)的偏移是固定的+0x020,由于UUID大小固定,后面版本字段
在RPC层的偏移也是固定的。真正设置过滤规则时,还可以对Version、Packet type、
Transfer Syntax字段进行过滤,减少误报。
前面提到了"在RPC层的偏移",意味着我假设手头的工具可以正确定位RPC层。剥掉IP
首部、TCP首部可能好理解也好操作,大家都熟了,剥掉SMB层可能不太熟。看前面显
示的Data Offset字段,字段值加上4即RPC层在TCP数据区的偏移,SMB层就这样简单
地被剥掉了。别高兴得太早,Data Offset字段本身在TCP数据区的偏移是随SMB命令
而改变的,就Trans(0x25)而言,偏移是61。有人要问了,我先过滤出Trans(0x25),
再直接假设RPC层在TCP数据区的偏移是+0x058,不就得了。嘿,这是有问题的。注意
看上面显示中的Padding字段,该字段的长度与值不固定!可能你抓了1000次包,都
没看到Padding字段的长度有变化,但第1001次你敢保证仍不变吗?事实上我最初写
代码时就是这样假设的,结果后来针对不同OS测试时意外出错,调试了半天才得到现
在的结论。
写程序时可以精确过滤并定位各个偏移,用协议分析工具时就得变通一下了。先过滤
先过滤出Trans(0x25),再直接假设RPC层在TCP数据区的偏移是+0x058,进而针对RPC
层各字段进行过滤。因为Padding字段长度有变毕竟是极少数事件,万一哪天你细心
地碰上了,可以针对性地增加另一类过滤,然后逻辑或一下。
下面是前述Bind(11)报文的响应报文:
--------------------------------------------------------------------------
Transmission Control Protocol, Src Port: 139 (139), Dst Port: 52635 (52635), Len: 128
NetBIOS Session Service
Message Type: Session message
Flags: 0x00
.... ...0 = Add 0 to length
Length: 124
SMB (Server Message Block Protocol)
SMB Header
Server Component: SMB
Response to: 1
Time from request: 0.000545000 seconds
SMB Command: Trans (0x25)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x88
1... .... = Request/Response: Message is a response to the client/redirector
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc001
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only
...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs
.... 0... .... .... = Extended Security Negotiation: Extended security negotiation is not supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .0.. = Security Signatures: Security signatures are not supported
.... .... .... ..0. = Extended Attributes: Extended attributes are not supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Process ID High: 0
Signature: 0000000000000000
Reserved: 0000
Tree ID: 2048
Process ID: 23643
User ID: 2048
Multiplex ID: 63744
Trans Response (0x25)
Word Count (WCT): 10
Total Parameter Count: 0
Total Data Count: 68
Reserved: 0000
Parameter Count: 0
Parameter Offset: 56
Parameter Displacement: 0
Data Count: 68
Data Offset: 56
Data Displacement: 0
Setup Count: 0
Reserved: 00
Byte Count (BCC): 69
Padding: 00
SMB Pipe Protocol
Function: TransactNmPipe (0x0026)
FID: 0x4000
DCE RPC Bind_ack, Fragment: Single, FragLen: 68, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind_ack (12)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 68
Auth Length: 0
Call ID: 1
Max Xmit Frag: 4280
Max Recv Frag: 4280
Assoc Group: 0x00011135
Scndry Addr len: 13
Scndry Addr: /PIPE/ntsvcs
Num results: 1
Ack result: Acceptance (0)
Transfer Syntax: 8a885d04-1ceb-11c9-9fe8-08002b104860
Syntax ver: 2
0040 00 00 00 7c ff 53 4d 42 25 00 00 00 00 88 ...|.SMB%.....
0050 01 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
0060 5b 5c 00 08 00 f9 0a 00 00 44 00 00 00 00 00 38 [/.......D.....8
0070 00 00 00 44 00 38 00 00 00 00 00 45 00 00 05 00 ...D.8.....E....
0080 0c 03 10 00 00 00 44 00 00 00 01 00 00 00 b8 10 ......D.........
0090 b8 10 35 11 01 00 0d 00 5c 50 49 50 45 5c 6e 74 ..5...../PIPE/nt
00a0 73 76 63 73 00 00 01 00 00 00 00 00 00 00 04 5d svcs...........]
00b0 88 8a eb 1c c9 11 9f e8 08 00 2b 10 48 60 02 00 ..........+.H`..
00c0 00 00 ..
--------------------------------------------------------------------------
协议序列为ncacn_np时,Scndry Addr len、Scndry Addr字段明显有变,以至RPC层
大小不再是60,但你也不能说它固定是68,显然因Scndry Addr的内容而变。要小心
获取Ack result字段在RPC层的偏移。
分析响应报文时同样需要正确定位RPC层。这次Data Offset字段本身在TCP数据区的
偏移是51(不再是61),该字段的值加4后即RPC层在TCP数据区的偏移。
用协议分析工具时可以先过滤出Trans(0x25),再直接假设RPC层在TCP数据区的偏移
是+0x03C,进而针对RPC层各字段进行过滤。
SMB_37_3.cap的显示就不文本化了,与SMB_37_1.cap类似。发送Bind报文试图绑定不
存在的接口UUID,引发Provider rejection(2)报文。区别在于承载者由TCP变成SMB,
其它分析不变。这个包不可能在身边的环境中抓到,我用程序发出来的,提供在此仅
用于研究,大家自己打开了看。
3) "BIND Over Write AndX"简介
当Bind(11)由SMB命令Write AndX(0x2f)承载时,即"BIND Over Write AndX"。
可以简单地将Transaction理解成Write/Read的合成命令,区别在于前者处理小数据
量的通信,后者处理大数据量的通信。至于多少算小多少算大,你我都不必关心细节。
它们之间的关系远非如此简单,与本文关系不大,不纠缠了。
前面说过,SMB层的实现同时用到了139、445/TCP,二者之间是竞争关系。此次出于
演示目的,我用程序手工发送报文,指定使用445/TCP。下面是一次枚举共享操作中
出现的报文(SMB_37_4.cap):
--------------------------------------------------------------------------
Transmission Control Protocol, Src Port: 37665 (37665), Dst Port: 445 (445), Len: 140
NetBIOS Session Service
Message Type: Session message
Length: 136
SMB (Server Message Block Protocol)
SMB Header
Server Component: SMB
Response in: 2
SMB Command: Write AndX (0x2f)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x08
0... .... = Request/Response: Message is a request to the server
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc001
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only
...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs
.... 0... .... .... = Extended Security Negotiation: Extended security negotiation is not supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .0.. = Security Signatures: Security signatures are not supported
.... .... .... ..0. = Extended Attributes: Extended attributes are not supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Process ID High: 0
Signature: 0000000000000000
Reserved: 0000
Tree ID: 2048
Process ID: 38271
User ID: 2048
Multiplex ID: 25139
Write AndX Request (0x2f)
Word Count (WCT): 14
AndXCommand: No further commands (0xff)
Reserved: 00
AndXOffset: 0
FID: 0x4000
Offset: 0
Reserved: FFFFFFFF
Write Mode: 0x0008
.... .... .... 1... = Message Start: This is the START of a MESSAGE (pipe)
.... .... .... .0.. = Write Raw: DON'T use WriteRawNamedPipe (pipe)
.... .... .... ..0. = Return Remaining: DON'T return remaining (pipe/dev)
.... .... .... ...0 = Write Through: Write through not requested
Remaining: 72
Data Length High (multiply with 64K): 0
Data Length Low: 72
Data Offset: 64
High Offset: 0
Byte Count (BCC): 73
Padding: 00
DCE RPC Bind, Fragment: Single, FragLen: 72, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind (11)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 72
Auth Length: 0
Call ID: 1
Max Xmit Frag: 4280
Max Recv Frag: 4280
Assoc Group: 0x00000000
Num Ctx Items: 1
Context ID: 0
Num Trans Items: 1
Interface UUID: 4b324fc8-1670-01d3-1278-5a47bf6ee188
Interface Ver: 3
Interface Ver Minor: 0
Transfer Syntax: 8a885d04-1ceb-11c9-9fe8-08002b104860
Syntax ver: 2
0040 00 00 00 88 ff 53 4d 42 2f 00 00 00 00 08 .....SMB/.....
0050 01 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
0060 7f 95 00 08 33 62 0e ff 00 00 00 00 40 00 00 00 ....3b......@...
0070 00 ff ff ff ff 08 00 48 00 00 00 48 00 40 00 00 .......H...H.@..
0080 00 00 00 49 00 00 05 00 0b 03 10 00 00 00 48 00 ...I..........H.
0090 00 00 01 00 00 00 b8 10 b8 10 00 00 00 00 01 00 ................
00a0 00 00 00 00 01 00 c8 4f 32 4b 70 16 d3 01 12 78 .......O2Kp....x
00b0 5a 47 bf 6e e1 88 03 00 00 00 04 5d 88 8a eb 1c ZG.n.......]....
00c0 c9 11 9f e8 08 00 2b 10 48 60 02 00 00 00 ......+.H`....
Transmission Control Protocol, Src Port: 445 (445), Dst Port: 37665 (37665), Len: 51
NetBIOS Session Service
Message Type: Session message
Length: 47
SMB (Server Message Block Protocol)
SMB Header
Server Component: SMB
Response to: 1
Time from request: 0.000601000 seconds
SMB Command: Write AndX (0x2f)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x88
1... .... = Request/Response: Message is a response to the client/redirector
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc001
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only
...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs
.... 0... .... .... = Extended Security Negotiation: Extended security negotiation is not supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .0.. = Security Signatures: Security signatures are not supported
.... .... .... ..0. = Extended Attributes: Extended attributes are not supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Process ID High: 0
Signature: 0000000000000000
Reserved: 0000
Tree ID: 2048
Process ID: 38271
User ID: 2048
Multiplex ID: 25139
Write AndX Response (0x2f)
Word Count (WCT): 6
AndXCommand: No further commands (0xff)
Reserved: 00
AndXOffset: 47
FID: 0x4000
Count Low: 72
Remaining: 65535
Count High (multiply with 64K): 0
Reserved: 0000
Byte Count (BCC): 0
0040 00 00 00 2f ff 53 4d 42 2f 00 00 00 00 88 .../.SMB/.....
0050 01 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
0060 7f 95 00 08 33 62 06 ff 00 2f 00 48 00 ff ff 00 ....3b.../.H....
0070 00 00 00 00 00 .....
--------------------------------------------------------------------------
对于139/TCP来说,TCP数据区前4字节算是NBT层的。对于445/TCP来说,TCP数据区前
4字节不算是NBT层的,直接交给SMB层的代码处理了,但在旁路解码处理时,不必关
心这些细节,方便起见,仍称这4字节为NBT层数据。
对比SMB_37_2.cap与SMB_37_4.cap中NBT层的解码,后者已经没有了Flags字段,而
Length字段由17-bits扩展到24-bits。
Write AndX(0x2f)承载的RPC层仍占72字节,与前面两小节相比没有任何区别,作为
承载者的SMB层本身却发生重大变化。SMB Command变成Write AndX(0x2f),对SMB层
的解码也就变了,Data Offset字段本身在TCP数据区的偏移变成59。Data Length等
于72,正好是RPC层的大小,RPC层是做为SMB层数据区出现的!
至此已经很清晰地感受到协议分层处理这个事实。在讨论DCE/MS RPC时,应将SMB层
看作与TCP层一样的传输层,RPC层可以在这些传输层中选择一个作为承载者。至于传
输层内部如何实现,不关RPC层的事。
用协议分析工具时可以先过滤出Write AndX(0x2f),再直接假设RPC层在TCP数据区的
偏移是+0x044,进而针对RPC层各字段进行过滤。
与前面两小节相比,另一个重要变化是Bind_ack(12)报文并未随Write AndX(0x2f)的
响应报文出现,此时必须显式调用Read AndX(0x2e)读取Bind_ack(12):
--------------------------------------------------------------------------
Transmission Control Protocol, Src Port: 37665 (37665), Dst Port: 445 (445), Len: 63
NetBIOS Session Service
Message Type: Session message
Length: 59
SMB (Server Message Block Protocol)
SMB Header
Server Component: SMB
Response in: 4
SMB Command: Read AndX (0x2e)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x08
0... .... = Request/Response: Message is a request to the server
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc001
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only
...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs
.... 0... .... .... = Extended Security Negotiation: Extended security negotiation is not supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .0.. = Security Signatures: Security signatures are not supported
.... .... .... ..0. = Extended Attributes: Extended attributes are not supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Process ID High: 0
Signature: 0000000000000000
Reserved: 0000
Tree ID: 2048
Process ID: 39203
User ID: 2048
Multiplex ID: 46171
Read AndX Request (0x2e)
Word Count (WCT): 12
AndXCommand: No further commands (0xff)
Reserved: 00
AndXOffset: 0
FID: 0x4000
Offset: 0
Max Count Low: 32767
Min Count: 32767
Remaining: 32767
High Offset: 0
Byte Count (BCC): 0
0040 00 00 00 3b ff 53 4d 42 2e 00 00 00 00 08 ...;.SMB......
0050 01 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
0060 23 99 00 08 5b b4 0c ff 00 00 00 00 40 00 00 00 #...[.......@...
0070 00 ff 7f ff 7f ff ff ff ff ff 7f 00 00 00 00 00 ................
0080 00 .
Transmission Control Protocol, Src Port: 445 (445), Dst Port: 37665 (37665), Len: 132
NetBIOS Session Service
Message Type: Session message
Length: 128
SMB (Server Message Block Protocol)
SMB Header
Server Component: SMB
Response to: 3
Time from request: 0.000471000 seconds
SMB Command: Read AndX (0x2e)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x88
1... .... = Request/Response: Message is a response to the client/redirector
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...0 .... = Canonicalized Pathnames: Pathnames are not canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc001
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only
...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs
.... 0... .... .... = Extended Security Negotiation: Extended security negotiation is not supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .0.. = Security Signatures: Security signatures are not supported
.... .... .... ..0. = Extended Attributes: Extended attributes are not supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Process ID High: 0
Signature: 0000000000000000
Reserved: 0000
Tree ID: 2048
Process ID: 39203
User ID: 2048
Multiplex ID: 46171
Read AndX Response (0x2e)
Word Count (WCT): 12
AndXCommand: No further commands (0xff)
Reserved: 00
AndXOffset: 0
FID: 0x4000
Remaining: 0
Data Compaction Mode: 0
Reserved: 0000
Data Length Low: 68
Data Offset: 60
Data Length High (multiply with 64K): 0
Reserved: 000000000000
Byte Count (BCC): 69
Padding: 00
DCE RPC Bind_ack, Fragment: Single, FragLen: 68, Call: 1
Version: 5
Version (minor): 0
Packet type: Bind_ack (12)
Packet Flags: 0x03
0... .... = Object: Not set
.0.. .... = Maybe: Not set
..0. .... = Did Not Execute: Not set
...0 .... = Multiplex: Not set
.... 0... = Reserved: Not set
.... .0.. = Cancel Pending: Not set
.... ..1. = Last Frag: Set
.... ...1 = First Frag: Set
Data Representation: 10000000
Byte order: Little-endian (1)
Character: ASCII (0)
Floating-point: IEEE (0)
Frag Length: 68
Auth Length: 0
Call ID: 1
Max Xmit Frag: 4280
Max Recv Frag: 4280
Assoc Group: 0x00024b67
Scndry Addr len: 13
Scndry Addr: /PIPE/ntsvcs
Num results: 1
Ack result: Acceptance (0)
Transfer Syntax: 8a885d04-1ceb-11c9-9fe8-08002b104860
Syntax ver: 2
0040 00 00 00 80 ff 53 4d 42 2e 00 00 00 00 88 .....SMB......
0050 01 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 08 ................
0060 23 99 00 08 5b b4 0c ff 00 00 00 00 00 00 00 00 #...[...........
0070 00 44 00 3c 00 00 00 00 00 00 00 00 00 00 00 45 .D.<...........E
0080 00 00 05 00 0c 03 10 00 00 00 44 00 00 00 01 00 ..........D.....
0090 00 00 b8 10 b8 10 67 4b 02 00 0d 00 5c 50 49 50 ......gK..../PIP
00a0 45 5c 6e 74 73 76 63 73 00 00 01 00 00 00 00 00 E/ntsvcs........
00b0 00 00 04 5d 88 8a eb 1c c9 11 9f e8 08 00 2b 10 ...]..........+.
00c0 48 60 02 00 00 00 H`....
--------------------------------------------------------------------------
Bind_ack(12)报文随Read AndX(0x2e)的响应报文出现。Data Offset字段本身在TCP
数据区的偏移是49。
用协议分析工具时可以先过滤出Read AndX(0x2e),再直接假设RPC层在TCP数据区的
偏移是+0x040,进而针对RPC层各字段进行过滤。重复提醒,Padding字段长度不固定,
偏移+0x040只是权宜之计,如能动态根据Data Offset字段的值计算偏移最好不过。
前两小节的BIND操作只涉及一来一回两个报文,本小节的BIND操作却涉及四个报文,
麻烦了许多。一般"BIND Over Transaction"都能安全替代"BIND Over Write AndX",
自己写程序实现BIND操作时不必选用后者。但是在协议分析过程中,却有可能同时碰
上二者。
扯远一点。当出现一些DCE/MS RPC类蠕虫时,会有公司或个人提供一些定制后的过滤
规则。从我们前期的短小分析来看,这些过滤规则面临一些难题,或者说因协议分析
工具自身能力不足带来的难题。一是动态端口,这个现在仍不急着讲。二是从协议层
次上精确定位RPC层,我不清楚现有工具中哪个可以识别了SMB Command之后动态定位
Data Offset字段本身在TCP数据区的偏移,动态根据Data Offset字段的值计算RPC层
在TCP数据区的偏移,同时以这个偏移为基准定位其它RPC层的协议字段。更多时候这
些公开发布的过滤规则就像我前面介绍的那样,做了一些重大假设,比如填充域长度
固定,只考虑"BIND Over Write AndX",不考虑"BIND Over Transaction"等等。针对
蠕虫的某一特定实例,做这样的重大假设是可以的,其作者不太可能变态到同时实现
了两种BIND操作,随机挑着用。但我今天这么公开提到了,难说下次蠕虫作者不这样
干。真要出现这样的局面,只好设置多套过滤,逻辑或一下。总有人抱怨过滤规则不
工作,那是因为出现了蠕虫变种、Exploit变种等等,违背了原过滤规则所做的重大
假设。这时应抓取样本报文,自行设置过滤规则。话说回来,协议分析工具做这种事
确实太勉为其难了,交互式分析工具严重依赖于人的参与,这也导致NIDS、NIPS必然
出场。NIDS、NIPS是程序实现的解码分析,灵活得多。
协议分析工具、NIDS、NIPS的相同点是都要做协议分层解码,都要逐层剥离,一旦中
间某层解码失败,作为负载出现的后续层次都将解码失败。DCE/MS RPC由SMB承载时,
首先要对SMB层进行解码才好继续进行后续分析。Ethereal是目前我所用过的协议分
析工具中对SMB层解码最深入的一个,推荐使用。而Samba是目前我所见过的对SMB层
Hacking最深的开源项目,远比Ethereal深入,甚至可以说不在一个层次。即使现在
部份Windows源码泄露,也还是值得研读Samba源码。
协议分层越多,解码越麻烦,也越容易忽略许多例外情形。换句话说,很多工具、程
序只考虑到最常见的情形,多多少少、有意无意做了一些假设,当例外情形出现违背
了这些假设,问题就来了。Ethereal对SMB层解码太深,历史上出现过的问题就很多,
我敢打赌,到现在还有问题。至于Samba么,一样的,在Samba项目的历史上出现过很
多现在也鲜为人知的趣事,这群天才们从无到有Hacking SMB,那还是Windows的早期,
Samba与Windows通信时搞出个BSOD实在是太普通了。要是搁在现在,不成了大漏洞、
大新闻么。当时的环境、氛围与现在太不同,最终多半是安静地通知微软并协助修补
了事。有个叫Luke Kenneth Casson Leighton的人,此人是半路加盟Samba Team的,
也算是天才,很强悍,后来因个人理念冲突与Samba Team分道扬镳,再后来加入ISS
的XForce小组继续从事SMB协议分析。他写过一本书:
<<DCE/RPC OVER SMB - SAMBA AND WINDOWS NT DOMAIN INTERNALS>>
99年出的。因为Ethereal已经得到相当程度的加强,这书搁到现在算不上稀世奇珍了,
但仍可从中找到一些Ethereal至今未做解码的内容,Samba早在99年之前就解码了!
他在该书中提到一件事,NT 4 SP4之前有一个与Auth Length字段相关的BUG,微软成
功地在保持了向后兼容性的前提下修正了BUG,作者称之为"quite a feat"。在该书
中看到多处历史上悄悄修补过的SMB层BUG,叹息啊,没赶上好时光,也没那群天才们
的实力,同时相当佩服微软保持向后兼容性的强悍。
其它协议分析工具对SMB层解码相比Ethereal就太浅了,但同时也少了很多麻烦,比
如Iris这个小不点,当成玩具就可以了,不会擦枪走火的。不要迷信商业版协议分析
软件,一样的,解码越深死得越快,不解码或只简单解码活下来的机会更大。snort、
tcpdump死得不比Ethereal少。ISS的商业版NIDS很强,对SMB层的解码分析能力是我
接触过的同型产品中最强的一个,没办法,人家的XForce小组中就有好几个前Samba
Team的人。但这同时意味着解码风险增加,已经出过几次问题了。想像一下,假设我
知道某竞争对手的产品对SMB层解码很强,就针对性地制造畸型SMB报文,会如何。不
过放心啦,国内的NIDS、NIPS没这水平,想搞它们都没机会。这事有点讽刺,就跟傻
也是一种幸福一样。
SMB_37_5.cap与SMB_37_3.cap类似。发送Bind报文试图绑定不存在的接口UUID,引发
Provider rejection(2)报文。承载者都是SMB,但这次是"BIND Over Write AndX"。
同样这个包不可能在身边的环境中抓到,我用程序发出来的,提供在此仅用于研究。
这一节只起对比作用,结果由技术文章写成八卦话题了,就当灌水吧。
4) "BIND Over ..."扩展
怀疑另外两个SMB命令NT Trans(0xa0)、Trans2(0x32)也可以承载Bind(11),虽然我
在现实环境中尚未抓包观察到,最近也没时间写程序测试,记录于此,仅作备忘。
对此有两份文档([3]、[4])可供参考:
<<NT LAN Manager SMB File Sharing Protocol Extensions>>
3.2 NT Transact SMB
4.5.1 NT Transact
<<Implementing CIFS>>
2.9.4 Transaction SMBs
这三种Transaction命令的差别相当小。如果我写恶意程序,一定会尝试另两种Trans
命令,尽可能地规避IDS嘛。
5) SMB_COM_TRANSACTION2与SMB_COM_NT_TRANSACTION
在上一小节我提到这两个命令,并且怀疑它们亦可用于承载Bind(11)。拖了些日子,
昨天翻看draft-leach-cifs-v1-spec-02.txt([11]),发现原来的简单想象有问题。
参看如下小节:
3.13.1 SMB_COM_TRANSACTION and SMB_COM_TRANSACTION2 Formats
6.2 SMB_COM_TRANSACTION2 Subcommand codes
3.13.2 SMB_COM_NT_TRANSACTION Formats
6.3 SMB_COM_NT_TRANSACTION Subcommand Codes
4.6.1 NT_TRANSACT_IOCTL
SMB_COM_TRANSACTION2(0x32)请求包的格式与SMB_COM_TRANSACTION(0x25)非常像,
但是这次Setup Count由2变成了1。原来的Setup[]对应:
Setup[0] Function: TransactNmPipe (0x0026)
Setup[1] FID: 0x4000
现在的Setup[]对应:
Setup[0] Subcommand:
原来有"Transaction Name: /PIPE/"字段,现在没有这个字段。这实际意味着二者的
编码解码完全不同了,SMB_COM_TRANSACTION2的具体功能与Subcommand紧密相关,无
法承载抽象的Bind(11)。
在cmd中执行start //<ip>/<share>,抓取SMB_37_6.cap:
--------------------------------------------------------------------------
Transmission Control Protocol, Src Port: 3268, Dst Port: 445, Len: 80
NetBIOS Session Service
Message Type: Session message
Length: 76
SMB (Server Message Block Protocol)
SMB Header
Server Component: SMB
Response in: 2
SMB Command: Trans2 (0x32)
NT Status: STATUS_SUCCESS (0x00000000)
Flags: 0x18
0... .... = Request/Response: Message is a request to the server
.0.. .... = Notify: Notify client only on open
..0. .... = Oplocks: OpLock not requested/granted
...1 .... = Canonicalized Pathnames: Pathnames are canonicalized
.... 1... = Case Sensitivity: Path names are caseless
.... ..0. = Receive Buffer Posted: Receive buffer has not been posted
.... ...0 = Lock and Read: Lock&Read, Write&Unlock are not supported
Flags2: 0xc807
1... .... .... .... = Unicode Strings: Strings are Unicode
.1.. .... .... .... = Error Code Type: Error codes are NT error codes
..0. .... .... .... = Execute-only Reads: Don't permit reads if execute-only
...0 .... .... .... = Dfs: Don't resolve pathnames with Dfs
.... 1... .... .... = Extended Security Negotiation: Extended security negotiation is supported
.... .... .0.. .... = Long Names Used: Path names in request are not long file names
.... .... .... .1.. = Security Signatures: Security signatures are supported
.... .... .... ..1. = Extended Attributes: Extended attributes are supported
.... .... .... ...1 = Long Names Allowed: Long file names are allowed in the response
Process ID High: 0
Signature: 0000000000000000
Reserved: 0000
Tree ID: 2052
Process ID: 1576
User ID: 2049
Multiplex ID: 3584
Trans2 Request (0x32)
Word Count (WCT): 15
Total Parameter Count: 8
Total Data Count: 0
Max Parameter Count: 2
Max Data Count: 40
Max Setup Count: 0
Reserved: 00
Flags: 0x0000
.... .