西門子作為一個老牌工控企業,在中國市場擁有很高的市場佔有率。如果要說起西門子的通信協議,相信大家多多少少能說出一些,比如MPI、PPI、USS、Profibus、Profinet、S7等,但是西門子在協議的開放性方面還是相對要封閉一些,所以很多時候我們是沒法知道這些協議的底層通信原理的。
在這裡,我主要是結合Wireshark抓包工具,跟大家去分享一下,如何是一步一步抓取西門子S7通信協議底層通信報文的,希望通過我一步一步地分析,讓大家都能夠對西門子S7協議有所瞭解的同時,也學會基本的抓包操作與報文分析。
1
環境搭建
1、首先我們要準備要準備一個西門子的PLC,並保證PLC與PC之間的網絡連接正常。PS:對於手頭沒有PLC的童鞋,可以自行查看相關文章:基於TIA搭建西門子PLC仿真環境及通信方案。
2、為了抓取到通信的報文,需要實現PC與PLC之間的通信,這裡我採用的方式是通過KepServer V6.4來實現。
3、安裝Wireshark抓包軟件。
4、認識S7協議的網絡模型。
2
操作步驟
1、首先將KepServer與PLC之間的通信連接配置好;
PS:對於KepServer軟件應用可以參考相關文章:基於KepServer V6.4實現與三菱FX3U PLC之間的通信。
2、將Wireshark軟件打開,並處於監控報文狀態;
3、將KepServer進行連接PLC,此時Wireshark軟件中會出現報文的數據,將KepServer連接停止並關閉軟件,同時將Wireshark的監控停止,以便進行後續的報文分析;
3
初步分析
結合自身對TCP通信的瞭解,可以將抓取到的報文類型進行區分:
TCP三次握手過程
S7協議的第一次連接驗證
S7協議的第二次連接驗證
TCP四次揮手過程
通過分析,我們發現西門子的S7通信並不是簡簡單單的TCP通信,在TCP執行三次握手之後,還需要發送兩次連接驗證,在兩次連接驗證之後,才進行真正的數據交互。
4
抓包分析
(1)第一次握手發送報文
報文說明:
TPKT(第五層:會話層)
該層總共佔4個字節:
版本號:0x03
預留:0x00
長度:0x0016
COTP(第六層:表示層)
該層總共佔用18個字節:
長度:0x11
PDU類型(CRConnect Request 連接請求):0x0E
目標引用:0x0000
源引用:0x0001
擴展格式/流控制:0x00
參數代碼TPDU-Size:0xC0
參數長度:0x01
TPDU大小:0x0A
參數代碼SRC-TASP:0xC1
參數長度:0x02
SourceTSAP:0x0201
參數代碼DST-TASP:0xC2
參數長度:0x02
DestinationTSAP:0x0201
(2)第一次握手回覆報文
報文說明:
TPKT(第五層:會話層)
該層總共佔4個字節:
版本號:0x03
預留:0x00
長度:0x0016
COTP(第六層:表示層)
該層總共佔18個字節:
長度:0x11
PDU類型(CCConnect Confirm 連接確認):0x0D
目標引用:0x0001
源引用:0x0006
擴展格式/流控制:0x00
參數代碼TPDU-Size:0xC0
參數長度:0x01
TPDU大小:0x0A
參數代碼SRC-TASP:0xC1
參數長度:0x02
SourceTSAP:0x0201
參數代碼DST-TASP:0xC2
參數長度:0x02
DestinationTSAP:0x0201
(3)第二次握手發送報文
報文說明:
TPKT(第五層:會話層)
該層總共佔4個字節:
版本號:0x03
預留:0x00
長度:0x0019
COTP(第六層:表示層)
該層總共佔3個字節:
長度:0x02
PDU類型(DT Data):0XF0
目標引用:0x80
S7Communication(第七層:應用層)
該層總用佔18個字節,並且分兩部分:
Header:
協議ID(Protocol ID):0x32
ROSCTR:0x01
預留:0x0000
協議數據單元引用:0x037C
參數長度:0x0008
數據長度:0x0000
Parameter:
功能碼:0xF0
預留:0x00
最大AmQ(Calling):0x0001
最大AmQ(Called):0x0001
PDU長度:0x03C0
(4)第二次握手返回報文
報文說明:
TPKT(第五層:會話層)
該層總共佔4個字節:
版本號:0x03
預留:0x00
長度:0x0019
COTP(第六層:表示層)
該層總共佔3個字節:
長度:0x02
PDU類型(DT Data):0XF0
目標引用:0x80
S7Communication(第七層:應用層)
該層總用佔20個字節,並且分兩部分:
Header:
協議ID(Protocol ID):0x32
Ack_Data:0x03
預留:0x0000
協議數據單元引用:0x037C
參數長度:0x0008
數據長度:0x0000
錯誤等級:0x00
錯誤代碼:0x00
Parameter:
功能碼:0xF0
預留:0x00
最大AmQ(Calling):0x0001
最大AmQ(Called):0x0001
PDU長度:0x00F0
由於只配置了VD0,因此讀取DB1.DBX0.0 開始的4個字節
報文說明:
TPKT(第五層:會話層)
該層總共佔4個字節:
版本號:0x03
預留:0x00
長度:0x001F
COTP(第六層:表示層)
該層總共佔3個字節:
長度:0x02
PDU類型(DT Data):0XF0
目標引用:0x80
S7Communication(第七層:應用層)
該層總用佔24個字節,並且分兩部分:
Header:
協議ID(Protocol ID):0x32
Ack_Data:0x01
預留:0x0000
協議數據單元引用:0x037D
參數長度:0x000E
數據長度:0x0000
Parameter:
功能碼Read Var:0x04
通信項數:0x01
通信項1:
通信項Header
變量指定:0x12
地址長度:0x0A
SyntaxID:0x10
傳輸數據類型byte:0x02
通信項Param
讀取長度:0x04
DB號:0x01
存儲區類型DB存儲區:0x84
開始字節:0x000000
報文說明:
TPKT(第五層:會話層)
該層總共佔4個字節:
版本號:0x03
預留:0x00
長度:0x001D
COTP(第六層:表示層)
該層總共佔3個字節:
長度:0x02
PDU類型(DT Data):0XF0
目標引用:0x80
S7Communication(第七層:應用層)
該層總用佔22個字節,並且分兩部分:
Header:
協議ID(Protocol ID):0x32
Ack_Data:0x03
預留:0x0000
協議數據單元引用:0x037D
參數長度:0x0002
數據長度:0x0008
錯誤等級:0x00
錯誤代碼:0x00
Parameter:
功能碼Read Var:0x04
通信項數:0x01
通信項1:
返回結果Success:0xFF
傳輸數據類型Byte/Word/DWord:0x04
長度:0x0020
數據:0x00000000
該返回報文說明讀取的4個字節數值均為0
如果將這裡的報文進行整理,結合Socket通信的相關知識,與西門子PLC通信的問題便迎刃而解了。