PRISMA原理以及python包使用介绍
2016-10-17 20:35
489 查看
刚开始一直在寻找PRISMA的相关文档,感觉很少,结果后面才发现在下载包中的vignettes以及inst文件下面,有对它的详细介绍以及示例展示,还是自己不够细心,导致浪费了很长一段时间。QAQ
Testing-based feature dimension reduction(降维);
最优矩阵分解
整体流程图:
在目录/inst/extdata中有提供测试数据集asap,其中原始数据asap.raw如图所示:
asap.cfg是Sally的配置文件,通过如下命令得到PRISMA输入。
这里笔者想说一下很重要的一点,就是sally是干嘛的(之前很久没有弄懂,终于看了源码以及帮助文档之后弄懂了)。
下面以granularity为tokens,输出格式为“text”为例:
首先sally会根据配置文件中设定的“ngram_delim”来对原始的“.raw”数据进行划分,当然这里还会有一个自动对URI进行解码的过程。划分了之后,就得到了很多的tokens,把所有的报文序列中分割得到的tokens都作为一个特征,也作为初始矩阵的一维,所以才会有图中的“16777216”这么大的维数,很显然这是一个稀疏矩阵,选择用这种格式输出其实也可以看做是用最简单的方法来存储结果,因为真的用矩阵存会相当大,所以就只记录下来“value”为“1”的项;
然后,对于这些token一个一个的在报文序列中进行匹配,如果哪里有匹配的就会做一个记录,也就是下面的这种形式
每个匹配的token特征由三部分组成:
dimension :标识这个特征的index (specifies the index of the dimension),因为划分后得到了很多很多的token,每一个token都是一个特征(后面的reduction就是为了获得具有代表性的token),为了标识这些特征所以每一个特征都有一个index 。
feature: a textual representation of the feature
value: the value at the dimension.
这里笔者将详细讲解sallyProcessing.py函数:
相信熟悉python的很快就能看明白,笔者是菜鸟所以自己抠了一个短的输入文件进行测试,便于理解。
输入:
增加了print之后的显示:
输出:
实际上这里的sallyProcessing.py主要作用就是把.sally文件中格式变换一下,将“.sally”文件中“148165591:6.0:1,417718110:NT:1,709591711:Windows:1”这种格式的内容中的中间值(这里是6.0和NT以及Windows)读出来存在.fsally中,其实也就是得到分好的gram的集合,也作为PRISMA的输入。
这一部分主要是为了比较高效地完成token划分过程,然后将划分token的结果转换成PRISMA比较好处理的输入。
进入R环境,加载数据
读取asap数据集:
可以看到由10000个样本,然后有10034个特征(这些特征就是上面得到的token,虽然最初划分的得到的tokens很多,但是由于会有重复的,通过sallyProcessing.py处理之后,将tokens都提取出来了,会得到很多相同的token,于是就会合并掉,最终这里只有10034个tokens了也就是10034个特征),通过处理变成了一个12*24的矩阵。
所谓的12*24是因为PRISMA会将一些tokens整合到一个集合中,用这一个集合来作为一个特征,这个在另一篇文章中有提到对其的配置方法,具体是通过计算token之间的关联系数(correlation coefficient)将关联系数相近的合并为一组,如图第二行就是将“admin.php par action”作为一个特征,这里有12个(或者组更合适)特征;
c87c
首先在提取报文结构的时候,由于数据集庞大,分析时候必须关注一些具有代表性的特征,所以不能把初步划分的10034个tokens都作为最终分析的特征,需要进行降维,去除掉多余的特征(如时间戳、cookie等等,这些都是随机出现,而且某一种取值基本都只会出现一次)。
论文中提到,会使用stastical test-driven dimension reduction,排除掉特征集中的constant以及volatile特征,详细参见PRISMA的论文。
这里的test去除了值出现频繁很高以及很低的token,在实际报文序列中,这些可能对应着变值字段和一个定值字段,在找出具有代表性的特征的时候,丢掉了这些,但是在后面的template推断过程中又将其考虑进去了,这样才能得到更准确的格式信息。
扩展:这一步完成以后,报文数据就被转换到了向量空间,并且经过了降维,筛选出了具有代表性的token特征(详细的可以参考ASAP论文中的讲解),使用什么方法来提取报文格式以及状态机,个人觉得就可以“仁者见仁智者见智”了。
在PRISMA的论文中提到了两种聚类方法:
Part-based Clustring:
论文提到这种方法适用于Assembled of parts类型协议效果较好。先进行NMF,然后再按照NMF得到的坐标计算报文之间的相似度来聚类。
而具体怎么实现非负矩阵分解就不讲了(因为我也讲不清楚:-D囧:-D)。
Position-based Clustering:
论文中提到这种方法适用于Monolithic communication,where tokens are weighted according to their absolute position in the message,因为某些协议体现出position-dependent 特征,提出了一种weighted distance measure:
Templates:
首先需要说明,Markov模型的一个状态对应状态机中的一个状态,而每一个状态里面可能会有多个会话,一个会话中也会有多种格式的报文也就是会有多个Template。Learning Templates 的具体步骤如下:
根据之前的划分方法将原始报文序列tokenize;
根据Markov模型将原始报文划分成不同会话的报文;
对于Markov模型中的每一个状态
将相同token数目的报文放到一个group中
如果一个group中的报文在某一个相同的位置,有一个相同的token,那么就认为是最终Template中的一个定值字段,否则就认为是一个变值字段
最终会得到Markov模型中每一个状态的Template,这个Template代表了这个状态下通用的报文格式。需要注意的是,每一个状态可能会对应很多个template,因为这里是按照token数量进行的分组,每一组都会得到一个Template。
实际上这里做了很大的简化,会对得到的结果的准确率造成影响。
Rules:
所谓的Rules其实就是结合Markov模型,会话信息,原始报文,提取出Template中每一个字段的取值,这个就不用赘述了。
Introduction
PRISMA可以高效地处理sally输出文件,很快地处理n-gram过程;Testing-based feature dimension reduction(降维);
最优矩阵分解
整体流程图:
Loading the Data
首先需要 获得“.sally”文件,就是通过sally对原始网络流量进行处理;在目录/inst/extdata中有提供测试数据集asap,其中原始数据asap.raw如图所示:
asap.cfg是Sally的配置文件,通过如下命令得到PRISMA输入。
sally -c asap.cfg asap.raw asap.sally python sallyProcessing.py asap.sally asap.fsally
这里笔者想说一下很重要的一点,就是sally是干嘛的(之前很久没有弄懂,终于看了源码以及帮助文档之后弄懂了)。
下面以granularity为tokens,输出格式为“text”为例:
首先sally会根据配置文件中设定的“ngram_delim”来对原始的“.raw”数据进行划分,当然这里还会有一个自动对URI进行解码的过程。划分了之后,就得到了很多的tokens,把所有的报文序列中分割得到的tokens都作为一个特征,也作为初始矩阵的一维,所以才会有图中的“16777216”这么大的维数,很显然这是一个稀疏矩阵,选择用这种格式输出其实也可以看做是用最简单的方法来存储结果,因为真的用矩阵存会相当大,所以就只记录下来“value”为“1”的项;
然后,对于这些token一个一个的在报文序列中进行匹配,如果哪里有匹配的就会做一个记录,也就是下面的这种形式
417718110:NT:1,528173057:admin.php:1,542593949:5.1:1,709591711:Windows:1,1070264077:NeBkxkA0rw:1,1070607007:HTTP:1,1220141225:action:1,1369927740:de:1,1710609481:U:1,1720296684:GET:1,1920966484:9.20:1,2451033089:www.foobar.com:1,2452995035:cgi:1,2497091255:1.1:1,2543529916:Accept:1,2761047053:*:1,2844811140:Opera:1,3060078669:Host:1,3250181107:par:1,4032950582:rename:1,4261263756:User-Agent:1 line0
每个匹配的token特征由三部分组成:
dimension :标识这个特征的index (specifies the index of the dimension),因为划分后得到了很多很多的token,每一个token都是一个特征(后面的reduction就是为了获得具有代表性的token),为了标识这些特征所以每一个特征都有一个index 。
feature: a textual representation of the feature
value: the value at the dimension.
这里笔者将详细讲解sallyProcessing.py函数:
#!/usr/bin/python import sys from optparse import OptionParser usage = "usage: %prog in.sally out.fsally" parser = OptionParser(usage) (options, args) = parser.parse_args() if len(args) != 2: parser.print_help() sys.exit() sallyIn = file(sys.argv[1]) sallyOut = file(sys.argv[2], "w") # skip first line sallyIn.readline() allNgrams = {} count = 0 for l in sallyIn: count += 1 if count % 1000 == 0: print(count) info = l.split(" ") if info[0] == "": curNgrams = [] else: curNgrams = [ngramInfo.split(":")[1] for ngramInfo in info[0].split(",")] allNgrams.update(allNgrams.fromkeys(curNgrams)) sallyOut.write("%s\n" % " ".join(curNgrams)) sallyOut.write("%s\n" % " ".join(allNgrams.keys())) sallyOut.close() sallyIn.close()
相信熟悉python的很快就能看明白,笔者是菜鸟所以自己抠了一个短的输入文件进行测试,便于理解。
输入:
增加了print之后的显示:
输出:
实际上这里的sallyProcessing.py主要作用就是把.sally文件中格式变换一下,将“.sally”文件中“148165591:6.0:1,417718110:NT:1,709591711:Windows:1”这种格式的内容中的中间值(这里是6.0和NT以及Windows)读出来存在.fsally中,其实也就是得到分好的gram的集合,也作为PRISMA的输入。
这一部分主要是为了比较高效地完成token划分过程,然后将划分token的结果转换成PRISMA比较好处理的输入。
The PRISMA Data Set
对于上面得到的输入,可以通过如下方法加载加以展示。进入R环境,加载数据
R library("PRISMA")
loadPrismaData("asap")
读取asap数据集:
data(asap) asap
可以看到由10000个样本,然后有10034个特征(这些特征就是上面得到的token,虽然最初划分的得到的tokens很多,但是由于会有重复的,通过sallyProcessing.py处理之后,将tokens都提取出来了,会得到很多相同的token,于是就会合并掉,最终这里只有10034个tokens了也就是10034个特征),通过处理变成了一个12*24的矩阵。
所谓的12*24是因为PRISMA会将一些tokens整合到一个集合中,用这一个集合来作为一个特征,这个在另一篇文章中有提到对其的配置方法,具体是通过计算token之间的关联系数(correlation coefficient)将关联系数相近的合并为一组,如图第二行就是将“admin.php par action”作为一个特征,这里有12个(或者组更合适)特征;
asap$data
c87c
asap$group
Dimensionnality Reduction
上面得到了12*24的矩阵是经过了降维(这里可以参见ASAP的论文),具体实现将在下面详细讲解。首先在提取报文结构的时候,由于数据集庞大,分析时候必须关注一些具有代表性的特征,所以不能把初步划分的10034个tokens都作为最终分析的特征,需要进行降维,去除掉多余的特征(如时间戳、cookie等等,这些都是随机出现,而且某一种取值基本都只会出现一次)。
论文中提到,会使用stastical test-driven dimension reduction,排除掉特征集中的constant以及volatile特征,详细参见PRISMA的论文。
这里的test去除了值出现频繁很高以及很低的token,在实际报文序列中,这些可能对应着变值字段和一个定值字段,在找出具有代表性的特征的时候,丢掉了这些,但是在后面的template推断过程中又将其考虑进去了,这样才能得到更准确的格式信息。
扩展:这一步完成以后,报文数据就被转换到了向量空间,并且经过了降维,筛选出了具有代表性的token特征(详细的可以参考ASAP论文中的讲解),使用什么方法来提取报文格式以及状态机,个人觉得就可以“仁者见仁智者见智”了。
Clustering for Event Inference
出现在同一个特定通信event中的报文,通常都会有相似的结构特征(similar structural features),所以可以利用这种结构来提取event信息。首先定义一种metric来衡量两个报文之间的相似性,譬如欧氏距离(其中的Φw(x)表示 w 在报文 x 中出现的次数)在PRISMA的论文中提到了两种聚类方法:
Part-based Clustring:
论文提到这种方法适用于Assembled of parts类型协议效果较好。先进行NMF,然后再按照NMF得到的坐标计算报文之间的相似度来聚类。
非负矩阵分解实质就是通过将处理得到的矩阵A:features×N(data point),分解成两个矩阵B:features×e,C:e×N,(e远小于features的个数),得到的矩阵B可以解释成一个新的基准向量,矩阵C表示在这个新的向量空间中每一个点的坐标【也就是说B(B1,B2,...,Be)定义了新的基准矢量,C(C1,C2,...,CN)则表示每一个点对应的每个基准矢量的权值)】,C里面的Ci就是每一个数据点的坐标,这些坐标就用来计算报文之间的相似度,进行聚类(这里可以参考上面的流程图来理解)。
而具体怎么实现非负矩阵分解就不讲了(因为我也讲不清楚:-D囧:-D)。
Position-based Clustering:
论文中提到这种方法适用于Monolithic communication,where tokens are weighted according to their absolute position in the message,因为某些协议体现出position-dependent 特征,提出了一种weighted distance measure:
Inference of the State Machine
不论采用哪种聚类方法,都会将报文分成若干类,而每一类就代表了一个Event,正是需要依赖这些Event来进行状态机推断。论文中是通过Markov模型来进行推断,笔者会在后面文章中详细讲述。Learning Templates and ruls
大部分协议逆向工作都是先完成协议格式的提取,再利用得到的格式信息进行状态机推断,而PRISMA则是先得到状态机,再利用状态机信息来得到格式信息Template,以及会话之间转换的rules(为了完成后面的Protocol Simulation)。Templates:
首先需要说明,Markov模型的一个状态对应状态机中的一个状态,而每一个状态里面可能会有多个会话,一个会话中也会有多种格式的报文也就是会有多个Template。Learning Templates 的具体步骤如下:
根据之前的划分方法将原始报文序列tokenize;
根据Markov模型将原始报文划分成不同会话的报文;
对于Markov模型中的每一个状态
将相同token数目的报文放到一个group中
如果一个group中的报文在某一个相同的位置,有一个相同的token,那么就认为是最终Template中的一个定值字段,否则就认为是一个变值字段
最终会得到Markov模型中每一个状态的Template,这个Template代表了这个状态下通用的报文格式。需要注意的是,每一个状态可能会对应很多个template,因为这里是按照token数量进行的分组,每一组都会得到一个Template。
实际上这里做了很大的简化,会对得到的结果的准确率造成影响。
Rules:
所谓的Rules其实就是结合Markov模型,会话信息,原始报文,提取出Template中每一个字段的取值,这个就不用赘述了。
相关文章推荐
- Lucene.net 原理介绍以及使用方法
- python写红包的原理流程包含random,lambda其中的使用和见简单介绍
- Git原理命令介绍 以及 eclipse下使用egit和git clone
- 【转】Ettercap简要原理介绍以及使用说明
- 3、Python中关于字典的介绍以及使用方法
- mongodb的介绍、原理以及使用场景
- python 装饰器功能以及函数参数使用介绍
- Python greenlet使用介绍及实现原理
- python lambda的介绍以及使用
- react-redux高阶组件connect方法使用介绍以及实现原理
- python ide开发环境wingide-6.0安装以及使用介绍
- SDWebImage的使用以及原理介绍
- Lucene.net 原理介绍以及使用方法
- python 装饰器功能以及函数参数使用介绍
- 关于datagrid的使用以及动态修改,以及使用存储过程的介绍
- Data Access Application Block(Enterprise Library 3.1)的下载以及使用方法介绍
- 详细介绍在tomcat中配置数据源以及数据源的原理
- cglib 介绍 原理 使用 demo examples
- asp.net 2.0生命周期 以及Page_Load Page_Init方法使用原理