現在網上有很多類似的文章、其實這一篇也借鑒了很多其他博主的文章。
寫這篇文章的重點是在於解析功能和報文、對Dnp3這個協議並不會做很多介紹。
那我們就開始吧
上圖則為dnp3協議整體的報文模型(點擊紅框部分可以直接跳轉至應用層的hex流)
Dnp3協議 一共分為三層 鏈路層、傳輸層、應用層。
Dnp3看似很臃腫、但是他的報文格式倒是很簡潔。
Dnp3 協議並沒有對特定的功能做特定的結構、而它的結構基本都可以共用
Dnp3 真正決定功能的功能碼處於應用層、其他層的功能碼只能算是一個大體的范圍
接下來 還是從Wireshark 解析的報文進行出發
read功能
發包
我分部分介紹吧
下圖為鏈路層
Start Bytes byte[0][1] 05 64 為數據開始的字節 固定為0x0564就可以
Length byte[2] 14為長度、Dnp3的長度計算有一些獨特、 它包括鏈路報文頭中的5個字節,超出5個字節的部分為傳輸層報文的長度,也就是說,鏈路層報文長度計數中不含CRC校驗碼字節。鏈路層報文長度的最小值為5,最大值為255。一條DNP鏈路層報文的最短長度為鏈路報文頭的長度:10個字節。一條DNP鏈路層報文的最大長度為10+(250/16)×18+(250+2)=292字節
Control byte[3] c4 鏈路控制字節
第一位為 表明發送的方向
第二位為 表示發送的設備是主設備還是從設備
第三位為 如果是請求則為糾錯,如果是回應則為保留位
第四位為 這一位是說明第三位是否有效、在圖上為0則為Frame count bit(意譯為計數但實為糾錯)未開啟。
后四位為 功能碼(這個功能碼則是規定了大體的方向,更像是包的類型)
對於主設備來說
0,鏈路重置
1,進程重置
3,請求發送數據
4,直接發送數據
9,查詢當前鏈路的狀態
對於從設備來說
0,同意
1,拒絕
11,回應當前鏈路狀態
Destination byte[4][5] 00 04 目標的地址
Source byte[6][7] 01 00 源地址
Checksum byte[8]byte[9] e9 b6 為校驗碼、DNP3用的是Crc算法
到這里整個鏈路層已經介紹完畢了、后續的其他功能的鏈路層也都是一致的。
下圖為傳輸層
很簡單…只有一個字節
第一位是final,標識是否為最后一個包
第二位是first,標識是否為最后一個包
后六位為seq,表明當前是第幾個包
Data chunks 與 [1 DNP 3.0 AL Fragment 14(bytes): #17(14)]
這些就不用去研究它、它所包含的字節是應用層的。只不過是Wireshark把它解析出了一欄(我並不能說是Wireshark解析錯誤還是別有用意但是這些不重要、不用在意這兩塊就對了)
下圖為應用層
Control byte[0] c1 這里一共是八個位
第一位為 表明是否為第一個
第二位為 表明是否為最后一個
第三位為 表明是否需要回復,圖中即表示不需要回復
第四位為 表明是否為主動提出的
后四位為 為隊列號,這里的設計和上面傳輸層的類似
Function Code byte[1] 01 這里就是控制功能的具體方向、若是讀則01 若是寫則02(也有其他類型的功能碼)
那接下來看Read Request這個結構體內的數據
這個結構體內的數據還是共處於應用層結構之內
這一塊的意思也就是為 要去讀取什么(限制對象讀取什么)
Object byte[2] (這里是Wireshark解析有些問題、obj和var解析到一塊了實際是為分開的) 3c 這里表達的意思為 要讀取的數據的基本類型
Object byte[3] 02 進一步說明數據的類型,比如是模擬的話,那你是32位還是64位 (有一份表格說明類這些數據類型,請搜附錄一 數據類型)
Qualifier field byte[4] 06 為限定詞
第一位為 保留,wireshark同樣沒有給出解析信息
第三位為 限定碼,這個不太好理解,簡單點說是表明一個數據對象的索引的字節數
后四位為 也就是指定的范圍的意思,圖中6即為讀取所需類型的全部數據。往后就是最后的對象了,這個包中並沒有。
回包
還是分層吧 這一層與發包是一樣的 為鏈路層 所回應hex字節類型也都是一樣
傳輸層的結構也是一樣
應用層會有一些少許的不同
Control byte[0] c1 這里一共是八個位
第一位為 表明是否為第一個
第二位為 表明是否為最后一個
第三位為 表明是否需要回復,圖中即表示不需要回復
第四位為 表明是否為主動提出的
后四位為 為隊列號,這里的設計和上面傳輸層的類似與發包是一樣的
Function code byte[1] 81 功能碼 這里就是代表回應的意思
Internal byte[2]byte[3] 00 00 可以看到這個很雜亂,其實也只是表明的是從設備的“狀態”問題,包括像是設備是否重啟、設備是否有問題、時間同步等等,這里就不在一一說明了。
但是細心的就就可以發現、dnp3整體的報文最后是包含了60 e6 這兩個字節,但是在Wireshark 解析中 並沒有解析到 那么這兩位是干什么的呢。我也查了很多資料也對這最后兩位並沒有確切的解釋、姑且認為他只是dnp3攜帶的數據元素吧。
Write
發包
整體來看 鏈路層和傳出層都是一致的還是依舊說應用這一層吧。
Control byte[0] c0 這里一共是八個位
第一位為 表明是否為第一個
第二位為 表明是否為最后一個
第三位為 表明是否需要回復,圖中即表示不需要回復
第四位為 表明是否為主動提出的
后四位為 為隊列號,這里的設計和上面傳輸層的類似
Function code byte[1] 02 功能碼 這里所代表的意思的就寫了
接下來就是Write Request 這個結構體內的數據
Object byte[2] (這里是Wireshark解析有些問題、obj和var解析到一塊了實際是為分開的,而且也沒有給他確切的字段名) 50 這里表達的意思為 要讀取的數據的基本類型
Object byte[3] 01 進一步說明數據的類型,比如是模擬的話,那你是32位還是64位
Qualifier field byte[4] 00
第一位為 保留,wireshark同樣沒有給出解析信息(而且解析到了一起)
第三位為 限定碼,這個不太好理解,簡單點說是表明一個數據對象的索引的字節數
后四位為 也就是指定的范圍的意思
接着往下 number of items這個結構體內
Start byte[5] 07 如子譯一樣 只是為要寫的項目的開始位置
Stop byte[6] 07 在哪里停
Proint number 7 這個結構體
這個結構體也很明了 7號設備是否重啟,那么它的值為00 就是不重啟。。
回包
與之前的都一樣= = 其實這個dnp3協議它的報文結構基本都是一樣的。
剩下的就不在累述了,基本上你能看懂一個報文,其他的也都可以看懂。