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
[client] ---------------------------> [server]
2)
SMB negprot reply
[client] <-------------------------- [server]


SMB sesssetupX request
[client] ---------------------------> [server]
3)
SMB sesssetupX reply
[client] <-------------------------- [server]


SMB TconX request
[client] ---------------------------> [server]
4)
SMB TconX reply
[client] <-------------------------- [server]


關於每個數據報的詳細描述在第六章裏有詳細的講解。


--[ 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;
UCHAR Flags; // Flags
USHORT Flags2; // More flags
union {
USHORT Pad[6]; // Ensure section is 12 bytes long
struct {
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
struct {
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
UCHAR AndXCommand; Secondary (X) command; 0xFF = none
UCHAR AndXReserved; Reserved (must be 0)
USHORT AndXOffset; Offset to next command WordCount
USHORT Action; Request mode: bit0 = logged in as GUEST
USHORT ByteCount; Count of data bytes
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

[ attacker ]
(***者發送一個虛假的neprot應答數據報)


real negprot reply
[client] <---------------------------------- [server]


[attacker (什麼都不做)]


sessetupX request with the password in clear text
[client] ----------------------------------> [server]

(***者嗅探到明文形式的密碼)

以上的圖表明瞭在網絡上進行一次直接數據報注射過程。大多數情況下,這種方法並不會發生,
因爲虛假的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 request
[client] -----------------> [attacker] [server]

***者接收到了negprot請求數據報。

negprot request
[client] [attacker] -------------------> [server]

***者重定向negprot請求數據報到服務器。

negprot reply
[client] [attacker] <---------------------------- [server]
(加密屬性位設置爲要求對密碼進行加密)

服務器發送了一個將加密屬性設置爲1的negprot應答數據報,要求客戶端對密碼進行加密傳送。
***者並不會重定向發送這個數據報。他改變了要求加密的那一位,而告訴客戶端不用對口令進行加
密。


negprot reply
[client] <----------------------------- [attacker] [server]
(加密屬性位被設置爲無須加密口令 )

***者將修改過的無須加密口令的negprot應答報文發送到客戶端。

SesssetupX request
[client] ------------------------> [attacker] [server]
(密碼以明文形式傳送)

客戶端將密碼以明文形式傳送,這是***者得到了服務器的密碼了 !

SesssetupX request
[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頭部:

UCHAR Type; // Type of the packet
UCHAR Flags; // Flags
USHORT Length; // Count of data bytes (netbios header not included)

在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)
USHORT ByteCount; Count of data bytes
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 TotalParameterCount; Total parameter bytes being sent
USHORT TotalDataCount; Total data bytes being sent
USHORT Reserved;
USHORT ParameterCount; Parameter bytes sent this buffer
USHORT ParameterOffset; Offset (from header start) to Parameters
USHORT ParameterDisplacement; Displacement of these Parameter bytes
USHORT DataCount; Data bytes sent this buffer
USHORT DataOffset; Offset (from header start) to data
USHORT DataDisplacement; Displacement of these data bytes
UCHAR SetupCount; Count of setup words
UCHAR Reserved2; Reserved (pad above to word)
USHORT Setup[SetupWordCount]; Setup words (# = SetupWordCount)
USHORT ByteCount; Count of data bytes
UCHAR Pad[]; Pad to SHORT or LONG
UCHAR Parameters UCHAR Pad1[]; Pad to SHORT or LONG
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 應答報文 :

│---------------------------│
│TCP HDR │
│---------------------------│
│NETBIOS HDR │
│---------------------------│
│SMB BASE HDR │
│---------------------------│
│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
UCHAR AndXCommand; Secondary (X) command; 0xFF = none
UCHAR AndXReserved; Reserved (must be 0)
USHORT AndXOffset; Offset to next command WordCount
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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章