针对工业控制系统中最常用的Modbus协议,爬取了约1万条数据,利用wireshark工具对Modbus协议结构进行了初步分析,初步得到了modbus协议的特征,modbus协议的功能字在协议中的出现的位置是可以推算出来的,我们选取modbus协议的功能字和功能字后连续的两位字节码总共三位字节码作为modbus协议的特征,如下图所示被红框圈出来的即我们选择的三位字节码,使用Random Forest,SVM和GBDT三种分类算法,对约10000条随机数据进行训练,并用约20000条随机数据进行验证。

Random Forest分类器

Random Forest即随机森林就是通过集成学习的思想将多棵树集成的一种算法,它的基本单元是决策树,而它的本质属于机器学习的一大分支——集成学习(Ensemble Learning)方法。

正确率为(17541+7780)/(18402+7780)*100%=96.7%

召回率为17541/(17541+0)*100%=100%

SVM分类器

支持向量机(Support Vector Machine)是Cortes和Vapnik于1995年首先提出的,它在解决小样本、非线性及高维模式识别中表现出许多特有的优势,并能够推广应用到函数拟合等其他机器学习问题中。
支持向量机方法是建立在统计学习理论的VC 维理论和结构风险最小原理基础上的,根据有限的样本信息在模型的复杂性(即对特定训练样本的学习精度,Accuracy)和学习能力(即无错误地识别任意样本的能力)之间寻求最佳折衷,以期获得最好的推广能力(或称泛化能力)。

正确率为(17541+7606)/(18576+7606)*100%=96%

召回率为17541/(17541+0)*100%=100%

GBDT分类器

GBDT是boosting算法的一种,按照boosting的思想,在GBDT算法的每一步,用一棵决策树去拟合当前学习器的残差,获得一个新的弱学习器。将这每一步的决策树组合起来,就得到了一个强学习器。

正确率为(17541+8618)/(18576+7606)*100%=99.9%

召回率为17541/(17541+0)*100%=100%

综合对比三种分类器的分类结果,三种分类器都可以做到召回率100%,即可以将所有的modbus协议正确识别出来,但对于非modbus协议都存在的误判,其中GBDT分类器的正确率最高。

代码如下,使用了Python中的sklearn包。

import pyshark
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.svm import SVC
import re
import numpy as np
#切割字符串
def cut_text(text, lenth): # lenth 表示切割的子字符串的长度
  textArr = re.findall('.{'+str(lenth)+'}', text)
  textArr.append(text[(len(textArr)*lenth):])
  if textArr[-1] =='': textArr.pop()
  return textArr
#SVC分类器
def Classifier1(X,y,XX):
  model = SVC(C=5.0)
  #用X(输入),y(输出)来训练
  model.fit(X,y)
  #对XX进行预测
  predicted = model.predict(XX)
  return predicted
#RandomForest分类器
def Classifier2(X,y,XX):
  model = RandomForestClassifier()
  model.fit(X,y)
  predicted = model.predict(XX)
  return predicted
#GBDT分类器
def Classifier3(X,y,XX):
  model = GradientBoostingClassifier()
  model.fit(X,y)
  predicted = model.predict(XX)
  return predicted

train=[]
test=[]
y=[]
target_test=[]

#训练集1
cap=pyshark.FileCapture("./train/train.pcap",include_raw=True,use_json=True)
for cap_ in cap:
  strr=str(cap_.layers[-1].value)
  if(strr[0]=='[' or strr[0]=='\'' ):
    newstr=strr[2:8].ljust(6,'0') 
  else:
    newstr=strr[0:6].ljust(6,'0') 
  traindata=cut_text(newstr,2)
  print(traindata)
  a= [int(x,16) for x in traindata]
  train.append(a)
  y.append(1)
cap.close()

#训练集2
cap=pyshark.FileCapture("./train/train2.pcapng",include_raw=True,use_json=True)
for cap_ in cap:
  strr=str(cap_.layers[-1].value)
  if(strr[0]=='[' or strr[0]=='\'' ):
    newstr=strr[2:8].ljust(6,'0') 
  else:
    newstr=strr[0:6].ljust(6,'0') 
  traindata=cut_text(newstr,2)
  print(traindata)
  a= [int(x,16) for x in traindata]
  train.append(a)
  y.append(0)
cap.close()

traindataz=np.array(train)
target=np.array(y)

print(traindataz)
print(target)

#测试集1
cap=pyshark.FileCapture("./test/test.pcap",include_raw=True,use_json=True)
for cap_ in cap:
  if(cap_.highest_layer=='MODBUS_RAW'):
    target_test.append(1)
  else:
    target_test.append(0)
  strr=str(cap_.layers[-1].value)
  if(strr[0]=='[' or strr[0]=='\'' ):
    newstr=strr[2:8].ljust(6,'0') 
  else:
    newstr=strr[0:6].ljust(6,'0') 
  traindata=cut_text(newstr,2)
  a= [int(x,16) for x in traindata]
  test.append(a)
cap.close()

#测试集2
cap=pyshark.FileCapture("./test/test2.pcapng",include_raw=True,use_json=True)
for cap_ in cap:
  if(cap_.highest_layer=='MODBUS_RAW'):
    target_test.append(1)
  else:
    target_test.append(0)
  strr=str(cap_.layers[-1].value)
  if(strr[0]=='[' or strr[0]=='\'' ):
    newstr=strr[2:8].ljust(6,'0') 
  else:
    newstr=strr[0:6].ljust(6,'0') 
  traindata=cut_text(newstr,2)
  a= [int(x,16) for x in traindata]
  test.append(a)
cap.close()

#测试集3
cap=pyshark.FileCapture("./test/test3.pcap",include_raw=True,use_json=True)
for cap_ in cap:
  if(cap_.highest_layer=='MODBUS_RAW'):
    target_test.append(1)
  else:
    target_test.append(0)
  strr=str(cap_.layers[-1].value)
  if(strr[0]=='[' or strr[0]=='\'' ):
    newstr=strr[2:8].ljust(6,'0') 
  else:
    newstr=strr[0:6].ljust(6,'0') 
  traindata=cut_text(newstr,2)
  a= [int(x,16) for x in traindata]
  test.append(a)
cap.close()

#测试集4
cap=pyshark.FileCapture("./test/test4.pcap",include_raw=True,use_json=True)
for cap_ in cap:
  if(cap_.highest_layer=='MODBUS_RAW'):
    target_test.append(1)
  else:
    target_test.append(0)
  strr=str(cap_.layers[-1].value)
  if(strr[0]=='[' or strr[0]=='\'' ):
    newstr=strr[2:8].ljust(6,'0') 
  else:
    newstr=strr[0:6].ljust(6,'0') 
  traindata=cut_text(newstr,2)
  a= [int(x,16) for x in traindata]
  test.append(a)
cap.close()

#测试集5
cap=pyshark.FileCapture("./test/test5.pcap",include_raw=True,use_json=True)
for cap_ in cap:
  if(cap_.highest_layer=='MODBUS_RAW'):
    target_test.append(1)
  else:
    target_test.append(0)
  strr=str(cap_.layers[-1].value)
  if(strr[0]=='[' or strr[0]=='\'' ):
    newstr=strr[2:8].ljust(6,'0') 
  else:
    newstr=strr[0:6].ljust(6,'0') 
  traindata=cut_text(newstr,2)
  a= [int(x,16) for x in traindata]
  test.append(a)
cap.close()

#测试集6
cap=pyshark.FileCapture("./test/test6.pcap",include_raw=True,use_json=True)
for cap_ in cap:
  if(cap_.highest_layer=='MODBUS_RAW'):
    target_test.append(1)
  else:
    target_test.append(0)
  strr=str(cap_.layers[-1].value)
  if(strr[0]=='[' or strr[0]=='\'' ):
    newstr=strr[2:8].ljust(6,'0') 
  else:
    newstr=strr[0:6].ljust(6,'0') 
  traindata=cut_text(newstr,2)
  a= [int(x,16) for x in traindata]
  test.append(a)
cap.close()

testdataz=np.array(test)  
target_test=np.array(target_test)  


print(testdataz)

TP=0
FP=0
TN=0
FN=0
#这里选择使用的分类器
result=Classifier3(traindataz,target,testdataz)
print(result) 

for index in range(0,len(result)):
  if(result[index]==target_test[index]):
    if(target_test[index]==1):
      TP=TP+1
    else:
      TN=TN+1
  else:
    if(target_test[index]==1):
      FN=FN+1
    else:
      FP=FP+1

print(TP,FP)
print(FN,TN)



说点什么
支持Markdown语法
好耶,沙发还空着ヾ(≧▽≦*)o
Loading...