S7 COM PLC狀態查詢 - 讓你知道攻擊是否生效

好的,這是一個非常實際的問題,在進行網路監控或開發自己的客戶端時至關重要。

要從 S7 封包中判斷 PLC 的狀態 (主要是 RUNSTOP),沒有一個固定的欄位存在於每一個封包中。您必須透過攔截並解析特定的請求-回應 (Request-Response) 封包組合來實現。

以下是三種主要的方法,從最直接到最間接:

方法一:主動查詢系統狀態列表 (Read SZL) - 最準確的方法

這是最標準、最可靠的作法。您的應用程式(或您正在監控的客戶端)會主動向 PLC 發送一個「讀取系統狀態列表」的請求,PLC 會在回應中明確告知其當前狀態。

  1. 要觀察的封包:【請求】

    • 您會看到一個由客戶端發往 PLC 的封包。
    • PDU 類型 (ROSCTR): 0x07 (Userdata)
    • 參數 (Parameters): 在 Userdata 的參數部分,會包含一個「Read SZL」(讀取 SZL) 的子功能請求。
    • 關鍵識別碼 (SZL ID): 請求中會指定要讀取的 SZL ID。用於查詢 CPU 狀態的 ID 通常是 0x04240x0132 (取決於 CPU 型號和韌體)。
  2. 要觀察的封包:【回應】

    • PLC 會回覆一個 PDU 類型為 0x03 (Ack_Data) 的封包。
    • 這個封包的資料區 (Data) 就包含了您要的狀態資訊。
  3. 如何判斷 (解析回應封包的 Data 區): _ 在 SZL 回應的資料區中,會有一個特定的位元組 (Byte) 用來表示 PLC 的運行狀態。

    • SZL ID 0x0424 的回傳值為例,其結構中偏移量 (offset) 為 2 的位元組就是狀態碼:
回應資料區 (Offset 2) 的值代表的 PLC 狀態
0x00(未知/中間狀態)
0x01STOP
0x02STARTUP (啟動中)
0x03RUN_OB (執行啟動組織塊)
0x04RUN
0x05FREEZE (凍結)
0x06HOLD (保持)
0x07LINK_UP (正在連線)
0x08RUN (與0x04意義相同,但在 S7-400 中更常見)

結論: 透過監控這個 SZL 請求-回應週期,並解析回應封包資料區的特定位元組,就能最精確地得知 PLC 當前的運行模式。


方法二:分析操作回應的錯誤碼 - 間接推斷法

如果您沒有主動發送狀態查詢,可以透過分析其他操作(如寫入變數)的回應來間接推斷 PLC 的狀態。

  1. 場景: 您的應用程式嘗試向 PLC 寫入一個變數 (Write Variable)。

  2. 要觀察的封包:【請求】

    • 一個由客戶端發往 PLC 的封包。
    • PDU 類型: 0x01 (Job Request)
    • 功能碼 (Function Code): 0x05 (Write Variable)
  3. 要觀察的封包:【回應】

    • PLC 回覆一個 PDU 類型為 0x03 (Ack_Data)0x02 (Ack) 的封包。
    • 關鍵在於 S7 標頭中的 錯誤碼 (Error Code) 欄位。
  4. 如何判斷 (解析回應封包的 S7 Header):

    • S7 Header 的最後 4 個位元組中,包含了錯誤類別 (Error Class) 和錯誤碼 (Error Code)。
    • 如果錯誤碼為 0x0000: 表示操作成功。這強烈暗示 PLC 處於 RUN 模式,因為在 STOP 模式下通常不允許寫入大部分變數。
    • 如果回傳特定錯誤碼: 當 PLC 處於 STOP 模式時,嘗試寫入會失敗,並回傳一個特定的錯誤碼,指出當前狀態下不允許此操作。最常見的錯誤碼之一是:
      • 錯誤類別 0x81 (應用關係錯誤), 錯誤碼 0x04 (物件狀態衝突/上下文不可用)。這個錯誤 0x8104 經常表示 “The context is not available”,一個典型的原因就是 CPU is in STOP mode

    結論: 這種方法不夠直接,但非常實用。如果您監控到一個寫入操作成功了,可以推斷 PLC 在 RUN 模式;如果失敗並回傳了 0x8104 這類錯誤,就可以推斷 PLC 在 STOP 模式。


方法三:監控狀態變更命令 - 觀察法

這種方法不能查詢當前的穩定狀態,但可以即時捕捉到狀態變更的意圖

  1. 要觀察的封包:【請求】

    • 您需要監控由客戶端發往 PLC 的特定控制命令封包。
  2. 如何判斷:

    • 看到 PLC Stop 命令:
      • PDU 類型: 0x01 (Job Request)
      • 功能碼: 0x29
      • 這表示有客戶端正在命令 PLC 進入 STOP 模式。
    • 看到 PLC Control 命令:
      • PDU 類型: 0x01 (Job Request)
      • 功能碼: 0x28
      • 這表示有客戶端正在命令 PLC 進行 Start, Hot RestartCold Restart

    結論: 這種方法讓您知道狀態即將改變,但需要結合 PLC 的回應封包 (Ack) 才能確認命令是否被成功執行。


總結

方法優點缺點適用場景
方法一 (Read SZL)最準確、最直接,提供詳細的狀態資訊。需要主動發送特定請求,封包特徵較複雜。開發自己的監控軟體,需要精確、即時的狀態顯示。
方法二 (分析錯誤碼)被動監控即可,無需額外發包,實用性高。不夠直接,依賴於其他操作的發生,且可能有多種原因導致同一錯誤。在現有網路中進行被動流量分析,快速推斷 PLC 狀態。
方法三 (監控命令)即時性最高,能第一時間發現狀態變更的企圖。無法得知當前的穩定狀態,只能看到「變化」的瞬間。安全監控,用於檢測是否有未授權的啟停操作。

聯絡作者

歡迎透過以上方式與我交流資安技術與 CTF 心得!