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