工控安全入門(三)—— 再解S7comm


之前的文章我們都是在ctf的基礎上學習工控協議知識的,顯然這樣對於S7comm的認識還不夠深刻,這次就做一個實戰補全,看看S7comm還有哪些值得我們深挖的地方。

本篇是對S7comm的補全和實戰,閱讀本篇之前一定要先閱讀以下文章,掌握基本的S7comm知識:

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

本篇文章依然有很多筆者自己摸索的內容,可能存在錯誤,同時也發現了wireshark對於s7comm解析的幾個模糊之處,希望大家能幫忙指正。本次選用的流量包來自於github的w3h,有興趣的同學可以下載下來仔細研究。

https://github.com/w3h/icsmaster/tree/master/pcap

 

s7comm_reading_setting_plc_time

首先來大體上看一下流量包

可以看到,主機是192.168.1.10,設備為192.168.1.40,首先是tcp包,但傳輸失敗了,之后調用arp解析到了40的mac地址,接下來通過tcp的三次握手來建立連接,通過COPT的CR和CC建立了通信,最后再利用S7comm的job建立了通信。這是s7comm在兩個設備建立通信的一般流程,到此為止,利用我們上一篇文章的知識都可以完美解決,可是再往下就出了問題,這個userdata的包是個啥?

我們打開看看具體的細節

可以看到大體結構和我們上一篇文章所講的無異,最主要的就是PDU的類型不一樣導致后面的跟的參數我們看不明白了。不要慌,這個時候就要慢慢來分析了。

首先ROSCTR變為了0x07,wireshark給出的是Userdata,翻譯過來是用戶數據?那就不對了,如果我們把設備比作電腦的話,我們之前用的job更像是一般用戶的操作,而這個Userdata嘛更像是程序員的操作,比如說它可以用來讀取SZL(后面會說這是個啥)、調試、安全等等方面。(是不是感覺有點像modbus的0x5a操作?)

也正因為它包含了復雜的功能,所以Parameter比起job更為復雜,這里主要要關注兩項。

  • function,1byte,wireshark已經幫我們解析為了8位
    • 前四位,標識pdu的狀態或者說是類型,比如說圖中的0100對應request,說明該pdu是主機請求設備的。而作為回應的有0000,對應push,推遲了請求;或者是10
    • 00,對應response,對於該請求的返回
    • 后四位,標識方法所屬的類型,這里是0100,對應的是cpu功能
  • subfunction,子方法,前一個字節決定了大方向,這個字節來決定具體要干啥,圖中是0x1,也就是read szl。

那么szl到底是個啥呢?其實它是系統狀態列表的縮寫,本來標准縮寫應該是SSL(system status list官方手冊上也是這么寫的),但因為西門子是德國的,在德語中”狀態“是z開頭的,於是就成了szl。簡單說就是當前設備的狀態信息,包括很多重要的信息。可以看到Data中有SZL-ID和Index兩個字段,這倆就用來指示要讀取的內容

ID占兩個字節,意思分別如下:

  • 前四位,diagnosit type,直譯是診斷類型,實際上就是說明要操作的對象是啥| Bit | Type |
    | —— | —— |
    | 0000 | Cpu |
    | 1100 | cp |
    | 1000 | Fm |
    | 0100 | im |
  • 中間4位,這個應該是wireshark解析錯誤了,可以看到官方文檔給出的是4位,而wireshark給出的是16位,顯然是不對的。這里的數字是要提取的局部列表的值,簡單說就是這表東西有點多,你當然可以全輸出,但更多時候我們還是只需要其中的一部分。
  • 后八位表明表明局部列表的序號,這里是0x32wireshark為我們說明這個局部列表是通信狀態數據,具體的各類局部列表的序號如下(我們關注的是最后兩個字節):

這里SZL-ID的完整意思就是,從編號為0x32的局部列表(寫作W#16#xy32)中提取0x01的內容(寫作W#160132),0x01意思是通用通信數據,index是0x04,即對象管理系統(寫作W#16#0004,這個index舊版的手冊上沒有),這就組成了完整的請求。根據我們寫作的格式查找手冊即可查詢具體作用。

再看看這個pdu的回復,可以看到data tree就是讀取到的信息

  • key,關鍵交換機的保護等級
  • param,分配的保護等級
  • real,合法的cpu保護等級
  • bart_sch,這是當前的狀態,圖中為RUN_P,此外還有RUN、STOP等等
  • crst-wrst,這是wireshark給的解釋,我認為此處應該是anl_sch,即初始的設定,這里是0,也就是沒有出事設定
  • res,看到reserved就是保留的(但這里保留的字節是不是太多了……)

接着看下一個PDU,對應的包是第16個

還是和上面一個套路,不過這次的SZL-ID和index都是0,這可怪了,按照上面我們給出的分析方法,似乎找不到這個特殊的家伙,這時候我們就需要結合response來進行逆推了

可以看到返回了一大堆數據,而這些很眼熟啊,正好就是SZL-ID啊,所以我們就可以推斷出,上面一個request的作用是檢查所有存在的局部列表。

后面的pdu就不再展開分析了,都是在讀取cpu類的相關信息,只不過是指定的局部列表不同、index不同罷了,大家有興趣的可以自行往下看。

 

step7_s300_stop.pcapng && snap7_s300_stop.pcapng

stop絕對是對工控設備最重要也是最容易出事的指令了,一個不小心就會釀成大禍。這里給大家分析兩種stop的包,首先簡單說一下背景:

  • step 7,這是個用於管理和組態項目中所有設備的工具,界面非常友好,使用也很簡單
  • snap7,是個開源的西門子s7系列的通信庫,支持多種編程語言

首先來看snap7的吧,流量包就兩個pdu,是我們已經熟悉的job和ack_data,我們打開job來詳細看一下

這里可以看到整體十分簡單,唯一一個有疑惑的地方就是PI Service,這個PI Service是程序調用服務的意思,它標識包括啟動、停止等等的服務,它本身最常用在0x28的function中,0x28標識PI service包,再通過PI service這個字段來標識具體的功能。因為stop的重要性,所以在s7comm中把它從PI service包中單獨拿了出來,作為stop包,並將PI service字段置為P_PROGRAM。

再看step 7的stop

比起snap 7的stop,step 7在其基礎上又額外有兩個pdu,都是userdata,我們一個一個看

結合上面的知識我們知道:直接看function,0000標識push,0100標識是cpu類的方法,子方法說明這是診斷信息。而下面data中的cpu diagnostic message也就是診斷信息的具體內容,給了倆理由,一個是stop操作導致停止;一個是SFB 20停止。SFB的全稱是system function block,系統功能塊,這是為用戶提供的程序集合,可以理解為設備系統的一部分,它是不能被修改刪除的。

第二個包就有意思了,首先和上面一樣是一個push,但這次的類是mode-transition,這個可是個新東西。

該類的方法用來切換設備的工作狀態,在該類的包中沒有Data段了,僅僅靠Current mode來決定要做什么。圖中為stop,即停止運行的意思。除此之外,常用到的還有Warm Restart(暖啟動,重啟程序,但數據不變)、Hot Restart(完全從停止的狀態開始運行)、Cold Restart(重啟,並重置數據)、RUN(運行)等等。

 

step7_s300_AuthPassword.pcapng

該流量包是step 7 軟件對plc進行密碼修改,如下:

前兩個包是讀取CPU狀態的,和上面分析的相同,不再廢話,直接從第三個開始看

這次的類又變了,成了security,這個類實現的功能非常少,就是一個設置密碼,一個清除密碼,如圖這里subfunction標識了是設置密碼,data就是加密后的新密碼。

加密過程非常的簡單:

首先對前兩個數與0x55進行異或操作0x21^0x55 = t ,0x3a^0x55 = o

接着對剩下的數操作,操作為與自己距離為-2的數進行異或,再與0x55異或,如:0x1b^t = o

腳本如下:

list = [0x21,0x3a,0x1b,0x1d,0x6e,0x68,0x1b,0x1d] passwd = [] for i in range(0,len(list)): if i==0 or i==1: passwd.append(chr(list[i]^0x55)) else: passwd.append(chr(list[i]^0x55^list[i-2])) print passwd 

解得新設置的密碼為toor 。第四個包為回應,沒有特別之處,剩下兩個同樣是查詢信息。

 

s7comm_downloading_block_db1

大體看一下流量包

一開始是建立通信的操作,之后對設備信息進行了查詢,關鍵是后面,出現了block function和resquest download,我們一點點看

可與看到為塊方法類,這就需要詳細解釋一下西門子設備里的塊到底是怎么樣一個概念了。西門子的plc程序采用的是結構化設計,就像是我們的c語言,我們會分成很多模塊進行編寫(包括程序、數據),最后在main函數里調用,而塊這個概念就是對應着我們c語言里的不同模塊。

  • OB,object block,相當於main函數,由它去調用其他塊
  • SFB、SFC,前面提到過,就相當於是系統給你寫好的函數,直接調用就完事了
  • FB、FC,自己寫的函數,可以在OB中調用
  • DB,數據塊,放數據的

可以看到系統函數和自己寫的函數都有C和B的區分,最開始接觸時,就簡單的理解為,C的就是沒有全局變量的函數,沒有存下來什么;而B就是帶全局變量的函數,它修改了全局變量。

當然,上面的理解有些簡單粗暴,但卻很有道理。B就是block,而這個block是指DB,B不光是有函數,它還有自己的數據塊用來存放數據,這個數據塊也叫做背景數據塊;而C呢則是使用的共享的數據塊,調用時臨時分配給他一塊數據塊,用完就收回來,它不會對數據進行持續性的保留。

舉個栗子,如果你設備上有1、2兩個器件,他們各自有各自的運行狀態和收集到的數據,如果你執行的操作並沒有涉及到數據,那可以用B,但如果你要將各自的數據收集,那就要用有背景數據塊的C了。

聊完了什么是塊之后我們繼續看這個包,子方法是1,意思是列出所有的塊,除了該方法外,該類還有:

  • 列舉塊類型(List blocks of type)
  • 讀取塊的信息(Get block info)

我們之后還會看到,先看看這包的回復

可以看到和上一篇文章中的read var同樣使用了item來組織內容,item包含塊的類型和數量,OB作為s7的main,必然是1個,FC、FB數量則取決於用戶的定義,而SFC、SFB的數量則和系統掛鈎。

之后幾組(一個request和一個response組成)包都是重復操作,直到37,使用了Get block info的方法

很顯然block type指定了塊的類型,而number則是塊的編號,這里涉及到了一個新的概念,文件系統

  • P(Passive module):被動文件系統
  • A (Active module):主動文件系統
  • B (Active as well as passive module):主被文件系統

這里的意思就是讀取第一個DB塊

接着看response,可以看到最關鍵的字段為Error code,根據上面item我們知道DB塊實際上是0,根本沒有number=1的情況,所以不能回復相應的數據,這時就會回應error code,這里的error code即沒有對應的塊。data中的內容也是”對象不存在“。

相應的如果數據塊存在的話,回復的數據就應該是DB的數據。

往下走看到了request download,它是job包的一種,所以一定是(job,ack_data)這樣的組合。主要關注的是

filename,由幾個字段共同組成,用來唯一指定一個塊

  • file identifier,文件標識符一般由_ (Complete Module)、$ (Module header for up-loading)兩種
  • block type,塊的類型,這里是0A
  • block number也就數塊的編號
  • 文件系統,上面有說過。

response很簡單,這里就不再看了。接着往下走download block包

可以看到和request download差不多,主要看看response的包

可以見到,這次帶回了數據,還有個關鍵地方,Function status,它提示我們,還有更多的數據在后面。所以我們可以看到,后續的流量中一直再重復job、ack_data直到出現ended標識才算是真正的完成了一組數據的下載。

在之后,會調用PI-Service的_INSE來激活下載的塊,這樣才算是真正完成了下載的任務。

總結一下,當要對一個塊進行下載操作時,往往需要如下幾步:

查看塊是否存在(Block類中的Get block info) —> 請求下載(request download) —> 下載(由於數據過多可能重復多次) —> 激活塊(PI-Service的_INSE)

除此之外我們還可以看到,在激活塊后主機10發起來一個RST的請求與設備斷開了連接,然后又重新連接,我們並不清楚流量包抓取過程中的實際情況,只能推測有可能是因為更新了數據,所以主機與設備重新建立了通信。

 

總結

某大佬說過,安全不是ctf。我們可以看到比賽題目中的S7comm並沒有涉及到文章中的很多知識,但是這些東西我認為也十分重要,實際過程中我們接觸的更多也是這樣的流量包,只有掌握好這些最基礎的知識,才能更進一步。


免責聲明!

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



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