◆楊柳鵬
(河北大學 河北 071002)
簡談MC7字節碼
◆楊柳鵬
(河北大學 河北 071002)
本文簡單介紹MC7字節碼和已知的MC7文件格式,并且說明對MC7文件進行修飾的過程,闡述基于SNAP7庫的PLC注入程序,最后給出一個成功的范例來進一步佐證MC7字節碼對PLC的影響。
MC7字節碼;西門子PLC;注入
Stuxnet是一個具有劃時代意義的病毒。作為世界上首個以關鍵工業設施為目標的破壞性病毒,它的出現標志著工業級黑客登上歷史舞臺。直到今天,Stuxnet的感染方式仍舊是不少針對工業控制系統的病毒的模仿對象。其在西門子PLC中執行的惡意代碼由MC7字節碼構成。
西門子PLC的編程語言主要有五種:LAD、STL、FBD、SCL、GRAPH。其中,LAD和STL是常用的兩種基本語言。然而無論采用哪種語言編程,編碼完成后源碼都將自動地轉化為STL。最后編程軟件將由MC7字節碼構建產生MC7文件。簡單來說就是把代碼包裝成二進制文件。MC7字節碼是西門子PLC的CPU可以理解并執行的原生代碼。
這是FC100塊:
其STL如下:
其中有意義的字節和其對應位置的作用:
0707 :(第1-2字節)MC7文件開始標志
01:(第3字節)塊標識,01表示用戶塊、03表示系統塊
01:(第4字節)塊類型,01為常規類型、03為配置文件、05為背景數據
01:(第5字節)程序語言種類,STL對應01、LAD對應02、FBD對應03、SCL對應04、GRAPH對應06、05和07表示編寫DB塊或SDB塊(即用數據類型、地址、大小描述)
0C:(第6字節)塊種類,OB塊對應08、DB塊對應0A、SDB塊對應0B、FC塊對應0C、SFC塊對應0D、FB塊對應0E、SFB塊對應0F
0064 :(第7-8字節)塊號
0000 0074 :(第9-12字節)文件總長度。將74化為十進制116,對應此MC7文件字節總數(116個字節)
0000 :(第13-14字節)數據類型。0800表示系統配置文件,0000表示用戶數據文件
0000 :(第15-16字節)塊是否處于保護狀態。0003表示塊被保護,0000表示塊不被保護
02ab 2735 2d03:(第17-22字節)最后修改時間。其中02ab 2735(第17-20字節)表示毫秒(44771125毫秒),2d03(第21-22字節)表示天數(11523天)?;鶞蕰r間為1984年1月1日。此段代碼表示該MC7文件最后修改時間為2015年7月20日12:26:11.125
03a1 6383 21a7:(第23-28字節)最后創建時間。計算方法等同于最后修改時間
001 c:(第29-30字節)內部塊數據表長度
0006 :(第31-32字節)跳轉指令內存
0014 :(第33-34字節)本地數據長度
000 a:(第35-36字節)執行代碼長度
c000:(第37-38字節)對應語句A I0.0
c100:(第39-40字節)對應語句A I0.1。對于A I指令,字節碼占用兩個字節,以c開頭,用緊跟c后的半個字節表示位地址(即I0.1的.1),用一個字節表示字節地址(即I0.1的0)
ca00:(第41-42字節)對應語句O I0.2。對于O I指令,字節碼占用兩個字節,以c開頭,用緊跟c后的半個字節-8的值表示位地址(即I0.2的.2),用一個字節表示字節地址(即I0.2的0)
d880:(第43-44字節)對應語句= Q0.0.對于= Q指令,字節碼占用兩個字節,以d開頭,用緊跟c后的半個字節-8的值表示位地址(即Q0.0的.0),用后一個字節-80的值表示字節地址(即Q0.0的0)
6500 :(第45-46字節)對應語句BE。中止在當前塊中的程序掃描,跳轉到調用當前塊的程序塊
0100 :(第47-48字節)執行代碼區結束標志。
MC7字節碼可以用于設計西門子PLC的仿真程序,或脫離西門子PLC官方編譯器S7kafapx.exe實現對程序的修改(Stuxnet核心功能)。
3.1.注入原理
3.1.1 西門子S7Comm協議
S7Comm協議是S7通訊協議簇中的一種,用以傳輸塊。
3.1.2 SNAP7庫函數
SNAP7是一個直接和西門子S7系列PLC對接的開源的多平臺的以太網通信軟件。我們主要用兩個函數:
Cli_FullUpload(),從PLC的CPU上傳一個完整的塊
Cli_Download(),從我們的PC向PLC的CPU下載MC7文件
具體使用方法請查詢《SNAP7-refman》。
3.2 修飾
這里的修飾指對自由循環組織塊OB1的修飾。在注入前,參照上文給出的文件格式用十六進制編輯器手動寫出完成含有攻擊代碼的MC7文件(在這里我把它稱作Payload),以“被調用塊名_被調用塊號.mc7”格式保存。注入時可注入MC7文件所在的整個文件夾,但被調用塊只能唯一。由于PLC在設計時考慮了生產線的連續工作問題,所以接收一般程序時不會重啟,我們便在OB1的原始執行代碼前插入一個用來調用塊的函數調用寫好的Payload。這樣在下一個刷新周期,CPU便會執行我們的攻擊代碼。
這里需要注意,CALL函數調用塊時需要添加程序塊參數和背景數據塊,所以我采用UC函數,即無條件調用。
構建注入器時采用如下代碼定義調用FC塊代碼:
uint8_tuc[] = {
0xFB, 0x70, 0x00, 0x00,
0x70 , 0x0B, 0x00, 0x02,
0xFE, 0x03, 0x00, 0x00, 0x00, 0x00,
0xFE, 0x0B, 0x00, 0x00, 0x00, 0x00,
0x30 , 0x03, 0x00, 0x00,
0x30 , 0x03, 0x00, 0x00,
0x70 , 0x07
};
除了插入調用塊函數,我們還應按照插入代碼大小修改OB1的原始MC7文件的“執行代碼長度”和“文件的總長度”區域。
3.3 情景假設
假設我們已獲得一個由許多PLC、監控計算機、傳感器、HMI和其它一些設備組成的ICS結構中的網絡訪問權限。在這種情形下,我們可獲得目的PLC地址,進而篡改邏輯。
范例采用PLCSIM仿真器模擬被注入的PLC。使用NetToPLCSIM軟件建立物理網絡接口和仿真PLC的連接,模擬和仿真PLC的通信。
采用上文例子“FC_100.mc7”。
注入完成后打開Step7主面板選擇“在線”,此時會發現OB1塊后新增FC100塊。觀察OB1塊會發現調用函數“UCFC100”已插入其中。由于存在塊調用PLCSIM增加了邏輯:
I0.0和I0.1同時置1則Q0.0置1;I0.2置1則Q0.0置1。
[1]Dillon Beresford. Black hat. In Siemens Simatic S7 PLC Exploitation[M].NSS Labs, 2011.
[2]DavideNardella.SNAP7[EB/OL]. http://snap7.sourceforg e.net/.