天天看点

SMB协商过程

近日闲来无事,由于前段单位网络配置出现问题导致逻辑环路,使网络瘫痪,虽然后面重新配置后正常,但还是吸取了不少经验,所以对网络流量及数据分析产生兴趣。我单独模拟了一些简单了网络连接过程进行了抓包,但还是有很多疑问,下面是在网络搜到的一篇关于cifs/smb的文章,感觉很不错,分享过来,以备以后所需。

本文,我将向大家解释什么是cifs和smb,它们如何工作和这些协议里一些共同的不安全隐患。

本文将会成为学习微软网络知识的一个有用资源。smb协议是一个在lan中非常通用的协议了。我为

大家提供了一个关于如何操作smb例子的源代码。

你将会学习到在所有smb密码都是加密的情况下,如何使用arp毒药来获得清晰的smb密码(不需要

粗鲁与暴力)。你将会理解smb与netbios之间的关系。你同样会学到什么是微软远程管理协议(rap),

以及如何使用它来扫描远程smb服务器上的共享资源。

本文提供的程序和资料都只有一个教育性的目的。你将用它来做的任何事情与我无关。

--[ 2什么是smb/cifs ?

依照微软的意思,cifs是为客户系统在网络上向服务器请求文件和打印服务的开放跨平台的运行

机制。它是建立在广泛应用于个人电脑和工作站等操作系统的标准服务器消息块(smb)协议。

实际上,smb是一个通过网络在共享文件,设备,命名管道和邮槽之间操作数据的协议。cifs是

smb的一个公共版本。

smb客户端的可用系统:

for microsoft :

windows 95, windows for workgroups 3.x, windows nt,2000 and xp

for linux :

smblient from samba, smbfs for linux

smb服务器:

samba

microsoft windows for workgroups 3.x

microsoft windows 95

microsoft windows nt

the pathworks family of servers from digital

lan manager for os/2,sco,etc

visionfs from sco

totalnet advanced server from syntax

advanced serverfor unix from at&t (ncr?)

lan server for os/2 from ibm.

--[ 3 会话的建立

注意:smb协议已经被发展成为可以运行于dos操作系统,因此字节顺序将会和网络顺序相反。

smb可以运行在tcp/ip,netbeui,decnet和ipx/spx协议之上。如果smb执行于tcp/ip,decnet

或则是netbeui之上,那么netbios名字必须被使用。

我将会在第六章向大家介绍什么是netbios。但是现在,你必须知道netbios名字用来在网络上鉴

别一台计算机。

smb技术的发展开始于八十年代,出现过很多版本的smb协议。但是最通用的(在windows 98,

windows nt,windows 2000 and xp)是nt lm 0.12版本。本文是基于nt lm 0.12版本之上的。

你必须知道一个smb域名是用来鉴别一个smb服务器上的一组资源的(用户,打印机,文件……)。

那么一个客户端是如何与一个服务器建立smb会话的呢?

让我们假设一个这样的环境:一个客户端希望访问一台服务器上的特定资源。

1 - 开始于客户端向服务器请求一个netbios会话。客户端发送它的已编码的netbios名字到smb

服务器(它们在139端口监听连接请求)。服务器接收到netbios名字后回复一个netbios会话数据报给

有效的会话连接。客户端在建立了连接之后才能进入访问。

2 - 客户端发送一个smb negprot请求数据报(negprot是磋商协议“negotiate protocol”的

简写)。客户端列出了它所支持的所有smb协议版本。

3 - 通过磋商之后,客户端进程向服务器发起一个用户或共享的认证。(下一章中我们将会看到

共享认证和用户认证之间的不同)。

这个过程是通过发送sesssetupx(sesssetupx是会话建立和x“session setup and x”的简称)

请求数据报实现的。客户端发送一对登录名/密码或一个简单密码到服务器,然后服务器通过发送一个

sesssetupx应答数据报来允许或拒绝本次连接。

4 - 好了,在客户端完成了磋商和认证之后,它会发送一个tconx数据报并列出它想访问的特定

网络资源的名称,之后服务器会发送一个tconx应答数据报以表示此次连接是否接受或拒绝。

netbios session request

(netbios name)

[client] ---------------------------> [server]

1)

netbios session granted

[client] <-------------------------- [server]

smb negprot request

2)

smb negprot reply

smb sesssetupx request

3)

smb sesssetupx reply

smb tconx request

4)

smb tconx reply

关于每个数据报的详细描述在第六章里有详细的讲解。

--[ 4 - smb的安全等级

在smb中有两种安全模式:

第一种是“共享”级的安全模式。这种安全模式需要一个访问网络上共享资源的密码。用户通过

这个正确的密码来访问网络资源(ipc,磁盘,打印机)。他可以是网络上任何一个知道共享资源服务

器名字的用户。

第二种是“用户”级的安全模式。这是在第一种模式上的增强版。它坚持使用一对登录名/密码来

访问共享资源。所以如果一个用户想访问这种类型的共享资源,就必须同时提供登录名和密码。这种

模式对了解用户如何使用共享资源是很有帮助的。

--[ 5 - 密码

在smb协议中,如果你想进行一次在服务器上的请求认证,你的密码可以以原码或加密后的形式发

送到服务器端。如果服务器支持加密属性,客户端必须发送一个应答信号。在negprot应答数据报中,

服务器会给客户端发送一个密钥。然后,客户端将密码加密并通过sesssetupx请求数据报发送到服务

器端。服务器将会核查密码的有效性,并由此允许或拒绝客户端的访问。

你必须知道一个smb密码(未加密)的最大长度是14位。密钥的长度一般为8位,加密过后的口令长

度为24位。在ansi密码中,密码中的所有位都转换成大写的形式然后再加密。

密码是以dec编码方式进行加密的。

--[ 6 - 几种smb数据报的描述

这一部分,我将会对smb协议中涉及到的大多数重要的数据报类型进行分析。我知道这或许很烦,

不过这是了解smb的工作机制和进行攻击的基础。我将会解释什么是数据报中最重要的类型。每种命

令都对应两种数据报类型,请求数据报和应答数据报。

----[ 6.1 - smb数据报的常规特征

通常情况下,smb运行于tcp/ip协议组之上。那么我们就假设smb运行在tcp层之上。在tcp层上面,

你常常会发现netbios(nbt)头部。在nbt上面,有smb基础报文头部。在smb基础报文头部之上,就是

另一种依赖于特定请求命令的头部。

----------------------

│ tcp header │

│ netbios header │

│ smb base header │

│ smb command header │

│ data │

“smb base header”包含了几种信息,像接收缓冲区的长度,允许的最大连接数目……它也包

含了一个鉴别请求命令的数字。

“smb command header”包含了所有的请求命令的参数(像磋商协议版本命令……)。

“data”容纳了请求命令的数据。

我们把“smb packet”看成:netbios header + smb base header + smb command header

+ data。

注意:我将使用这个定义:

typedef unsigned char uchar; // 8 unsigned bits

typedef unsigned short ushort; // 16 unsigned bits

typedef unsigned long ulong; // 32 unsigned bits

而string被定义为以空字符结束的ascii字符串。

----[ 6.2 - netbios与smb

netbios(network basic input and output system)在微软的网络系统中被广泛使用。它是

一个软件接口和命名系统。每台主机都有一个长度为15个字符的netbios名字,且第十六个字符用来

标志主机的类型(域名服务器,工作站……)。

第十六个字符的选择:

0x00 基础电脑,工作站。

0x20 资源共享服务器。

这还有一些其他的值可选,不过我们对这两个最感兴趣。第一个(0x00)鉴定一台工作站,第二个

(0x20)鉴定服务器。

在一个smb数据报中,netbios头部对应netbios会话头部。

定义如下:

uchar type; // type of the packet

uchar flags; // flags

ushort length; // count of data bytes (netbios header not included)

“flags”域的值总是被置为0。

“type”域有几种可能的选择:

0x81 对应一个netbios会话请求。这个代码在客户端发送它的netbios名字到服务器是使用。

0x82 对应一个netbios会话应答。这个代码在服务器向客户端批准netbios会话时使用。

0x00 对应一个会话消息。这个代码总是在smb会话中被使用。

“length”域包含了数据字节的长度(netbios头部没有被包含在内)。数据包含在netbios头部

以上的所有部分(它可能是 smb base header + smb command header + data 或 netbios名字)。

netbios名字与编码。

netbios编码名字的长度为32字节。

netbios名字总是以大写的形式存在的。

编码一个netbios名字非常的简单。例如我的计算机的netbios名字是“bill”,它是一个工作

站,所以它的第十六个字符为“0x00”。

首先,如果一个netbios名字比15字节短,就会在右边补填上空格。

“bill “

十六进制为: 0x42 0x49 0x4c 0x4c 0x20 0x20 ......0x00

每个字节都分裂为4位一组:

0x4 0x2 0x4 0x9 0x4 0xc 0x4 0xc 0x2 0x0 .......

而且每个4位都要添加ascii码‘a’的值(0x41)。

0x4 + 0x41 = 0x45 -> ascii value = e

0x2 + 0x41 = 0x43 -> ascii value = c

……

最后netbios名字被编码为32字节长。

注意:

smb可以直接运行于tcp之上而无须nbt(在windows 2k和xp上它们使用455端口)。此时,

netbios名字没有被限制在15字符以内。

----[ 6.3 - smb的基础报文头部

这个头部在所有的smb数据报中都会使用,以下是它的定义:

uchar protocol[4]; // contains 0xff,'smb'

uchar command; // command code

union {

struct {

uchar errorclass; // error class

uchar reserved; // reserved for future use

ushort error; // error code

} doserror;

ulong status; // 32-bit error code

} status;

ushort flags2; // more flags

ushort pad[6]; // ensure section is 12 bytes long

ushort pidhigh; // high part of pid

ulong unused; // not used

ulong unused2;

} extra;

};

ushort tid; // tree identifier

ushort pid; // caller's process id

ushort uid; // unauthenticated user id

ushort mid; // multiplex id

uchar wordcount; // count of parameter words

ushort parameterwords[ wordcount ]; // the parameter words

ushort bytecount; // count of bytes

uchar buffer[ bytecount ]; // the bytes

“protocol”域包含协议(smb)的名字,前面放了一个0xff。

“command”域包含请求命令的数据。例如0x72就是“磋商协议”命令。

“tid”域在客户端成功和一台smb服务器上的资源建立连接后被使用的。tid数字用来鉴别资源。

“pid”域在客户端成功在服务器上创建一个进程是使用。pid数字用来鉴别进程。

“uid”域在一个用户被成功通过验证后被使用。uid数字用来鉴别用户。

“mid”域在客户端拥有几个请求(进程,线程,文件访问……)是和pid同时使用。

“flags”域也很重要,如果第15位置1,则使用unicode编码。

----[ 6.4 - 重要smb命令的描述

smb 磋商协议(negprot)

磋商协议在smb会话建立连接的第一步时使用。

在smb基础报文头部中的“command”域被填充为:0x72。

下面是negprot请求与应答数据报的定义:

request header

uchar wordcount; //count of parameter words = 0

ushort bytecount; //count of data bytes

uchar bufferformat; //0x02 -- dialect

uchar dialectname[]; //ascii null-terminated string

} dialects[];

这个数据报包括客户端向服务器发送的它所支持smb协议的所有版本信息。

有三件事要说,在这个报文中:

“wordcount”域总是被置为零;

“bytecount”域等于结构“dialects”的长度;

“bufferformat”域总是等于0x02。

“dialectname”包含smb协议支持的几种版本信息。

应答数据报头部:

uchar wordcount; count of parameter words = 17

ushort dialectindex; index of selected dialect

uchar securitymode; security mode:

bit 0: 0 = share, 1 = user

bit 1: 1 = encrypt passwords

ushort maxmpxcount; max pending multiplexed requests

ushort maxnumbervcs; max vcs between client and server

ulong maxbuffersize; max transmit buffer size

ulong maxrawsize; maximum raw buffer size

ulong sessionkey; unique token identifying this session

ulong capabilities; server capabilities

ulong systemtimelow; system (utc) time of the server (low).

ulong systemtimehigh; system (utc) time of the server (high).

ushort servertimezone; time zone of server (min from utc)

uchar encryptionkeylength; length of encryption key.

ushort bytecount; count of data bytes

uchar encryptionkey[]; the challenge encryption key

uchar oemdomainname[]; the name of the domain (in oem chars)

这个数据报由服务器发出,它包含smb协议支持的版本列表,服务器的smb域名,如果需要还要

包含密钥。

重要的:

第一个感兴趣的域是“securitymode”位。如果第0位被选中,那么我们就选择了用户安全模式;

如果没有,则拥有共享安全模式。如果第1位被选中,密码就使用dec加密算法进行编码。

“sessionkey”域被用来鉴别会话。一个会话有单一的一个会话钥匙。

“capabilities”域表明服务器是否支持unicode字符串,或nt lm 0.12特别的命令……

数据被放在报文头部的结束处。通过一个negprot应答,这些数据与“encryptionkey”和

“oemdomainname”相对应。

“oemdomainname”域的长度等于(bytecount - encryptoinkeylength)。

“oemdomainname”字符串包含服务器的smb域名。

sesssetupx(session setup and x)

sesssetupx数据报被用来处理用户鉴别,或在你访问资源时提供一个密码。

sesssetupx的命令代码是:0x73。

请求数据报头部:

uchar wordcount; count of parameter words = 13

uchar andxcommand; secondary (x) command; 0xff = none

uchar andxreserved; reserved (must be 0)

ushort andxoffset; offset to next command wordcount

ushort maxbuffersize; client's maximum buffer size

ushort maxmpxcount; actual maximum multiplexed pending requests

ushort vcnumber; 0=first (only),nonzero=additional vc number

ulong sessionkey; session key (valid iff vcnumber != 0)

ushort caseinsensitivepasswordlength; account password size, ansi

ushort casesensitivepasswordlength; account password size, unicode

ulong reserved; must be 0

ulong capabilities; client capabilities

ushort bytecount; count of data bytes; min = 0

uchar caseinsensitivepassword[]; account password, ansi

uchar casesensitivepassword[]; account password, unicode

string accountname[]; account name, unicode

string primarydomain[]; client's primary domain, unicode

string nativeos[]; client's native operating system, unicode

string nativelanman[]; client's native lan manager type, unicode

这个报文提供很多关于客户端系统的信息。

“maxbuffersize”域非常的重要,它提供客户端可以接收数据报的最大长度。如果你将这个域

设置为零,那么你不会接收到任何类型的数据。

这个数据报内,有几个字符串。最总要的是“casesensitivepassword”(unicode编码的密码)

域和“caseinsensitivepassword”(ansi编码的密码)域。

这两个域中的一个被使用,它取决于服务器是否支持unicode编码(在磋商协议应答报文中描述)。

密码的长度保存在“caseinsesitivepasswordlength”或“casesensitivepasswordlength”里。

其他字符串,请参见它后面的描述。数据的长度保存在“bytecount”域中。

uchar wordcount; count of parameter words = 3

ushort action; request mode: bit0 = logged in as guest

string nativeos[]; server's native operating system

string nativelanman[]; server's native lan manager type

string primarydomain[]; server's primary domain

在这个数据报文里也包含了很多信息:操作系统类型,smb服务器版本信息和服务器的域名。

如果连接失败,那么在 nativeos, nativelanman

and primarydomain 里面将没有任何东西。

我们已经讲完了“硬件”部分,下面我们来看看smb协议。

----[ 6.5 我们如何才能将本应该加密的smb密码清楚的还原 ?

在会话的建立过程中,密码是在sesssetupx阶段被发送到服务器的。而smb negprot应答报文包

含了一个“securitymode”域,它判断是否允许使用加密属性。

如果你想在所有的密码都被加密后获得一个清晰的密码,你可能会面对两种情况。

第一种情况是得到密钥和加密过的口令,然后暴力破解。它会花费你很多的时间……

一些程序如 lophtcrack (附smbgrinder),dsniff or readsmb2 会嗅探到smb加密过的密码。

第二种方法是劫持连接,并使客户端确信密码不用加密后传送。

这种技术解释起来有点复杂,不过我会告诉你如何才能实现 !

如果服务器配置成需要加密的密码,那么smb negprot应答数据报就会选种“securitymode”的

第1位。但是,如果攻击者在服务器之前发送了一个negprot应答数据报,且相应的第一位被置为零就

可以了,这样密码就会以明文的形式出现在sesssetupx请求报文。

negprot request

[client] ----------------------------------> [server]

[ attacker ]

(攻击者等待一个negprot请求数据报)

[client] <-------------│ [server]

│ fake negprot reply

(攻击者发送一个虚假的neprot应答数据报)

real negprot reply

[client] <---------------------------------- [server]

[attacker (什么都不做)]

sessetupx request with the password in clear text

(攻击者嗅探到明文形式的密码)

以上的图表明了在网络上进行一次直接数据报注射过程。大多数情况下,这种方法并不会发生,

因为虚假的negprot应答数据报会被处理。还有一个问题就是会话特性,有效的密码它不会在交换环

境中工作……

我们可以使用arp毒药(arp-poisoning)来避免上面的所有问题。

我不会解释或描述什么是arp毒药,你可以在互连网上找到很多这方面的文章。但是如果你不知道

这是什么,你只须知道这种攻击允许攻击者在客户端和服务器之间进行重定向并修改网络通信。

如果你考虑到这种情形,攻击者就在他们之间。

这就是man in the middle……

----[ 6.6 - man in the middle 攻击

“attack where your enemy is not expecting you“

sun tzu, 《 the art of war 》

现在我就要为大家描述什么是 man in the middle 攻击。这种攻击允许你回避交换机,可以避

免连接失败,进而获得密码的明文表达式。

现在我们认为客户端和服务器之间的通信被攻击者重定向了(由于arp毒药)。客户端向服务器请

求一个smb会话,它会向服务器的139端口发送一个数据报。这时攻击者接收到了这个数据报,但是攻

击者并没有将这个数据报重新发送到服务器。

所有接收到的发送给服务器smb端口的数据报(现在发送到了攻击者的主机了)被重新定向到攻击者

主机的本地端口1139(使用nat或iptables非常容易实现)。在攻击者的本地端口1139,有一个程序(一

个透明的代理程序)进行修改并重定向smb数据报。

iptables/nat的命令如下:

将接收到的数据报(139端口)重定向到本地端口(例如1139)。

#iptables -t nat -a prerouting -i eth0 -p tcp -s 192.168.1.3 --dport 139 -j redirect --to-port 1139

192.168.1.3是客户端的ip地址。

重定向所有的网络通信:

#iptables -t nat -a postrouting -o eth0 -j masquerade

需要做哪些修改呢?

攻击者修改negprot应答数据报使密码以明文的形式传送,攻击者同样要修复密钥。他将密钥的长

度设置为零,并将域名代替密钥。攻击者将“securitymode”位设置为零。这样,密码就不会被加密了。

此后,客户端将会在sesssetupx请求数据报中把密码以明文的的方式传送。在攻击者获得了密码

后,他会在把sesssetupx请求数据报发送给服务器之前用密钥将密码加密。

服务器发送一个sesssetupx应答报文以接受或拒绝会话。攻击者重定向sesssetupx应答报文和

以后的所有网络通信。

会话连接不会失败,而且没有人知道我们的 man in the middle !

描述:

arp-p arp-p

[client] <--------- [attacker] ---------> [server]

攻击者使用arp毒药攻击,进而在两台主机之间重定性所有的网络数据报。

[client] <---------> [attacker] <---------> [server]

网络传输的重定向依靠nat或iptables来实现。

port 139

[client] -----------------> [attacker] [server]

攻击者接收到第一个发送给smb服务器的数据报。

[client] ----------------->[attacker 139] [server]

v

[attacker 1139]

攻击者将它重定向到1139端口。在1139端口上,我们的代理程序正在监听。

攻击者接收到了negprot请求数据报。

[client] [attacker] -------------------> [server]

攻击者重定向negprot请求数据报到服务器。

negprot reply

[client] [attacker] <---------------------------- [server]

(加密属性位设置为要求对密码进行加密)

服务器发送了一个将加密属性设置为1的negprot应答数据报,要求客户端对密码进行加密传送。

攻击者并不会重定向发送这个数据报。他改变了要求加密的那一位,而告诉客户端不用对口令进行加

密。

[client] <----------------------------- [attacker] [server]

(加密属性位被设置为无须加密口令 )

攻击者将修改过的无须加密口令的negprot应答报文发送到客户端。

sesssetupx request

[client] ------------------------> [attacker] [server]

(密码以明文形式传送)

客户端将密码以明文形式传送,这是攻击者得到了服务器的密码了 !

[client] [attacker] ---------------------> [server]

(密码被加密过后传送)

攻击者将密码加密后通过sesssetupx请求数据报发送到服务器。

sesssetupx reply

[client] <------------- [attacker] <---------------- [server]

服务器发送sesssetupx应答报文,攻击者只是将它重定向到客户端。

[client] <------------> [attacker] <--------------> [server]

攻击者继续在服务器与客户端之间重定向数据报,直到smb会话结束。

----[ 6.7 - 注意windows 2k/xp里基于tcp的smb操作

就想我先前说的,在windows 2k/xp中smb可以直接运行于tcp之上。smb服务器在445端口上监听

所有的连接。但是这并不是如此的“直接”,实际上,我们使用一个4字节长的数据代替了netbios头部。

│---------------│

│ tcp │

│special header │

│ smb base hdr │

特殊头部的定义如下:

uchar zero; // set to zero

uchar length[3]; // count of data bytes

// the 4 bytes of the header are not included

这个特别的头部和netbios头部并没有太大的区别,下面你就会知道为什么了。

下面是netbios头部:

在smb运行于tcp之上时,netbios请求会话就不再需要了。

实际上,客户端和服务器的netbios名字并不需要发送。所以,在netbios里的“type”域总是等

于零(如果“type”域不等于零,在客户端发送它的netbios的编码后的名字时这个域被置为0x81,如

果是服务器就填入0x82)。记住,在smb的会话期间,“type”域始终等于零。

第一个字节完全相同。

最后三个字节:

netbios头部的“flags”域始终置为零。只有数据报的长度会占据最后的两个字节。

我们可以得出这个结论:在netbios没有使用时,netbios头部和特殊头部没有什么区别。

downgrade 攻击:

如果客户端(运行于windows 2k 或 xp之上)使用了nbt,它在连接时总是同时使用139和445端口。

如果客户端在445端口接收到一个应答报文,客户端就会在139端口发送一个rst数据报。如果客户端在

445端口没有接收到应答报文,他会试图使用139端口进行连接。如果在两个端口都没有回应,那么这

次会话就算失败了。

如果客户端没有使用nbt,它仅在445端口上进行连接。为了完成 downgrade 攻击,强迫客户端

不使用445端口而使用139端口,你必须是客户端确信445端口是关闭的。在使用透明代理攻击的情况下

是非常容易实现的。在使用iptables的情况下,只须在攻击者的主机上将接收的所有网络数据报从445

端口重定向到其他的端口。这样客户端就会使用139端口了。

以上假设是基于客户端使用了nbt的。

如果客户端没有使用,那么透明代理就会在445端口上进行数据报的流通。

好的,我们已经完成了还原密码的攻击了。现在我们要学习smb的另一个重要部分。

--[ 7 - 事物处理子协议与rap命令

在这部分我会解释一些smb的命令:rap命令。这些命令使用事物处理子协议。我同样会描述这些

子协议。

----[ 7.1 事物处理子协议

在大量的数据通过smb会话传送时,或则有一个特别的操作请求,那么smb协议就会包含一个事物

处理子协议。

事物处理子协议主要用在smb远程过程调用(rpc):rap命令(rap是remote administration

protocal),我将会在稍后解释。

事物处理子协议并不是来源与smb协议。它只是为smb提供的另外一个命令。所以事物处理子协议

是基于smb基础报文头部的,它的命令代码是0x25。

像其他命令一样有发送和请求报文。

以下是事物处理请求报文头部:

uchar wordcount; count of parameter words; value =

(14 + value of the “setupcount“ field)

ushort totalparametercount; total parameter bytes being sent

ushort totaldatacount; total data bytes being sent

ushort maxparametercount; max parameter bytes to return

ushort maxdatacount; max data bytes to return

uchar maxsetupcount; max setup words to return

uchar reserved;

ushort flags; additional information:

bit 0 - also disconnect tid in tid

bit 1 - one-way transaction (no response)

ulong timeout;

ushort reserved2;

ushort parametercount; parameter bytes sent this buffer

ushort parameteroffset; offset (from header start) to parameters

ushort datacount; data bytes sent this buffer

ushort dataoffset; offset (from header start) to data

uchar setupcount; count of setup words

uchar reserved3; reserved (pad above to word)

ushort setup[setupcount]; setup words (# = setupwordcount)

string name[]; name of transaction

(null if smb_com_transaction2)

uchar pad[]; pad to short or long

uchar parameters uchar pad1[]; pad to short or long

uchar data[ datacount ]; data bytes (# = datacount)

在大多数情况下,一个rap命令通过事物处理子协议来发送时都需要几个事物处理数据报来发送参

数和数据。参数字节通常首先发送,数据字节紧跟在后。如果几个事物处理数据报必须相关联时,服

务器会送下面的这个小的数据报:

中间应答报文 :

uchar wordcount; count of parameter words = 0

ushort bytecount; count of data bytes = 0

在事物处理请求报文头部,“totalparametercount”域描述发送的参数字节的长度,在

“totaldatacount”域中也是这样的(发送的数据数目)。

从smb基础报文头部的开始到参数字符的偏移量保存在“parameteroffset”里,而数据字符的

偏移量保存在“dataoffset”域里。

“parameter”域包含参数字符,而“data”域则包含数据字符。

在“datacount”域和“parametercount”域里分别保存了事物处理数据报里的数据字节和参数

字节的长度。

注意一下“wordcount”域,它包含了下面的值:14 + “setupcount”域的值。但通常情况下,

“setupcount”域都等于零。

发送的请求数据报和应答数据报之间并没有太多的差别。

事物处理应答报文:

uchar wordcount; count of data bytes; value = 10 +

“setupcount“ field.

ushort reserved;

ushort parameterdisplacement; displacement of these parameter bytes

ushort datadisplacement; displacement of these data bytes

uchar reserved2; reserved (pad above to word)

ushort setup[setupwordcount]; setup words (# = setupwordcount)

uchar data[datacount]; data bytes (# = datacount)

客户端必须使用“parameteroffset”和“dataoffset”以了解参数和数据字节的偏移量(从smb

基础报文头部开始)。

----[ 7.2 - rap命令

rap(remote administation protocal)是smb的rpc实现。

rap 请求报文 :

│---------------------------│

│tcp hdr │

│netbios hdr │

│smb base hdr │

│smb transaction request hdr│

│rap request parameters │

│rap request datas │

rap 应答报文 :

│smb transaction reply hdr │

│rap reply parameters │

│rap reply datas │

在你使用rap命令时,你总会在事物处理(请求和应答)的“name”域中找到“/pipe/lanman”

字符串。

这有几个rap命令的例子:

- netshareenum : 获得服务器上所有共享资源的信息;

- netserverenum2 : 列举特定域里所有计算机的特定类型;

- netservergetinfo : 获得指定服务器的信息;

- netsharegetinfo : 获得特定共享资源的信息;

- netwkstauserlogon : 在smb服务器上进行一次登录;

- netwstauserlogoff : 注销;

- netusergetinfo : 获得指定用户的信息;

- netwkstagetinfo : 获得指定工作站的信息;

- samoemchangepassword : 更改远程smb服务器上一个用户的密码。

我不会列举所有的命令,而只是举一个例子。

--[ 8 - 使用rap命令列出服务器上所有可得的共享列表

这部分是上面的补充。我将会演示一个如何使用rap命令的例子。

我们如何才能获得网络上的每人都可访问的smb共享资源:

其实过程很简单。客户端必须在服务器上通过认证。这些在第三章里都有讲解。在服务器通过验

证后,客户端发送一个tconx请求数据报给服务器(在接收到sesssetupx应答数据报之后)。

tconx 的意思是 tree connect and x。

tconx请求数据报用来访问一个共享资源。

----[ 8.1 - tconx数据报

tconx数据报是建立在smb基础报文头部之上的,命令代码为0x75。

uchar wordcount; count of parameter words = 4

ushort flags; additional information

ushort passwordlength; length of password[]

ushort bytecount; count of data bytes; min = 3

uchar password[]; password

string path[]; server name and share name

string service[]; service name

密码在会话建立过程中被发送到了服务器。如果密码的长度为1,则密码就被置为空(0x00)。

“path”域包含了你想要访问的共享资源的名字。它使用unicode编码。如过我想访问一台

“myserver”服务器上的“myshare”资源,“path”字符串就该置为“//myserver/myshare”。

“service”包含了请求资源的类型:

stringtype of ressource

“a:” 磁盘共享.

“lpt1:” 打印机.

“ipc” 命名管道.

“comm” 通信设备.

“?????” 任何设备类型.

如果你要扫描设备的类型,你必须在“service”域里使用“?????”。

在你发送了一个tconx请求数据报到服务器后,它会给你发送一个tconx的应答报文。你还必须

修复“tid”域(在smb基础报文头部),因为它是rap命令里的事物处理请求。你还要告诉服务器你想

获得那些你有权得到的资源名字。当然,你可以通过“netshareenum”命令来获得它们。

----[ 8.2 - rap命令“netshareenum”的解释

我们将要学习rap命令里的“netshareenum”。

rap命令中的“netshareenum”请求:

函数netshareenum的16位代码: 0;

参数描述符: “wrlen”;

返回的数据描述符: “b13bwz”;

一个16位的值为0x01的整数;

一个16位整数包含的获得数据的缓冲区长度;

在这个请求数据报中不需要任何数据,所以“datacount”域和“totaldatacount”域都置零。

│--------------------------------------------│

│ netbios hdr │---------> 4 bytes

│ smb base hdr │---------> 32 bytes

│ smb transaction request hdr │

事物处理请求的“parameters”域获得rap请求命令的参数:

│--------------│

│ 0x0000 │ ----------------------------------------> a

│--------------│--------------│--------------│

│ w r │ l e │ h 0x00│-----------> b

│--------------│--------------│--------------│-------│

│ b 1 │ 3 b │ w z │ 0x00 │---> c

│ 0x0001 │ 0xffff │--------------------------> d

│--------------│--------------│

a: netshareenum函数代码: 0x00

b: 参数描述符

c: 数据描述符

d: 0x01(已定义值)和0xffff(获取数据报的最大长度)

服务器的应答:

“parameters”域接收到事物处理应答报文头部信息:

一个16位整数包含了返回的状态值:

成功 0

拒绝访问 5

拒绝访问网络 65

更多数据 234

服务器已关闭 2114

事物处理配置错误 2141

一个16位的“转换字”,用来计算备注信息的偏移量。

一个16位获得返回的条目数 = 返回share_info数据结构的数目。

一个16位获得可利用的条目数。

在事物处理应答报文的“data”域中包含了几组share_info的数据结构。

share_info数据结构包含了可利用资源的信息,定义如下:

struct share_info {

char shi1_netname[13]; /*name of the ressource*/

char shi1_pad; /*pad to a word*/

unsigned short shi1_type; /*code specifies the type of the shared resssource :

0 disk directory tree

1 printer queue

2 communications device

3 ipc*/

char *shi1_remark; /*remark on the specified ressource*/

}

shi1_remark是一个32位的字符传指针。它包含了相应资源的备注信息。你必须取出它的后16位

到“converter word”域中,以知道这个备注字符串和rap应答报文参数头部之间的偏移量。

实际上以ascii编码是:

│ netbios hdr │------------> 4 bytes

│ smb base hdr │------------> 32 bytes

│ smb trans reply hdr │

事物处理应答头部的“parameters”域定义:

(对应于netshareenum函数返回的参数)

│ status code │-------------> 2 bytes

│ converted word │-------------> 2 bytes

│ number of entries returned │-------------> 2 bytes

│ number of entries available │-------------> 2 bytes

事物处理应答报文的数据部分:

(对应于多个share_info数据结构)

│ shi1_netname │-----------> 13 bytes

│ shi1_pad to pad to word │-----------> 1 byte

│ type of service │-----------> 2 bytes

│ pointer to remark string │-----------> 4 bytes

.

其他的share_info数据结构

│ remark string 1 │

│ another remarks strings │

--[ 9 - 结论

我希望你能在这篇文章中学到些东西。如果你有任何意见,问题,请与我联系:

--[ 10 - 参考

[1] "a common internet file system (cifs/1.0) protocol

preliminary draft", paul j.leach and dilip c. naik

http://www.snia.org/tech_activities/cifs/cifs-tr-1p00_final.pdf

[2] "cifs remote administration protocol preliminary draft"

paul j.leach and dilip c. naik

http://us6.samba.org/samba/ftp/specs/cifsrap2.txt

[3] rfc 1001

http://www.faqs.org/rfcs/rfc1001.html

[4] rfc 1002

http://www.faqs.org/rfcs/rfc1002.html

继续阅读