工控安全入門(二)—— S7comm協議


在上一次的文章中我們介紹了施耐德公司的協議modbus,這次我們把目標轉向私有協議,來看看另一家巨頭西門子的S7comm。首先要說明,這篇文章中的內容有筆者自己的探索,有大佬們的成果,但由於S7comm是私有協議,一些結論和看法不可能完全正確,希望各位有認為不對的地方或是更好的看法可以評論告訴我。

ps:有些專業名詞可能不對,因為沒找到准確的翻譯或者是根本沒找到官方定義(畢竟是私有協議),筆者就自己起了名……

建議閱讀本篇前首先閱讀:工控安全入門(一)—— Modbus協議

 

S7comm簡介

西門子是德國的一家超大型企業,在能源、工業、醫療、基建等等方面都有它的身影,同時它也位列全球500強第66名。作為一個以電報起家的大型企業,它對於通信更是重視,S7comm就是西門子為了它生產的PLC之間、SCADA與PLC之間的通信而設計的專屬協議。

和Modbus的應用層協議不同,S7comm的協議棧修改程度更高,在應用層組織的數據經過COTP協議、TPKT協議的進一步處理后,最終通過TCP進行傳輸,下面是wireshark wiki給出的S7comm的協議棧:

OSI layer Protocol
Application Layer S7 communication
Presentation Layer S7 communication(COTP)
Session Layer S7 communication(TPKT)
Transport Layer ISO-on-TCP (RFC 1006)
Network Layer IP
Data Link Layer Ethernet
Physical Layer Ethernet

我們說的題目雖然是對S7comm的分析,實際上是對整個協議棧的探索。鑒於數據包邏輯上是由高層進行封裝再一步步的轉遞給較低層,但我們接收到包后是低層一層層拆卸交給上層,基於逆向思維,我們之后的分析應該是由低向高展開的

 

TPKT協議

我相信大家對於傳輸層往下的內容應該比較熟悉了,都是TCP/IP的基本內容,我就不再贅述,直接從會話層來看。

TPKT協議是一個傳輸服務協議,它為上層的COPT和下層TCP進行了過渡。我們常用的RDP協議(remote desktop protocol,windows的遠程桌面協議)也是基於TPKT的,TPKT的默認TCP端口為102(RDP為3389),其實它本身為payload增加的數據並不多,主要就是以下幾個:

  • version,1byte,表明版本信息
  • reserved,1byte,看到這個名字就知道是保留的了
  • length,2byte,包括payload和這三部分在內的總長度

下面我們就用之前分析過的2018工控比賽的流量包來實際看一下

可以看到,版本號是3號,長度為31,除此之外該層並沒有什么有用信息了

 

COPT協議

COPT協議的全稱是Connection-Oriented Transport Protocol,即面向連接的傳輸協議,從這個名字就可以看出,它的傳輸必然是依賴於連接的,所以在傳輸數據前必然有類似TCP握手建立鏈接的操作。

讓我們先來看看具體的流量包

首先是TCP的三次握手,在192.168.25.146與192.168.25.139間建立了TCP連接,之后是兩個COTP的包,注意,這里wireshark為我們標注出了CR和CC,后面的COTP包都是DT,這里的CR和CC其實分別是connect request和connet confirm的,也就是建立連接的過程,之后連接建立成功后,發送DT包,也就是data ,是在發送數據。

我們接着再看看他們攜帶的數據

可以看到,DT包和連接包有着明顯的不同,連接包明顯多了一堆內容,這其實是COPT包的兩種形態,COTP連接包(COTP Connection Packet)和COTP功能包(COTP Fuction Packet)

首先來看COPT連接包,通過上面的wireshark的分析我們可以看到,主要有以下幾個字段:

  • length,1byte,數據的長度,但並不包含length這個字段(個人感覺很奇怪……)
  • PDU type,1 byte,標識類型,圖中的0x0d即為連接確認的類型,常有的還有
    • 0xe,連接請求
    • 0x0d,連接確認
    • 0x08,斷開請求
    • 0x0c,斷開確認
    • 0x05,拒絕
  • DST reference,2byte,目標的引用,可以認為是用來唯一標識目標
  • SRC reference,2byte,源的引用,同上
  • option,1byte,可以看到wireshark將8位拆為了前四位和后兩位:
    • 前四位標識class,也就是標識類別
    • 倒數第二位對應Extended formats,是否使用拓展樣式
    • 倒數第一位對應No explicit flow control,是否有明確的指定流控制
  • parameter,附加的參數字段,參數可以有多個,每個參數又由以下幾個字段構成:
    • code,1byte,標識類型,主要有:
      • 0xc0,tpdu的size,tpdu即傳送協議數據單元,也就是傳輸的數據的大小(是否和前面的length有重復之處?)
      • 0xc1,src-tsap,翻譯過來應該叫源的端到端傳輸(在完整的TCP/IP協議棧中,這個字段代表的是應用與應用之間的通信,我這里猜測可能是為了),但從西門子給的手冊來看,它標記的應該是機架號,可是不管我怎么查,也沒有找到wireshark解析出的字符串。那么逆向我們找不到答案,就只能正向來了,在parameter字段的最后我們再來詳細說這到底是個啥。

      • 0xc2,dst-tsap,同上,之后我們再探索
    • length,長度
    • 對應的數據

接着COPT功能包,其實個人感覺這兩種包可以歸為一種,但是看到文獻都是分為兩種的,那我們也就划分為兩種吧

  • length,1byte,長度
  • PDU type,1 byte,圖中為0x0f,即為數據傳輸,此外的type都不太常用,這里不再提了(其實是我沒找到相關的流量包……有這方面流量的大佬希望補全以下)
  • option,1byte,以位為單位划分:
    • 第一位,標識是否為最后一個數據包(從這可以看出,COPT協議當數據較多時,會分為幾個單元傳輸
    • 后七位,標識TPDU的number

到這COPT包我們就算是分析的徹徹底底了,當然,上面還留了個小問題,parameter里的tsap到底是個什么東西?一些我們看上去整不明白的參數到底是干啥的呢?既然逆向不行了,我們就通過正向開發來看看,這到底是個啥,以下使用Simatic NET 軟件(做的時候忘記截圖了……圖片來自http://www.ad.siemens.com.cn)。

我們配置了一台local的OPC服務器(OPC服務器可以理解為轉換協議的一種設備),目標是實現它和PLC的通信。我們選擇使用Ethernet,並分別配置了機器的ip地址和子網。

接着我們進入地址的細節,發現了TSAP和RACK/SLOT兩個重要的選擇項,實際操作我們才發現,RACK是指CPU的機架號,而SLOT是指是CPU的槽位號,通過這兩個參數我們就可以唯一指定一個CPU。

那說明手冊有錯?那怎么可能,人家好歹也是個大廠,玄機就在這個TSAP上。其實它有三部分組成:

  • 連接號(我瞎起的名,確實是沒找到這玩意叫啥),指的是連接方式,03就是單向通信,單向的可以連接多個設備,10以上的就是雙向的,雙向的就沒法多個設備了。
  • 機架號,就是RACK
  • 槽位號,就是SLOT

如圖所示,我們為OPC服務器配置的是12.11,也就是雙向通信,1號架1號槽位,而PLC則是03.02,單向通信,0號架2號槽位。那么問題又來了,這和我們流量里的數據包完全不一樣啊!

數據包里是SNOPCCxxxx,咋解釋?這可一點也不符合我們上面的說明,這其實是另外一種連接方式,叫做S7優化連接,比起之前的連接方式,這種連接可以以符號的形式訪問數據塊。

它規定了src-tsap為SNOPCC000x000xxx,第一個x筆者沒有搞明白代表了什么,第二個是連接數,圖中即為有一個連接,而在dst-tsap必須為SIMATIC-ROOT-OTH 。剛好也和我們的數據包對應。所以我們分析的數據包應該是一個單向連接,連接的數目是一個。

到這里,我們對於COPT可以說是精確到每一位了,雖然還有一些地方有瑕疵,但總體來說是沒什么問題了。

 

S7comm協議

總算是來到了最后的S7comm協議,它的結構很簡單,主要分為三部分:

  • Header,主要是數據的描述性信息,最重要的是要表明PDU的類型
  • Parameter,參數,隨着不同類型的PDU會有不同的參數
  • Data,具體的數據

首先我們就具體來看看這個Header有什么玄機

aa

  • Protocol id,1 byte,即協議的id,為0x32
  • ROSCTR,1byte,pdu的類型,一般由以下幾種:
    • 0x01,job,就是開工干活的意思,主設備通過job向從設備發出“干活”的命令,具體是讀取數據還是寫數據由parameter決定
    • 0x02,ack,0x02,確認
    • 0x03,ack data,從設備回應主設備的job
    • Reserved,2byte,保留
    • PDU reference,pdu的參考
    • parameter length,參數的長度
    • error class,錯誤類型,像是圖中的0x00就是沒有錯誤的意思,而常見的請求錯誤則是0x85
    • error code,錯誤碼,結合錯誤類型來確定錯誤,圖中的0x00同樣是沒有錯誤的意思

關於具體的錯誤類型和錯誤碼的信息大家可以自行搜索,因為太多了這里就不再展開說明了。而parameter取決於不同的pdu類型,所以這里也不再說了,下面來看看具體的流量包

可以看到該pdu為job,也就是主設備在發號施令,而通過parameter可以看到,function是0x04的read,也就是讀取數據,item count意思是后續跟了幾個item,該pdu就一個,所以為1。而這個item的結構就有要單獨說說了:

  • variable specification,1byte,一般就是0x12(我沒見過別的……)
  • 長度,Length of following address specification,數據的長度
  • Syntax Id,符號id,一個標志,決定了一些格式性問題,這里是0x10是Address data S7-Any pointer-like DBx.DBXx.x的意思,具體啥意思我們在看完下面幾條后再提,詳細的大家還是可以去自己看看,主要就是對於后續的尋址起到了一定的限定
  • 傳輸大小,也可以認為是傳輸類型,在這是4,也就是WORD
  • DB number,就是數據塊編號的意思,0就代表要找的東西不在數據塊里
  • area,要操作的“東西”,比如0x82,就是讀設備的輸出,通過這一位也可以看到,我們要讀的數據不在DB里,所以DB number為0,如果為DB的話,這1byte應該為0x84
  • address,具體的地址,如下圖所示,前五位沒用到,第六位到第二十一位是Byte地址,最后三位是Bit的地址

首先,它定義了格式為Address data S7-Any pointer-like DBx.DBXx.x,然后指定了讀取的”東西“為設備的輸出,讀取的大小為word,其實到這里這個pdu的全部信息就已經分析完了,但是為了讓大家更好的理解上面定義的格式,我們還是繼續看一下。

它讀的DB number是0那么根據格式就是DB0.DBXx.x,而讀取的address是Byte為0,Bit為0,也就是DB0.DBX0.0,如果我們指定的”東西“為數據塊的話,就按照這種格式讀取。這就是格式的意思,再比如說0xb2,描述為Symbolic address mode of S7-1200,實際上格式就是符號地址,就不再是這樣的組織形式了。

再來看看上個pdu的相應,這里截圖沒截到header,header最值得關注的是pdu的類型,這里是0x03,也就是我們之前提到過的對於job的相應

而paramter部分可以看到,function是與job pdu的相同的。Data部分就是傳回來的具體數據了,return code是返回碼,用來標識job讓干活的結果,這里是0xff,代表的是成功的意思,除了這個,還有以下幾種:

  • 0x01,硬件錯誤
  • 0x03,想訪問的東西不讓訪問
  • 0x05,地址越界了
  • 0x06,你請求的數據類型和請求的”東西“的數據類型不一致

接着是data的長度(是真的data的長度,不包含前面),最后就是具體的data了,可以看到,這里讀到的是0x0000。

到此,S7comm協議我們也認識的差不多了,下面就讓題目了。

 

2018年工業信息安全技能大賽(東北賽區)工業協議數據分析

因為19年的題目涉及到S7comm的上次我們已經做了一個了,所以這次就找了個別的題目,首先來看流量包

可以看到一大堆的協議,不過整體思路還是剛才清晰的,首先是ARP協議去找mac地址(不知道arp的,補一下計算機網絡的知識吧……),接着是標准的TCP三次握手,接着是COPT的建立連接(要不以后我叫他兩次握手?),接着就到了S7comm和modbus來具體干活了。

我們可以看到這個job和我們之前的並不一樣,打開仔細瞧瞧

可以看到parameter中的funtion為0xf0,是建立通信的意思,這其實是和上面的TCP、COPT有些相似的,都是在兩個設備之間建立通信,而參數的主要信息是MAX AMQ calling和MAX AMQ called。

下面一個ack_data的pdu自然是相應建立通信的意思了,經過TCP握手、COPT建立連接、S7comm建立通信,這樣設備間的通信才正式建立完畢了。

往后的S7comm可以看到是read,也就是在讀數據,數據包和上面提到的一樣,不再贅述。經過查找,並沒有flag。

這時候就要考慮modbus協議中是否存在flag了,這時候就要用到之前modbus的技巧了,1、2、3、4的function code沒有大規模取數據的能力,flag一般都在他們之外,進行下簡單的過濾,打印出相應的數據就ok了

腳本還是用上一篇文章的就可以,這里就不在放了,需要的去上一篇取即可(不水字數了)。

最終flag為modbusICSsecurityWin

 

總結

S7comm作為一個私有協議,它的可出題點其實更多,而且由於是私有協議,很多地方都還有挖掘的空間,這篇文章只是帶大家按照我的思路,從無到有的分析了S7comm的各個部分,肯定有不完全正確的地方,也肯定有細節沒有考慮到,希望大家能更進一步,探索更多的秘密。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM