APP下载

基于TextCNN 的恶意源代码功能分类模型

2021-07-09黎星宇

现代计算机 2021年14期
关键词:源代码卷积代码

黎星宇

(四川大学计算机学院,成都 610065)

0 引言

随着互联网的普及与发展,越来越复杂的恶意软件造成了绝大多数的互联网安全问题,恶意软件的开发人员通过改写手中的恶意核心代码或使用工具可以相当轻易地制作出大量的恶意软件,这些源代码的中间传播站便是地下黑客网络社区[1]。安全研究人员可以通过探索这些社区来发现新的安全威胁、趋势和黑客行为,目前主流研究方向包括内容分析、社交网络分析和恶意软件分析等。相关研究人员探索了多个地缘政治区域的黑客社区,观察到黑客共享各种网络社区的恶意源代码资源,并且互相传播合作,各种恶意程序和脚本的源代码在黑客之间自由分发[2]。然而,源代码经常伴随着不完整的说明文档甚至没有相关文档和代码注释。对于跨越多个不同区域的社区研究人员会遇到使用不熟悉的编程语言编写的恶意脚本,或者由于源代码本身过于模糊,无法解译,代码中常常存在复杂的代码逻辑与不停转换的变量名,这对恶意源代码的研究和分析上造成了很大的限制。

针对这一问题本文设计了一种基于TextCNN 的自动化恶意源代码功能分类模型,受到自然语言处理领域的启发,将恶意源代码文件转换为普通文本文档,把代码词视为文本词,通过Word2Vec 转换为词向量,将一句代码视为一串词向量序列,该序列能有效地保留词特征,词时序特征以及词语义关系,再利用TextCNN建立恶意源代码分类模型,TextCNN 能高效保留文档的局部特征,通过卷积操作可以实现N-Gram 的单词组合,自学习其中的特征含义并筛选出代表特征词,从抽象的代码词中抽取出不同层次的语义信息。经过实验认证,本文设计的分类模型在恶意源代码样本数据集上结果表明,相较于传统机器学习分类方法,本分类模型在分类精确度上有明显的提升。

1 相关工作

过去的研究发现,黑客经常聚集在虚拟社区中,即IRC 社区和在线论坛,黑客通过平台与同行公开分享恶意软件源码和框架,那么这些被分享出来的公用恶意资源将成为安全研究的主流对象[2]。

恶意软件分析包括两种传统分析方法:静态分析和动态分析。静态分析包括分析源代码或其他形式的程序指令,这种分析方法不会实际执行程序,动态分析则相反,需要运行程序分析其动态行为,这两种分析形式相辅相成[3]。近年来越来越多的研究人员将神经网络应用到恶意软件二进制文件的汇编指令和API 调用序列的研究上,SAXE 等人[4]在2015 年将恶意软件二进制样本直接输入神经网络中训练分类器,PASCANU 等人[5]在同年将恶意代码动态执行指令的API 视为特征,利用循环神经网络进行分类,FAN[6]在2016 年抽取出指令序列,对其进行模式匹配,再用神经网络完成分类。随着NLP 方向的研究与发展,一些应用在自然语言处理上的深度学习方法也被使用到恶意代码的研究上,2017 年POPOV 等人[7]将恶意软件的汇编指令视为文档的词,指令序列视为文档的句子,利用Word2Vec将不同的汇编指令计算出对应的词向量,再使用机器学习的方法进行分类,2018 年CAKIR 等人[8]在文献[7]的基础上使用GBM 方法构造分类器,2019 年张涛等人[9]基于Doc2Vec 文字嵌入方法将恶意软件的动态API 序列视为特征,对恶意软件进行家族分类,同年乔延臣等人[10]将汇编指令排序后得到的序列结合卷积神经网络对恶意代码进行分类,2020 年刘恒讯等人[11]则使用API 函数调用序列词向量化来对恶意软件家族进行更细粒度的文本分类。

当前恶意代码分类的主要研究动向大多集中在二进制文件上,研究方向大致为检测是否为恶意文件与恶意软件家族分类。由于缺乏分析恶意源代码文件的工具,跨越多种编程语言的源代码没有对应的说明文档和解释代码,过于晦涩,缺乏可阅读性,导致这类数据通常比恶意软件二进制文件更难检索和分析,通过研究已经确定了恶意源代码现在可以在黑客社区中找到,在2013 年,BENJAMIN[3]利用恶意源代码的上下文,使用支持向量机和C4.5 决策树者两种算法和遗传算法配对的包装器模型选定恶意源代码特征,发现执行不同功能的恶意源代码中出现了不同的具有特征性的代码单词,最后利用机器学习分类器来识别恶意源代码的功能攻击类型,因此认为针对大量恶意软件源代码进行研究是可行的。

2 理论基础

2.1 Word2Vec

在自然语言处理领域,词语是最常见的文档切分力粒度,研究人员在做文本聚类或者分类的时候,经常需要考虑如何表示一个词语。最早被提出的方法是one-hot 编码方法,利用一个离散的取值空间,使用一个长度为词汇表大小的向量来表示一个本文,将文本表示成了一个长度为词汇表大小的向量,接下来就可以进行聚类或者分类了。但是独热编码经常会面对巨大的词汇表,需要高达上百万长度的向量,此时需要做细致的特征工程,把维度降下来,而特征约简导致的信息损失会影响文本分类的效果。独热编码的另一个重要缺陷,就是忽略了词语在文本中的顺序。自然语言文本实际上是一种序列数据,相邻的文字或者词语之间有着密切的关联。独热编码的假设过于粗暴,将这种关联省略了,导致了信息的丢失。2013 年,Mikolov[12]认为利用词的分布式表达方式,词向量可以包含此含义,并且计算不同词向量之间的关系形成低维且稠密的词表达方式,这种方法经常用在文本分类或情感分析等应用场景中。

在本文中,正是使用了这种符合直觉的词语表示方法来有提取恶意代码的特征表达,即Word2Vec[13]。Word2Vec 是Google 公司在2013 年开放的用于训练词向量的软件工具,不需要额外训练,属于无监督方法,给定语料数据集后,自学习地将词信息映射到语义空间中,最终得到一个词向量模型,每个指定维度的数组对应一个单词。Word2Vec 将一个词的上下文(前面k个词和后面k 个词)词编码输入神经网络,输出这个词的编号,他是一个高效率进行词嵌套学习的预测模型。Word2Vec 常用两种模型,一种为Skip-Gram 模型,这种模型利用中心词预测周围词,对出现频率较低的词预测效果更好,另一种是连续词袋模型(CBOW),与前者相反,CBOW 利用周围词预测中心词,通过计算上下文词向量输出中心词的词向量,训练时间要更少。在本实验中,恶意源代码样本数据集还是偏小且代码词也更为离散和生僻,因此使用Skip-Gram 方法来训练本文的词向量,保证代码词更高的准确度。因此综合实验表现,本文使用Skip-Gram 方法将恶意源代码转化为词向量,设置向量维度为300 维,利用词向量包含语义特征的特性,能有效地表示出源代码之间的词义关系,可以对恶意代码行为作出更好的描述。最后经过Skip-Gram 模型训练得出部分代码词的词向量如表1 所示。

表1 部分恶意代码词的词向量表达

2.2 文本卷积神经网络模型

在2014 年,KIM[15]针对CNN 的输入层做了一些变形,提出了文本卷积神经网络TextCNN。与传统图像的CNN 网络相比,TextCNN 在网络结构上没有任何变化,将文本视为图片矩阵,文本的单词作为矩阵的行,文本长度决定矩阵的行数,参考N-Gram 滑动窗口的思想,利用多个不同大小的卷积核对若干个单词组成进行卷积,从而提取出句子中的关键信息,这样文本词语的局部相关性能被更好地捕捉。

本文通过修改KIM 提出的网络参数与结构,设计适合训练恶意词向量的神经网络结构。如图1 所示网络一共有四层,包含输入层、卷积层、最大池化层以及输出层。

图1 TextCNN网络结构图

(1)输入层:

学校员工的工作地位与其在学校的分工有关。机能实验技术人员的地位较低,具体表现为缺乏参加培训、进修的机会,职业发展不明朗;较少有为学校政策出谋划策的机会,自身诉求得不到倾听;工作待遇较低;工作不受教师和学生的理解。

输入层是一个由词向量拼成的词矩阵,规模为1000×300,每一个行向量表示一个代码词的词向量,具有300 维;一篇恶意代码由多个代码词拼接而成,如图2 所示样本中文本长度在1000 左右的占比为90%左右,因此本实验中文本长度设定为1000。输入层有两个这样的输入矩阵,即双通道形式,其中一个用预训练好的词嵌入表达,并且在训练过程中不再发生变化;另外一个也由同样的方式初始化,但是会作为参数,随着网络的训练过程发生改变。令xi为第i个代码词,n为恶意代码文本长度,则一篇恶意源代码文件x1:n可以形式化表示为如下形式:

图2 样本集单文本长度占比图

(2)卷积层:

一共有三种规格卷积核,大小分别为3、4、5,每种规格包含100 个参数互不相同的卷积核。该层的卷积核的宽度k 和输入层词矩阵的宽相同,该宽度即为词向量大小,卷积核只会在高度方向移动,移动范围也就是卷积核的大小h。每次卷积范围的位置都是完整的单词,因为行不会被卷积分割,这样不会将几个单词的一部分进行卷积,这保证了代码词作为语言中最小粒度的合理性。使用卷积核ω∈Rhk与一个窗口xi:i+h-1进行卷积操作,产生一个特征ci,计算方法如下公式:

其中xi:i+h-1代表输入词矩阵的第i行到第i+h-1行所组成的大小为k×h的窗口,W表示权重矩阵,大小也为k×h,b为偏置参数,f为非线性函数,本文使用ReLU 函数。卷积核扫描整个词矩阵,每一次卷积操作相当于一次提取该窗口的特征向量,卷积核内不同的参数定义了不同的窗口,保证提取出互不相同且高密度的特征向量,恶意代码文本长度为n,而卷积核的高度为h,所以总共滑窗n-h+1 次拼接成特征图,构成卷积层的输出c。

(3)池化层:

池化层提取出每张特征图Top-K 的值作为保留,并保留特征值的原始顺序,主要目的是降低特征图的维度,池化过程的公式如下:

卷积层的每个卷积核能生成2 张特征图,一共生成3×2×100 个特征图,经池化操作,得到一个长度为规格为1×600 的向量,池化层的输出z可表示为:

(4)输出层:

输出为维度为4 向量,向量的每一维度对应着一个类别,该维度的数据表示预测该样本属于对应功能类型的概率,池化层的向量z输入到全连接层中,并使用Softmax 激活函数输出每种恶意代码类型的概率,以最大概率的标签作为预测结果。具体计算机公式如下:

3 实验评估

3.1 数据集

本文所使用的恶意源代码文件来自Exploit Data⁃base 官方GIT 仓库。Exploit Database 存储了大量的恶意软件程序和源代码,可以帮助安全研究者和渗透测试工程师更好地进行安全测试工作。Exploit Database将收集来的恶意源代码分为四种功能,分别是本地内存攻击,远程代码执行攻击,网络应用程序攻击和拒绝服务攻击。以下给出四种功能类型的说明:

本地内存攻击(Local Memory Attacks):利用软件安全漏洞,构造恶意输入导致软件在处理输入数据时出现非预期错误,将输入数据写入内存中的某些特定敏感位置,从而劫持软件控制流,转而执行外部输入的指令代码,造成目标系统被获取远程控制或拒绝服务。

远程代码执行攻击(Remote code Execution Attacks):用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,可能会允许攻击者通过改变PATH 或程序执行环境的其他方面来执行一个恶意构造的代码。可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统。

网络应用程序攻击(Web Application Exploits):包括SQL 注入,跨站点脚本,操作系统命令注入,会话劫持等方式攻击或窃取服务器数据。

拒绝服务攻击(Denial of Service):针对服务器漏洞,使用特殊手段消耗服务器资源,从而达到服务器无法正常为其他客户端提供正常服务的目的。一般迫使服务器的缓冲区域溢出或者使用IP 欺骗等方法。

本文选择以Python 语言所写的恶意源代码为研究对象,使用爬虫方法收集数据后,剔除重复的源代码文件和执行程序文件,共计5487 个文件,为了保证四种功能分类的样本均衡,最后筛选各类别样本数量为1200 个左右,共计4887 个样本文件,具体分类数量如图3 所示。通过梳理四大分类的源代码,将源代码转化为txt类型文档,利用传统文本分类方式将空格符号识别为分隔符,将代码词各自独立,统计出Python 编程语言的关键字,和高频出现的无效字使其作为停用词,其中针对恶意源代码中穿插的二进制类型字节编码(即0x56、x0A、0x24 等,其中0x 代表数字,x 代表字符,如图4),有针对性地发现这类型的编码在不同类型的源代码中出现次数也各有不同,因此使用统一代码抽离,化为单词“shellcode”,最后对各类源代码建立起不同的词袋模型。利用Word2Vec 的CBOW 模型将词袋训练为词向量模型,输入TextCNN 进行训练。对于待检测的源代码样本直接将该样本预处理后利用词向量模型生成矩阵输入训练好的TextCNN 模型中,输出长度为4 形式的向量,每个元素代表每种分类的概率,以最大概率作为结果判定输出。

图3 样本集中分类数量分布

图4 原始样本中频繁出现的字节编码

3.2 分类表现评估

在本文中我们采用交叉熵损失函数,将最小化损失函数作为训练目标,计每个分类下的恶意文档样本数量为n,pi表示样本的实际分类概率,pi=1 代表该文档属于类别i,否则pi=0,qi则表示模型的输出,即预测为功能i的概率交叉熵损失函数定义如下:

本恶意代码分类实验采用以下4 个指标作为评估标准:

(1)准确率(Accuracy):被模型正确分类的样本数占样本总数百分值的平均值;

(2)精确率(Precision):中,真正属于该分类的样本占所有被分类为某类型的样本百分值的平均值;

(3)召回率(Recall):被模型检测出来且分类正确被占所有待检测总样本的百分值的平均值;

(4)F1_score:准确率与精确率的调和平均数,使得两种指标得到综合平衡。

本实验使用十折交叉验证法进行性能评估,这是一种经典可靠的模型性能评估方法,轮流将样本集平均划分为十份,选取两份分别作为模型验证集和模型测试集,剩下八份作为模型训练集,本实验具体数量分布则是随机抽取训练样本集3900 个(80%)左右、验证样本集490 个左右(10%)以及测试样本集510 个(10%)左右。实验10 次后将10 次结果计算平均值作为最后的评估成果,多次进行十折交叉验证可以有效提高实验结果的准确性,消除随机性。实验结果如表2所示。

表2 十折交叉验证实验结果

3.3 机器学习对比试验

使用传统机器学习方法,在面对离散化文本文档提取有效特征的能力是非常有限的,特别是本文的实验样本是更为抽象的代码语言,与传统的语言文本相比,可阅读性更差,本文做了直接将文档样本作为学习样本的预前实验,分类精度一般在70%左右,因此在建立机器学习分类器之前需要使用一些特征工程筛选出更具代表性的特征词库,利用词库将代码文档映射为矩阵再使用机器学习方法建立分类器,实验流程如图5所示。

图5 对比实验流程图

利用上文收集的数据集,对其遍历后筛选出使用词频、互信息、卡方校验这三种常用的特征词方法所抽取的每个分类的前300 个特征词,三者取并集,将该集合作为特征词库。通过这一步的工作,本文的发现与动态分析研究一致,重点是为了观察不同类型的恶意代码行为与特征代码词的关系。特征词集平均为给定语言可用的所有词量的30%左右,这将有助于研究人员更快地对恶意源代码进行分析,并且需要更少的硬件作为支撑执行分析。除此之外本文发现对优化特征词集的手动检查表明,导入编程库和方法调用可能是最有用的分类表征,如表3 所示,Python 远程代码执行攻击可能会为互联网功能导入套接字库(“socket”),而本地内存攻击则缺乏这种行为。字节码编码(即0x45、0x32、0x21 等代换而来的“shellcode”)也代表了这种特性,经常用于基于内存的攻击。而在Web 应用程序攻击这类型源代码中,频繁使用了解析URL 的编程库和登录方法调用,这些分析结果都是与代码实现的实际功能相匹配的。

表3 特征工程筛选出的部分特征词

利用机器学习方法进行功能分类。本实验中选用了SVM(支持向量机)、C4.5 决策树、MLP(多层感知机)三种分类器。将以上三种分类模型与本文提出的TextCNN 模型进行横向比较,实验的评估指标结果对比如表4。

表4 横向实验评估对比

如表4 展示,根据实验结果可知,SVM、C4.5 决策树以及MLP 这三种传统的机器学习分类方法的精确度均在90%以下,这说明传统的机器学习方法在面对离散化的代码文本中无法有效找出暗含的特征,即使加入特征工程分类效果依然不够好,此外特征工程还需要使用人工加工,而这需要研究者对代码数据有很强的敏感度,和有相当程度的源代码阅读能力的背景知识。而本文提出的基于词向量的恶意代码分类模型在各指标上均有明显提高;证明了加入恶意代码词向量语义特征,能更好地表述恶意源代码。与BENJA⁃MIN[3]的分类实验相比,本文使用的数据集大小更具备规模,在分类精度上有明显提升。相对其他机器学习而言,文本神经网络降低了对抽取源代码词特征工程能力的要求,无需额外的特征加工工作,同时利用文本神经网络抓取离散文本语义特性和代码词时序之间的关联性,才使得恶意源代码分类的准确率有了提升。

4 结语

本文的主要研究工作集中在如何利用恶意源代码样本训练文本神经网络建立对恶意源代码属于哪种攻击类型的分类器,并且相比传统的文本分类的机器学习方法引入词向量能更好地抽析出恶意源代码在某些代码词的高特征性,设计了基于TextCNN 对恶意源代码的词频、词序列、词向量进行分类的神经网络。本文的模型在Exploit Database 收集的恶意源代码样本集上的交叉验证效果表明了该方法相较于传统的机器学习方法或者特征分类方法的准确率有更有优势。

基于以上所述,利用TextCNN 建立恶意源代码功能分类模型,将源代码映射为文本文档,把代码分类转化为文本分类,提取了包涵词频特征、词序列特征、词语义特征的词向量,提高了针对晦涩难懂的源代码分类的准确性,对于处理大规模或者长片段式恶意源代码片段的分类任务提出了一种有效的解决方案。但是基于神经网络的分类方法无法对于类似for、while 循环类型的结构化条件循环表达出明确的分类含义,除此之外,如果源代码中包含多种类型的恶意攻击功能,分类器只能将其中代码量占比最大的结果作为分类结果输出,接下来的研究方向将是进一步提高源代码的循环结构或条件结构的特征提取技术或者更细粒度划分的功能模型构建。

猜你喜欢

源代码卷积代码
基于全卷积神经网络的猪背膘厚快速准确测定
基于图像处理与卷积神经网络的零件识别
基于TXL的源代码插桩技术研究
基于深度卷积网络与空洞卷积融合的人群计数
神秘的代码
保护好自己的“源代码”
一周机构净增(减)仓股前20名
重要股东二级市场增、减持明细
解密别克安全“源代码”
近期连续上涨7天以上的股