SMB協議詳解

在南京看海發表於2016-11-23

一、概述

    SMB(ServerMessage Block)通訊協議是微軟(Microsoft)和英特爾(Intel)在1987年制定的協議,主要是作為Microsoft網路的通訊協議。SMB 是在會話層(session layer)和表示層(presentation layer)以及小部分應用層(application layer)的協議。SMB使用了NetBIOS的應用程式介面 (Application Program Interface,簡稱API),一般埠使用為139,445。另外,它是一個開放性的協議,允許了協議擴充套件——使得它變得更大而且複雜;大約有65個最上層的作業,而每個作業都超過120個函式,甚至Windows NT也沒有全部支援到,最近微軟又把 SMB 改名為 CIFS(CommonInternet File System),並且加入了許多新的特色。

   

二、協議分析

    SMB包頭部分,分佈如下:

   

    SMB Header的長度為32位元組:

    typedef unsigned charUCHAR;        

    typedef unsigned shortUSHORT;       

    typedef unsigned longULONG;       

 

    typedef struct {

       ULONG LowPart;

    LONG HighPart;

    } LARGE_INTEGER;                    

 

    typedef struct  {

       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 {

              USHORTPidHigh;           // 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

    } SMB_HEADER;

 

 

    NETBIOS Header的長度為4位元組:

       typedef struct netbiosHeader
{
UCHAR Type; // Type of the packet
UCHAR Flags; // Flags
USHORT Length; // Count of data bytes (netbios header not included)
} NETBIOSHEADER,*PNETBIOSHEADER;

        

 

    TCP Header為20位元組。SMBCommand Header的長度不是固定的,不同的命令有不同的長度。具體命令詳解參考下一章節。

 

 

三、SMB 命令

 

1、 SMB_COM_DELETE_DIRECTORY (0x01)

    這是原始核心協議的一個命令,用來刪除一個空的目錄。

 

2、 SMB_COM_CLOSE (0x04)

    這是原始核心協議的一個命令,用來關閉和一個有效的FID關聯的物件的一個例項。

 

3、 SMB_COM_FLUSH (0x05)

    這是原始核心協議的一個命令,用來要求伺服器將當前檔案的所有資料和資訊都寫回到儲存器上。

 

4、SMB_COM_DELETE (0x06)

    這是原始核心協議的一個命令,用來刪除一個或多個常規檔案。支援檔名中有萬用字元,允許一次刪除多個檔案。

5、SMB_COM_RENAME (0x07)

    這是原始核心協議的一個命令,用來重新命名一個或多個檔案或目錄。允許文

6、SMB_COM_CHECK_DIRECTORY (0x10)

    這是原始核心協議的一個命令。用來檢查指定的路徑是否在伺服器上存在。

 

7、SMB_COM_LOCKING_ANDX (0x24)

    此命令在LAN Manager 1.0中引入,不適用大於32-bit的檔案。支援最大64-bit的實現在NT LAN Manager中引入。

    此命令用來鎖定一個普通檔案中一段連續的資料。支援鎖定任一指定檔案中任意多的資料段,前提是這些資料段沒有重疊的部分。鎖定可以防止其他程式使用一個獨立的檔案控制程式碼(FID)對檔案鎖定部分進行鎖、讀和寫操作。任何程式使用獲取鎖的檔案的FID都可以訪問被鎖定的資料。

    此命令也可以被伺服器用來傳送一個OpLock中斷通知訊息給客戶端,客戶端收到後傳送確認訊息。這是CIFS協議中伺服器傳送請求訊息的一個例子。

下面列舉的是SMB_COM_LOCKING_ANDX後可能傳送的命令

·        SMB_COM_CLOSE

·        SMB_COM_FLUSH

·        SMB_COM_LOCKING_ANDX

·        SMB_COM_READ

·        SMB_COM_READ_ANDX

·        SMB_COM_WRITE

·        SMB_COM_WRITE_ANDX

 

8、SMB_COM_TRANSACTION (0x25)

    此命令在LAN Manager 1.0中引入。為事務處理協議的傳輸子協議服務。這些命令可以用於CIFS檔案系統內部通訊的郵箱和命名管道。如果出書的資料超過了會話建立時規定的MaxBufferSize,必須使用SMB_COM_TRANSACTION_SECONDARY命令來傳輸超出的部分:SMB_Data.Trans_Data 和 SMB_Data.Trans_Parameter。這兩部分在初始化訊息中沒有固定。

如果客戶端沒有傳送完所有的SMB_Data.Trans_Data,會將DataCount設定為小於TotalDataCount的一個值。同樣的,如果SMB_Data.Trans_Parameters沒有傳送完,會設定ParameterCount為一個小於TotalParameterCount的值。引數部分優先順序高於資料部分,客戶端在每個訊息中應該儘量多的傳送資料。伺服器應該可以接收無序到達的SMB_Data.Trans_Parameters 和 SMB_Data.Trans_Data,不論是大量還是少量的資料。

在請求和響應訊息中,SMB_Data.Trans_Parameters和SMB_Data.Trans_Data的位置和長度都是由SMB_Parameters.ParameterOffset、SMB_Parameters.ParameterCount,SMB_Parameters.DataOffset和SMB_Parameters.DataCount決定。另外需要說明的是,SMB_Parameters.ParameterDisplacement和SMB_Parameters.DataDisplacement可以用來改變傳送資料段的序號。伺服器應該優先傳送SMB_Data.Trans_Parameters。客戶端應該準備好組裝收到的SMB_Data.Trans_Parameters和SMB_Data.Trans_Data,即使它們是亂序到達的。

9、SMB_COM_TRANSACTION_SECONDARY (0x26)

    此命令在LAN Manager 1.0中引入。用來完成SMB_COM_TRANSACTION中未傳輸完畢資料的傳輸。

在請求和響應訊息中,SMB_Data.Trans_Parameters和SMB_Data.Trans_Data的位置和長度都是由SMB_Parameters.ParameterOffset、SMB_Parameters.ParameterCount,SMB_Parameters.DataOffset和SMB_Parameters.DataCount決定。另外需要說明的是,SMB_Parameters.ParameterDisplacement和SMB_Parameters.DataDisplacement可以用來改變傳送資料段的序號。伺服器應該優先傳送SMB_Data.Trans_Parameters。客戶端應該準備好組裝收到的SMB_Data.Trans_Parameters和SMB_Data.Trans_Data,即使它們是亂序到達的。

 

10、SMB_COM_ECHO (0x2B)

    此命令在LAN Manager 1.0中引入。客戶端傳送此命令測試和伺服器的傳輸層連線。

 

11、SMB_COM_OPEN_ANDX (0x2D)

    此命令在LAN Manager 1.0中引入。用來建立並開啟一個檔案,或者開啟一個已存在的普通檔案,並執行命令鏈中的命令。命令中包含客戶端要開啟的檔名,命名管道或裝置。如果執行成功,伺服器響應訊息中要攜帶一個合法的FID。客戶端在後續對此檔案的操作請求中要提供相同的FID。

下面這些命令是可以放在SMB_COM_OPEN_ANDX命令的AndX鏈中:

·        SMB_COM_READ

·        SMB_COM_READ_ANDX

·        SMB_COM_IOCTL

·        SMB_COM_NO_ANDX_COMMAND

 

12、SMB_COM_READ_ANDX (0x2E)

    此命令在LAN Manager 1.0中引入,在NT LAN Manager中對其進行了擴充套件。用來讀取資料,可以讀取普通檔案,命名管道,或直接訪問設別,比如串列埠(COM)或印表機介面(LPT)。如果客戶端用NT LAN Manager或以後的版本協商,應該傳送帶有12個引數的請求,這個版本支援最大64-bit的檔案。此命令是唯一一個支援讀取64-bit大小檔案的讀取命令。

下面這些命令是可以放在SMB_COM_READ_ANDX命令的AndX鏈中:

·        SMB_COM_CLOSE

 

13、SMB_COM_WRITE_ANDX (0x2F)

    此命令在LAN Manager 1.0中引入。用來向普通檔案,命名管道,或直接訪問設別,比如串列埠(COM)或印表機介面(LPT)中寫入資料。如果客戶端用NT LAN Manager或以後的版本協商,應該傳送帶有14個引數的請求,這個版本支援最大64-bit的檔案。此命令是唯一一個支援寫64-bit大小檔案的讀取命令。

下面這些命令是可以放在SMB_COM_WRITE_ANDX命令的AndX鏈中:

·        SMB_COM_READ

·        SMB_COM_READ_ANDX

·        SMB_COM_LOCK_AND_READ

·        SMB_COM_CLOSE

 

14、SMB_COM_TRANSACTION2 (0x32)

    此命令在LAN Manager 1.2中引入。支援伺服器檔案系統更豐富的語義集。允許客戶端設定和獲取擴充套件的key/value屬性對,支援長檔名(比原始的8.3名字格式要長),可以執行目錄搜尋及其他任務。

如果客戶端沒有傳送完所有的SMB_Data.Trans_Data,會將DataCount設定為小於TotalDataCount的一個值。同樣的,如果SMB_Data.Trans_Parameters沒有傳送完,會設定ParameterCount為一個小於TotalParameterCount的值。引數部分優先順序高於資料部分,客戶端在每個訊息中應該儘量多的傳送資料。伺服器應該可以接收無序到達的SMB_Data.Trans_Parameters 和 SMB_Data.Trans_Data,不論是大量還是少量的資料。

在請求和響應訊息中,SMB_Data.Trans2_Parameters和SMB_Data.Trans2_Data的位置和長度都是由SMB_Parameters.ParameterOffset、SMB_Parameters.ParameterCount,SMB_Parameters.DataOffset和SMB_Parameters.DataCount決定。另外需要說明的是,SMB_Parameters.ParameterDisplacement和SMB_Parameters.DataDisplacement可以用來改變傳送資料段的序號。伺服器應該優先傳送SMB_Data.Trans2_Parameters。客戶端應該準備好組裝收到的SMB_Data.Trans2_Parameters和SMB_Data.Trans2_Data,即使它們是亂序到達的。

15、SMB_COM_TRANSACTION2_SECONDARY (0x33)

    此命令在LAN Manager 1.2中引入。用來完成SMB_COM_TRANSACTION2中未傳完的資料。

 

16、SMB_COM_FIND_CLOSE2 (0x34)

    此命令在LAN Manager 1.2中引入。用來關閉由命令TRANS2_FIND_FIRST2而開啟的搜尋控制程式碼,伺服器釋放所有和此控制程式碼相關的資源。

 

17、SMB_COM_TREE_DISCONNECT (0x71)

    這是一個原始核心協議命令。用來關閉客戶端訪問伺服器資源時使用的一條邏輯連線,連線依靠SMB頭部的TID識別,斷開後伺服器將此TID視為無效的TID。所有和此TID相關的檔案、目錄及其他資源都被釋放,檔案和目錄的鎖也會被釋放。

18、SMB_COM_NEGOTIATE (0x72)

    這是一個原始核心協議命令。用來初始化伺服器和客戶端之間的SMB會話,必須在其他任何SMB命令傳送之前完成。

    每個SMB會話只能有一次協商過程,後續的SMB_COM_NEGOTIATE會被伺服器拒絕並返回一個錯誤響應。

19、SMB_COM_SESSION_SETUP_ANDX (0x73)

    此命令在LAN Manager 1.0中引入。相比最初的定義,請求和響應訊息的格式都有所改變。本文介紹CIFS格式,在NT LAN Manager中定義。當協商使用NT LAN Manager時必須使用此格式。

此命令用來配置一個SMB會話。如果伺服器執行在user級訪問控制模式,至少傳送一個SMB_COM_SESSION_SETUP_ANDX命令,執行使用者登入伺服器並建立一個有效的UID。

在CIFS協議中,在SMB_COM_SESSION_SETUP_ANDX命令執行成功之前傳送SMB_COM_TREE_CONNECT或SMB_COM_TREE_CONNECT_ANDX是違反協議的,即使伺服器執行在share級的訪問控制模式。在SMB_COM_SESSION_SETUP_ANDX請求之後,包含SMB_COM_TREE_CONNECT_ANDX批處理請求的AndX鏈可以滿足這一需求,匿名認證也可以滿足這一需求。

一個SMB會話用允許有多個SMB_COM_SESSION_SETUP_ANDX,用來建立額外的UID或建立額外的虛擬鏈路。

下面的命令可以放在SMB_COM_SESSION_SETUP_ANDX後面的AndX鏈中:

·        SMB_COM_TREE_CONNECT_ANDX

·        SMB_COM_OPEN

·        SMB_COM_OPEN_ANDX

·        SMB_COM_CREATE

·        SMB_COM_CREATE_NEW

·        SMB_COM_CREATE_DIRECTORY

·        SMB_COM_DELETE

·        SMB_COM_DELETE_DIRECTORY

·        SMB_COM_FIND

·        SMB_COM_FIND_UNIQUE

·        SMB_COM_RENAME

·        SMB_COM_NT_RENAME

·        SMB_COM_CHECK_DIRECTORY

·        SMB_COM_QUERY_INFORMATION

·        SMB_COM_SET_INFORMATION

·        SMB_COM_OPEN_PRINT_FILE

·        SMB_COM_TRANSACTION

 

20、SMB_COM_LOGOFF_ANDX (0x74)

    SMB頭部UID標記的使用者被登出,伺服器將釋放所有此UID相關的資源,包括釋放鎖,關閉所有的檔案,斷開連線,取消所有沒有處理完的命令,標記此UID無效。

下面的命令可以放在SMB_COM_LOGOFF_ANDX後面的AndX鏈中:

·        SMB_COM_SESSION_SETUP_ANDX.

 

21、SMB_COM_TREE_CONNECT_ANDX (0x75)

    此命令在LAN Manager 1.0中引入。用來建立一條客戶端和伺服器之間的連線,共享資源依靠共享名確定。連線建立後,此連線將用伺服器返回的TID作為識別標記。

下面的命令可以放在SMB_COM_TREE_CONNECT_ANDX後面的AndX鏈中:

·        SMB_COM_OPEN

·        SMB_COM_OPEN_ANDX

·        SMB_COM_CREATE

·        SMB_COM_CREATE_NEW

·        SMB_COM_CREATE_DIRECTORY

·        SMB_COM_DELETE

·        SMB_COM_DELETE_DIRECTORY

·        SMB_COM_SEARCH

·        SMB_COM_FIND

·        SMB_COM_FIND_UNIQUE

·        SMB_COM_RENAME

·        SMB_COM_NT_RENAME

·        SMB_COM_CHECK_DIRECTORY

·        SMB_COM_QUERY_INFORMATION

·        SMB_COM_SET_INFORMATION

·        SMB_COM_OPEN_PRINT_FILE

·        SMB_COM_TRANSACTION

 

22、SMB_COM_NT_TRANSACT (0xA0)

    此命令在NT LAN Manager中引入。擴充套件了由SMB_COM_TRANSACTION2提供的檔案系統訪問服務,允許處理非常大的引數和資料塊。

    SMB_COM_NT_TRANSACT訊息可以超過單個SMB訊息允許的最大值(由引數MaxBufferSize決定)。在這種情況下,客戶端使用一個或多個SMB_COM_NT_TRANSACT_SECONDARY訊息來傳輸和訊息初始化不匹配的data和Parameter。

    如果客戶端沒有傳送完所有的SMB_Data.Trans_Data,會將DataCount設定為小於TotalDataCount的一個值。同樣的,如果SMB_Data.Trans_Parameters沒有傳送完,會設定ParameterCount為一個小於TotalParameterCount的值。引數部分優先順序高於資料部分,客戶端在每個訊息中應該儘量多的傳送資料。伺服器應該可以接收無序到達的SMB_Data.Trans_Parameters 和 SMB_Data.Trans_Data,不論是大量還是少量的資料。

在請求和響應訊息中,SMB_Data.NT_Trans_Parameters和SMB_Data.nt_Trans_Data的位置和長度都是由SMB_Parameters.ParameterOffset、SMB_Parameters.ParameterCount,SMB_Parameters.DataOffset和SMB_Parameters.DataCount決定。另外需要說明的是,SMB_Parameters.ParameterDisplacement和SMB_Parameters.DataDisplacement可以用來改變傳送資料段的序號。伺服器應該按照自己順序傳送,優先傳送SMB_Data.NT_Trans_Parameters。客戶端應該準備好組裝收到的SMB_Data.NT_Trans_Parameters和SMB_Data.NT_Trans_Data,即使它們是亂序到達的。

23、SMB_COM_NT_TRANSACT_SECONDARY (0xA1)

    此命令用來完成SMB_COM_NT_TRANSACT中未傳完的資料。

24、SMB_COM_NT_CREATE_ANDX (0xA2)

    此命令在NT LAN Manager中引入。用來建立並開啟一個新檔案,或者開啟一個已存在的檔案,或開啟並清空一個已存在的檔案,或建立一個目錄,或建立一個命名管道。返回的FID可以用在後續的請求訊息中。

    訊息中包含客戶端想要建立或開啟的檔名,目錄,或命名管道和RootDirectoryFID。如果執行成功,伺服器返回一個FID標記開啟的資源。客戶端在後續的請求訊息中必須攜帶此FID。客戶端必須擁有對資源所在目錄的寫許可權,才能建立一個新的檔案或目錄;或者擁有檔案的寫許可權來執行截斷檔案的操作。

下面的命令可以放在SMB_COM_NT_CREATE_ANDX後面的AndX鏈中:

·        SMB_COM_READ

·        SMB_COM_READ_ANDX

·        SMB_COM_IOCTL

 

25、SMB_COM_NT_CANCEL (0xA4)

    此命令在NT LAN Manager中引入。使客戶端可以取消掉pending態的請求。伺服器用SMB_Header中的資訊識別客戶端想要取消哪些請求,伺服器可以取消或立即處理這些請求。伺服器對此訊息不能回覆響應訊息。客戶端應該依靠伺服器對指定取消的訊息的響應來判斷取消訊息的結果。如果伺服器不能識別客戶端請求中的指定訊息,也不應該傳送響應。

    此命令主要用來取消由SMB_COM_NT_TRANSACT和NT_TRANSACT_NOTIFY_CHANGE子命令引起的多餘的通知訊息。客戶端一般用NT_TRANSACT_NOTIFY_CHANGE命令避免輪詢目錄的改變。此命令另外的用途包括取消一個無限期等待繁忙資源的請求,或嘗試很多次來等待一個資源的請求。

 

26、SMB_COM_OPEN_PRINT_FILE (0xC0)

    這是一個原始核心協議命令。用來建立一個列印佇列緩衝檔案。此檔案將會在印表機中排隊。當檔案列印完畢後,伺服器應該刪除這個檔案。

 

27、SMB_COM_INVALID (0xFE)

    此命令在LAN Manager 1.0中引入。這是一個保留的值,指明一個非法的命令。客戶端不應該傳送此命令,伺服器收到此命令後應該返回STATUS_SMB_BAD_COMMAND (ERRDOC/ERRbadfunc)。

 

28、SMB_COM_NO_ANDX_COMMAND (0xFF)

    此命令在LAN Manager 1.0中引入。設計此命令的目的是用來指明一個AndX鏈的結束。

    客戶端不應該在主命令中使用此命令,伺服器在主命令中收到此命令後應該返回STATUS_SMB_BAD_COMMAND(ERRSRV/ERRbadcmd)。

    在早期的SMB協議規格(見[IBM-SMB])中,此命令保留來做特定協議的擴充套件。這個用法已過時。在最新的微軟協議文件中,包括[SMB-CORE]和[MSFT-XEXTNP],都沒有描述此命令作為協議擴充套件或其它目的的作用。

 

相關文章