精华内容
下载资源
问答
  • 恶意代码分类

    2018-07-26 16:46:51
    该资料很好的讲解了恶意代码的特征提取以及分类办法。
  • 为提高大规模恶意代码分类任务的分类准确率,提出基于词向量的恶意代码分类模型,引入NLP中表达语义含义的词向量概念,提取恶意代码函数语义特征,使用textCNN神经网络对其进行分类。实验结果表明,该模型在微软公司...
  • 基于卷积神经网络的恶意代码分类,莫君生,王玉龙,提出一种基于恶意代码图像的恶意代码分类的检测方法,通过结合计算机视觉分析技术与恶意代码变种检测技术,将恶意代码映射为无压
  • 恶意代码的多维度特征融合与深度处理,是恶意代码分类研究的一种发展趋势,也是恶意代码分类研究的一个难点问题。提出了一种适用于恶意代码分类的高维特征融合方法,对恶意代码的静态二进制文件和反汇编特征等进行...
  • 针对传统机器学习方法不能有效地提取恶意代码的潜在特征,提出了基于栈式自编码(stacked auto encoder,SAE)的恶意代码分类算法。其次从大量训练样本中学习并提取恶意代码纹理图像特征、指令语句中的隐含特征;在...
  • 基于深度学习的恶意代码分类(一)

    千次阅读 多人点赞 2021-03-15 20:01:01
    基于深度学习的恶意代码分类 1. 基于传统机器学习算法的恶意代码分类方法 恶意代码分类主要有两种应用:恶意代码检测和恶意代码家族聚类。 恶意代码检测的目的是判断未知代码是否是恶意代码,即将未知代码分为良性...

    基于深度学习的恶意代码分类

    序言

    由于本学期课程的安排,所以不得不将深度学习和网络攻防的知识进行结合,因此,对本门课程的学习进行一个记录,下面是学习的相关知识的过程,仅为本人个人理解,如果有不妥当的地方希望大佬们指正,一定虚心改正。

    1. 基于传统机器学习算法的恶意代码分类方法

    恶意代码分类主要有两种应用:恶意代码检测和恶意代码家族聚类。

    恶意代码检测的目的是判断未知代码是否是恶意代码,即将未知代码分为良性代码和恶意代码两类。

    恶意代码家族聚类是以恶意代码为数据集,依据特征相似性和家族类别标签将恶意代码分为多类。

    恶意代码分类任务主要有两个过程:特征提取过程分类过程。其中,特征提取过程通常采用传统的恶意代码分析方法进行提取;分类过程主要分为两个步骤:
    分类模型的构建分类模型的使用
    在第一个步骤中,将提取的代码特征转化为特征向量,将代码特征向量和类别标签作为输入用作分类算法,例如决策树(DT)、随机森林(RF)和支持向量机(SVM)等,通过对训练集的分析构建分类模型;
    在第二个步骤中,采用相同的特征提取方法对未知代码提取特征,将未知代码的特征向量作为输入用作训练过的分类模型中,实现新样本的分类。

    在恶意代码检测方面,2012 年,Ravi 等人提出基于 API 调用序列频繁项集的恶意代码动态监测系统,通过 API 调用的抽象,频繁项集挖掘和相似度计算实现恶意代码集群的匹配。该方法是基于数据挖掘的检测系统,使用了朴素贝叶斯、支持向量机和决策树等技术。

    基于深度学习算法的恶意代码分析方法

    近年来,深度学习技术在解决人工智能领域的任务中取得了重大突破,它擅长在高维数据中挖掘复杂的数据结构,因此,在科学、商业以及政府部门等多领域有着广泛应用。

    针对恶意代码分析,传统机器学习模型在特征提取阶段往往需要人工设计和参与,这需要完备的先验知识,并且不能从数据本质出发提取恶意代码区分度较大的特征,这在一定程度上影响了恶意代码的分类和聚类准确率。因此,深度学习技术在恶意代码分类也发挥着重要作用。基于深度学习的理论,Invencea 实验室提出从恶意代码二进制数据段中提取特征,并针对其构建深度神经网络以实现恶意代码检测。

    随着机器学习的不断发展,基于机器学习的恶意代码分析方法受到广泛的关注,但是传统机器学习模型在特征提取阶段往往需要人工设计和参与,这需要完备的先验知识,不能自动学习到恶意代码的特征,这在一定程度上影响了恶意代码的分类准确率。
    本文针对现有恶意代码分析方法的不足,基于深度学习的理论和方法,针对恶意代码基因的向量化表示恶意代码基因序列的向量化表示恶意代码静态抗混淆恶意代码的分类方法进行深入研究。

    从恶意代码基因的提取与向量化表示、恶意代码基因序列的向量化表示、恶意代码分类技术与恶意代码聚类技术四个方面进行研究。研究内容框架如图。
    在这里插入图片描述
    恶意代码基因提取和基于 Word2Vec (关于Word2Vec的理解链接)的恶意代码基因向量化表示方法。在海量恶意代码背景下,针对动态分析效率低以及现有恶意代码表示方法缺乏对语义描述的不足。在恶意代码基因提取阶段,从恶意代码行为层面出发,基于海量恶意代码的自动反汇编组件,利用行进递归算法实现恶意代码基因序列的提取;在恶意代码基因向量化表示阶段,基于 Word2Vec 算法构建恶意代码基因预测模型,通过神经网络的训练和自我调节获取有效的恶意代码基因向量,并利用恶意代码基因向量之间的空间距离表征恶意代码基因之间的关联性和相似性。

    基于卷积神经网络的分类模型(Convolution Neural Network CNN)

    基于卷积神经网络的分类模型,SMM_CNN(Static Malware Matrix _Convolution Neural Network),模型针对两种输入完成两种不同的任务。
    (1)针对经混淆的恶意代码,将恶意代码二进制码直接矩阵化作为模型的输入,通过神经网络自动从数据中提取特征,主要解决因无法正确反汇编而不能有效提取特征的问题,一定程度上解决静态分析抗混淆问题;
    (2)针对未经混淆的恶意代码,在1 中提到的恶意代码基因向量化的基础上将恶意代码基因序列矩阵化,以具有语义特性序列特性恶意代码基因矩阵为输入,通过卷积层和池化层自动对具恶意代码基因序列矩阵提取特征,更加有效地实现恶意代码家族分类。

    改进模型

    SMGS_RCNN(Static Malware Gene Sequences_ Recurrent Convolution Neural Network)模型。针对 SMM_CNN 模型获取恶意代
    码基因的全序列信息能力相对较弱的特点,该模型在 SMM_CNN 的基础上结合循环神经网络(Recurrent Neuron Network,RNN),利用 LSTM 组件的遗忘机制、增加保存机制和长期记忆信息机制,提取恶意代码基因的序列特征。(暂时未实现)

    聚类(非本文重点)

    设计并实现了一种表征恶意代码整体语义和基因序列信息的恶意代码基因序列向量化表示方法,并将其应用在恶意代码聚类中。在恶意代码基因序列向量化表示阶段,针对恶意代码基因序列构建基于 Doc2Vec 算法的预测模型,通过训练神经网络,将恶意代码基因序列转化为高维实数向量,并通过恶意代码基因序列向量表征恶意代码基因上下文信息和整体语义信息。在聚类阶段,分别基于自组织映射神经网络(Self Organizing Maps,SOM)和 K-means 算法构建聚类模型,以恶意代码基因序列向量作为输入,通过无监督的学习训练,实现恶意代码家族聚类。

    大体框架

    在这里插入图片描述
    以上是对于深度学习关于恶意代码分类的初步大体框架理解,下面将对本文中涉及的相关概念、模型、算法等理论知识。首先介绍词向量相关概念及其变体模型;然后介绍本文研究中所涉及到的卷积神经网络的网络结构及其训练过程;最后介绍改进的分类模型所要融合的循环神经网络及其变体相关知识。

    相关知识均借鉴于网上的知识,若有侵权请联系。

    展开全文
  • 利用机器学习进行恶意代码分类

    千次阅读 2019-01-25 22:05:49
    偶然看见2015年微软在kaggle上发起的恶意代码分类比赛,并提供超过500G的源码 早期反病毒软件均采用单一的特征匹配方法,利用特征串完成检测。 此次比赛冠军采用三个黄金特征:恶意代码图像,OpCode n-gram, ...

    背景

    偶然看见2015年微软在kaggle上发起的恶意代码分类比赛,并提供超过500G的源码

    早期反病毒软件均采用单一的特征匹配方法,利用特征串完成检测。

    此次比赛冠军采用三个黄金特征:恶意代码图像,OpCode n-gram, Headers个数

    并且使用xgboost和pypy加快训练速度

    转载当年乌云的一篇文章留底

    最近在Kaggle上微软发起了一个恶意代码分类的比赛,并提供了超过500G的数据(解压后)。有意思的是,取得第一名的队伍三个人都不是搞安全出身的,所采用的方法与我们常见的方法存在很大不同,展现了机器学习在安全领域的巨大潜力。在仔细读完他们的代码和相关的论文后,我简单的进行了一些总结与大家分享。

    需要指出的是,(1)比赛的主题是恶意代码的分类,不是病毒查杀(2)比赛采用的方法是纯静态分析的方法,不涉及行为分析等动态分析方法。

    因此这不意味着这个方法能够取代现有的方法,但是了解它能够为安全研究人员提供一个崭新的思路,至于能否在工业界应用仍待进一步研究。

    0x01 总览


    背景

    80年代末期,随着恶意代码的诞生,反恶意代码软件(或称反病毒软件)随之诞生。这个时期的恶意代码所采用的技术较为简单,这使得对应的检测技术也较为容易,早期的反病毒软件大都单一的采用特征匹配的方法,简单的利用特征串完成检测。随着恶意代码技术的发展,恶意代码开始在传播过程中进行变形以躲避查杀,此时同一个恶意代码的变种数量急剧提升,形态较本体也发生了较大的变化,反病毒软件已经很难提取出一段代码作为恶意代码的特征码。在这种情况下,广谱特征码随之诞生,广谱特征码将特征码进行了分段,通过掩码字节对需要进行比较的和不需要进行比较的区段进行划分。然而无论是特征码扫描还是广谱特征,都需要在获得恶意代码样本后,进行特征的提取,随后才能进行检测,这使得对恶意代码的查杀具有一定的滞后性,始终走在恶意代码的后面。为了针对变种病毒和未知病毒,启发式扫描应运而生,启发式扫描利用已有的经验和知识对未知的二进制代码进行检测,这种技术抓住了恶意代码具有普通二进制文件所不具有的恶意行为,例如非常规读写文件,终结自身,非常规切入零环等等。启发式扫描的重点和难点在于如何对恶意代码的恶意行为特征进行提取。特征码扫描、查找广谱特征、启发式扫描,这三种查杀方式均没有实际运行二进制文件,因此均可归为恶意代码静态检测的方法。随着反恶意代码技术的逐步发展,主动防御技术、云查杀技术已越来越多的被安全厂商使用,但恶意代码静态检测的方法仍是效率最高,被运用最广泛的恶意代码查杀技术。

    数据格式

    微软提供的数据包括训练集、测试集和训练集的标注。其中每个恶意代码样本(去除了PE头)包含两个文件,一个是十六进制表示的.bytes文件,另一个是利用IDA反汇编工具生成的.asm文件。如下图所示

    enter image description here

    方法简述

    Kaggle比赛中最重要的环节就是特征工程,特征的好坏直接决定了比赛成绩。在这次Kaggle的比赛中冠军队伍选取了三个“黄金”特征:恶意代码图像、OpCode n-gramHeaders个数,其他一些特征包括ByteCode n-gram,指令频数等。机器学习部分采用了随机森林算法,并用到了xgboostpypy加快训练速度。

    本文主要关注恶意代码图像和OpCode n-gram,以及随机森林算法的应用。

    0x02 恶意代码图像


    这个概念最早是2011年由加利福尼亚大学的NatarajKarthikeyan在他们的论文 Malware Images: Visualization and Automatic Classification 中提出来的,思路非常新颖,把一个二进制文件以灰度图的形式展现出来,利用图像中的纹理特征对恶意代码进行聚类。此后,有许多研究人员在这个思路基础上进行了改进和探索。就目前发表的文章来看,恶意代码图像的形式并不固定,研究人员可根据实际情况进行调整和创新。

    国内这方面的研究较少,去年在通信学报上有一篇《基于纹理指纹的恶意代码变种检测方法研究》,是由北京科技大学的韩晓光博士和北京启明星辰研究院等合作发表的,目测也是仅有的一篇。

    本节介绍最简单的一种恶意代码图像绘制方法。对一个二进制文件,每个字节范围在00~FF之间,刚好对应灰度图0~255(0为黑色,255为白色)。将一个二进制文件转换为一个矩阵(矩阵元素对应文件中的每一个字节,矩阵的大小可根据实际情况进行调整),该矩阵又可以非常方便的转换为一张灰度图。

    python代码如下

    #!python
    import numpy
    from PIL import Image
    import binascii
    def getMatrixfrom_bin(filename,width):
        with open(filename, 'rb') as f:
            content = f.read()
        hexst = binascii.hexlify(content)  #将二进制文件转换为十六进制字符串
        fh = numpy.array([int(hexst[i:i+2],16) for i in range(0, len(hexst), 2)])  #按字节分割
        rn = len(fh)/width
        fh = numpy.reshape(fh[:rn*width],(-1,width))  #根据设定的宽度生成矩阵
        fh = numpy.uint8(fh)
        return fh
    filename = "your_bin_filename"
    im = Image.fromarray(getMatrixfrom_bin(filename,512)) #转换为图像
    im.save("your_img_filename.png")
    

    利用该代码生成的几种病毒样本图像如下所示

    enter image description here

    用肉眼可看出,同一个家族的恶意代码图像在纹理上存在一定的相似性,不同的恶意代码家族是有一定区别的。如何用计算机发现和提取这些纹理的相似特征用以分类呢?这就需要用到计算机视觉里的一些技术了。在NatarajKarthikeyan的论文中采用的是GIST特征GIST特征常用于场景分类任务(如城市、森林、公路和海滩等),用一个五维的感知维度来代表一个场景的主要内容(详情请参考文献[xx])。简单来说,输入图像,输出为对应的GIST描述符,如下图所示

    enter image description here

    matlab实现里面每个图像的GIST描述符都用一个向量表示,最后用SVM完成分类训练。

    enter image description here

    这已经远远超出了场景识别所能做的。不过,国外有学者利用一些类似前文生成那种不规则图像来欺骗深度学习模型,如下图所示

    enter image description here

    详情请参考@王威廉老师的微博。当然,二者并没有什么直接关联,因为基于深度学习的图像识别系统的训练数据是一些有意义的图像。但这是一个非常有意思的巧合,至于基于深度学习的图像识别能否用于恶意代码图像的特征提取和分类,我认为是一个潜在的研究点,所能做的也不局限于此,如果有做深度学习的朋友可以伙同做安全的朋友一起研究交流。

    0x03 OpCode n-gram


    n-gram是自然语言处理领域的概念,早期的语音识别技术和统计语言模型与它密不可分。n-gram基于一个简单的假设,即认为一个词出现的概率仅与它之前的n-1个词有关,这个概率可从大量语料中统计得到。例如“吃”的后面出现“苹果”或“披萨”的概率就会比“公路”的概率大(正常的语料中基本不会出现“吃公路”这种组合),可以看出n-gram在一定程度上包含了部分语言特征。

    n-gram应用于恶意代码识别的想法最早由Tony等人在2004年的论文N-gram-based Detection of New Malicious Code 中提出,不过他们的方法是基于ByteCode的。2008年Moskovitch等人的论文Unknown Malcode Detection Using OPCODE Representation 中提出利用OpCode代替ByteCode更加科学。

    具体来说,一个二进制文件的OpCode n-gram如下图所示

    enter image description here

    针对这次Kaggle比赛提供的数据,用python提取出其n-gram特征

    #!python
    import re
    from collections import *
    # 从.asm文件获取Opcode序列
    def getOpcodeSequence(filename):
        opcode_seq = []
        p = re.compile(r'\s([a-fA-F0-9]{2}\s)+\s*([a-z]+)')
        with open(filename) as f:
            for line in f:
                if line.startswith(".text"):
                    m = re.findall(p,line)
                    if m:
                        opc = m[0][10]
                        if opc != "align":
                            opcode_seq.append(opc)
        return opcode_seq
    # 根据Opcode序列,统计对应的n-gram
    def getOpcodeNgram(ops ,n = 3):
        opngramlist = [tuple(ops[i:i+n]) for i in range(len(ops)-n)]
        opngram = Counter(opngramlist)
        return opngram
    file = "train/0A32eTdBKayjCWhZqDOQ.asm"
    ops = getOpcodeSequence(file)
    opngram = getOpcodeNgram(ops)
    print opngram
    # output
    # Counter({('mov', 'mov', 'mov'): 164, ('xor', 'test', 'setnle'): 155...
    

    0x04 决策树和随机森林


    决策树

    决策树在我们日常生活中无处不在,在众多机器学习的书籍中提到的一个例子(银行预测客户是否有能力偿还贷款)如下图所示

    enter image description here

    在这个在决策树中,非叶子结点如“拥有房产”、“是否结婚”就是所谓的特征,它们是依靠我们的知识人工提取出来的特征。但如果对某个领域不了解,特征数量又较多时,人工提取特征的方法就不可行了,需要依靠算法来寻找合适的特征构造决策树。

    限于篇幅,决策树的构造等过程本文不进行展开,网上相关资源非常多。(只要能够充分理解熵和信息增益的概念,决策树其实非常简单)

    随机森林

    随机森林是一个非常强大的机器学习方法,顾名思义,它是用随机的方式建立一个森林,森林里面有很多的决策树组成,随机森林的每一棵决策树之间是没有关联的。在得到森林之后,当有一个新的输入样本进入的时候,就让森林中的每一棵决策树分别进行一下判断,预测这个样本应该属于哪一类(对于分类算法),然后看看哪一类被选择最多,就预测这个样本为那一类。

    随机森林的思想与Adaboost里面的弱分类器组合成强分类器的思想类似,是一种“集体智慧”的体现。例如,屋子里面有n个人,每个人作出正确判断的概率为p(p略高于0.5,这时每个人可视为一个弱分类器),他们判断的过程独立互不影响,最终以多数人的判断为准。这里我们不从数学上来推导,类比抛硬币,对一枚均匀的硬币,抛n次的结果中,正面和反面的次数是差不多的。而对一枚不均匀的硬币,若出现正面的概率略大于反面,抛n次的结果中出现正面次数比反面次数多的概率就会很大。所以即使每个分类器的准确度不高,但是结合在一起时就可以变成一个强分类器。

    enter image description here

    如图所示,将训练数据有放回的抽样出多个子集(即随机选择矩阵中的行),当然在特征选择上也可以进行随机化(即随机选择矩阵中的列,图中没有体现出来),分别在每个子集上生成对应的决策树

    enter image description here

    决策过程如下图所示(忽略画风不一致的问题...)

    enter image description here

    0x05 冠军队伍的实现细节


    ASM文件图像

    但是在Kaggle比赛中冠军队伍采用的方法并不是从二进制文件生成的图像,也不是从.bytes文件,竟然是从.asm文件生成的图像,他们也没有使用GIST特征,而是使用了前800个像素值作为特征,让人非常费解。

    我专门给队伍里的Jiwei Liu同学发了一封邮件进行咨询,他给我的答复是:GIST特征与其他特征综合使用时影响整体效果,所以他们放弃了GIST特征,另外使用.asm文件生成图像纯属意外发现...

    至于为什么是前800个像素,他的解释是通过反复交叉验证得出的,具体原因不清楚。(在后文的分析中我会谈谈我的一些看法)

    OpCode n-gram

    这部分的实现不复杂,他们选取n=4,在具体的特征选择上通过计算信息增益选取每个分类与其他分类区分度最高的750个特征。

    其他特征

    其他一些特征包括统计Headers,Bytecode n-gram(n=2,3,4),分析指令流(将每个循环固定展开5次)来统计指令频数,这些特征虽然不像前面提到的特征那么有效,但是确实可以在一定程度上提升最终成绩。

    0x06 实验


    冠军队伍的代码是为了参加比赛而写的,时间仓促,又是多人合作完成,导致组织结构很乱,且基本没有注释,可读性较差。更重要的是自己想动手实践一下,所以按照他们的思路写了几个简单的程序,忽略了一些处理起来比较复杂或者难以理解的过程,代码可以在我的github上下载

    由于只是做一些简单的试验,不需要太多的数据(否则速度会非常慢),我从微软提供的训练数据中抽取了大概1/10左右的训练子集,其中从每个分类的中都随机抽取了100个样本(9个分类,每个样本2个文件,共1800个文件),这样也不需要用到pypyxgboost,只需要用到numpypandasPILscikit-learn这些库即可

    友情提示:要进行这个实验,首先确保有一个比较大的硬盘,推荐使用Linux系统。

    训练子集

    这一步需要提前将完整训练集解压好,数量庞大,时间比较久。

    #!python
    import os
    from random import *
    import pandas as pd
    import shutil
    rs = Random()
    # 读取微软提供的训练集标注
    trainlabels = pd.read_csv('trainLabels.csv')
    fids = []
    opd = pd.DataFrame()
    for clabel in range (1,10):
        # 筛选特定分类
        mids = trainlabels[trainlabels.Class == clabel]
        mids = mids.reset_index(drop=True)
        # 在该分类下随机抽取100个
        rchoice = [rs.randint(0,len(mids)-1) for i in range(100)]
        rids = [mids.loc[i].Id for i in rchoice]
        fids.extend(rids)
        opd = opd.append(mids.loc[rchoice])
    opd = opd.reset_index(drop=True)
    # 生成训练子集标注
    opd.to_csv('subtrainLabels.csv', encoding='utf-8', index=False)
    # 将训练子集拷贝出来(根据实际情况修改这个路径)
    sbase = 'yourpath/train/'
    tbase = 'yourpath/subtrain/'
    for fid in fids:
        fnames = ['{0}.asm'.format(fid),'{0}.bytes'.format(fid)]
        for fname in fnames:
            cspath = sbase + fname
            ctpath = tbase + fname
            shutil.copy(cspath,ctpath)
    

    特征抽取

    本实验中只用到了.asm文件,用到了.asm文件图像特征(前1500个像素)和OpCode n-gram特征(本实验取n=3,将总体出现频数大于500次的3-gram作为特征保留),实现代码与前文基本一致,具体细节可参考完整代码。

    scikit-learn

    因为scikit-learn的存在,将机器学习算法应用到其他领域变得非常方便快捷。例如我们已经抽取了这些恶意代码的OpCode n-gram特征("3gramfeature.csv"),利用scikit-learn即可快速训练一个随机森林

    #!python
    from sklearn.ensemble import RandomForestClassifier as RF
    from sklearn import cross_validation
    from sklearn.metrics import confusion_matrix
    import pandas as pd
    subtrainLabel = pd.read_csv('subtrainLabels.csv')
    subtrainfeature = pd.read_csv("3gramfeature.csv")
    subtrain = pd.merge(subtrainLabel,subtrainfeature,on='Id')
    labels = subtrain.Class
    subtrain.drop(["Class","Id"], axis=1, inplace=True)
    subtrain = subtrain.as_matrix()
    # 将训练子集划分为训练集和测试集 其中测试集占40%
    X_train, X_test, y_train, y_test = cross_validation.train_test_split(subtrain,labels,test_size=0.4)
    # 构造随机森林 其中包含500棵决策树
    srf = RF(n_estimators=500, n_jobs=-1)
    srf.fit(X_train,y_train)  # 训练
    print srf.score(X_test,y_test)  # 测试
    

    实验结果

    这里只对预测的准确度做一个简单的评判。

    在只应用.asm文件图像特征(firstrandomforest.py)或者Opcode n-gram特征(secondrandomforest.py)的情况下,以及二者相结合的情况(combine.py),准确率如下所示

    enter image description here

    由于随机森林训练的过程中存在一定的随机性,因此每次结果不一定完全相同,但总的来说,二者结合的准确率通常要高出许多,基本可以达到98%以上的准确率,而且别忘了我们只用了不到1/10的数据

    为什么是前800像素

    观察.asm文件的格式,开头部分其实是IDA生成的一些信息,如下图所示

    enter image description here

    可以目测这个长度已经超出了800个像素(800个字节),实际上这800个像素和反汇编代码没有关系!完全就是IDA产生的一些信息,更进一步的说,实际上冠军队伍的方法压根与恶意代码图像没有关系,实际上是用到了IDA产生的信息。

    但是仔细观察这些IDA信息,貌似长的都差不多,也没有什么有价值的信息,为什么可以有效区分恶意软件类型呢?

    一个大胆的猜想是微软提前将这些恶意代码分好类,在调用IDA进行反汇编的时候是按照每个分类的顺序进行的,由于未知的原因可能导致了这些IDA信息在不同分类上有细微差别,恰好能作为一个非常有效的特征!

    0x07 其他


    • 好的方法总是简单又好理解的。这次Kaggle比赛也是如此,冠军队伍的方法没有特别难理解的部分。但是请注意:面上的方法并不能体现背后难度和工作量,真正复杂和耗时的部分在于特征选择和交叉验证上。比如他们最终放弃GIST特征正是经过反复对比验证才做出的决定。
    • 这次的Kaggle比赛归根结底还是比赛,最终目标是取得最好成绩,不代表这个方法在实际中一定好用。
    • 放弃GIST特征告诉我们一个宝贵的经验,并不是某个特征好就一定要用,还要考虑它和其他特征综合之后的效果。
    • 比赛的数据是去除了PE头的,而输入输出表对分析恶意代码是很有帮助的,假如微软提供的数据包含了PE头,将输入输出表作为特征,最终的结果应该还能进一步提升。
    • 这个方法的能够发现一些静态方法发现不了的变种,但对于未知的新品种依然无能为力(没有数据,机器学习巧妇难为无米之炊...)
    • 可以尝试将该方法应用到Android和IOS平台的恶意代码检测中。

    0x08 资源和参考资料


    比赛说明和原始数据

    https://www.kaggle.com/c/malware-classification/

    冠军队伍相关资料

    本文代码

    https://github.com/bindog/ToyMalwareClassification

    参考资料

    Malware Images: Visualization and Automatic Classification

    Detecting unknown malicious code by applying classification techniques on OpCode patterns(墙裂推荐)

    如何使用GIST+LIBLINEAR分类器提取CIFAR-10 dataset数据集中图像特征,并用测试数据进行实验

    GIST特征描述符使用

    随机森林算法

    How Random Forest algorithm works

    Supervised Classification with k-fold Cross Validation on a Multi Family Malware Dataset

     

    展开全文
  • 为了准确检测和分析变形恶意代码,本文提出了一种基于最小距离的分类检测技术。通过提取恶意代码执行行为,进行操作语义描述。进而量化分析行为特征,计算不同特征属性间的最小相似距离,完成恶意代码分类检测。...
  • 恶意代码分类依据

    千次阅读 2019-01-21 15:56:34

             

    展开全文
  • 最近在Kaggle上微软发起了一个恶意代码分类的比赛,并提供了超过500G的数据(解压后)。有意思的是,取得第一名的队伍三个人都不是搞安全出身的,所采用的方法与我们常见的方法存在很大不同,展现了机器学习在安全领域...

    本文转自https://bindog.github.io/blog/2015/08/20/microsoft-malware-classification/
    原作者:宾狗

    1. 前言

    最近在Kaggle上微软发起了一个恶意代码分类的比赛,并提供了超过500G的数据(解压后)。有意思的是,取得第一名的队伍三个人都不是搞安全出身的,所采用的方法与我们常见的方法存在很大不同,展现了机器学习在安全领域的巨大潜力。在仔细读完他们的代码和相关的论文后,我简单的进行了一些总结与大家分享。

    需要指出的是,(1)比赛的主题是恶意代码的分类,不是病毒查杀(2)比赛采用的方法是纯静态分析的方法,不涉及行为分析等动态分析方法。

    因此这不意味着这个方法能够取代现有的方法,但是了解它能够为安全研究人员提供一个崭新的思路,至于能否在工业界应用仍待进一步研究。

    2. 总览

    2.1. 背景

    80年代末期,随着恶意代码的诞生,反恶意代码软件(或称反病毒软件)随之诞生。这个时期的恶意代码所采用的技术较为简单,这使得对应的检测技术也较为容易,早期的反病毒软件大都单一的采用特征匹配的方法,简单的利用特征串完成检测。随着恶意代码技术的发展,恶意代码开始在传播过程中进行变形以躲避查杀,此时同一个恶意代码的变种数量急剧提升,形态较本体也发生了较大的变化,反病毒软件已经很难提取出一段代码作为恶意代码的特征码。在这种情况下,广谱特征码随之诞生,广谱特征码将特征码进行了分段,通过掩码字节对需要进行比较的和不需要进行比较的区段进行划分。然而无论是特征码扫描还是广谱特征,都需要在获得恶意代码样本后,进行特征的提取,随后才能进行检测,这使得对恶意代码的查杀具有一定的滞后性,始终走在恶意代码的后面。为了针对变种病毒和未知病毒,启发式扫描应运而生,启发式扫描利用已有的经验和知识对未知的二进制代码进行检测,这种技术抓住了恶意代码具有普通二进制文件所不具有的恶意行为,例如非常规读写文件,终结自身,非常规切入零环等等。启发式扫描的重点和难点在于如何对恶意代码的恶意行为特征进行提取。特征码扫描、查找广谱特征、启发式扫描,这三种查杀方式均没有实际运行二进制文件,因此均可归为恶意代码静态检测的方法。随着反恶意代码技术的逐步发展,主动防御技术、云查杀技术已越来越多的被安全厂商使用,但恶意代码静态检测的方法仍是效率最高,被运用最广泛的恶意代码查杀技术。

    2.2. 数据格式

    微软提供的数据包括训练集、测试集和训练集的标注。其中每个恶意代码样本(去除了PE头)包含两个文件,一个是十六进制表示的.bytes文件,另一个是利用IDA反汇编工具生成的.asm文件。如下图所示
    数据格式

    2.3. 方法简述

    Kaggle比赛中最重要的环节就是特征工程,特征的好坏直接决定了比赛成绩。在这次Kaggle的比赛中冠军队伍选取了三个“黄金”特征:恶意代码图像、OpCode n-gram和Headers个数,其他一些特征包括ByteCode n-gram,指令频数等。机器学习部分采用了随机森林算法,并用到了xgboost和pypy加快训练速度。

    本文主要关注恶意代码图像和OpCode n-gram,以及随机森林算法的应用。

    3. 恶意代码图像

    这个概念最早是2011年由加利福尼亚大学的Nataraj和Karthikeyan在他们的论文 Malware Images: Visualization and Automatic Classification 中提出来的,思路非常新颖,把一个二进制文件以灰度图的形式展现出来,利用图像中的纹理特征对恶意代码进行聚类。此后,有许多研究人员在这个思路基础上进行了改进和探索。就目前发表的文章来看,恶意代码图像的形式并不固定,研究人员可根据实际情况进行调整和创新。

    国内这方面的研究较少,去年在通信学报上有一篇《基于纹理指纹的恶意代码变种检测方法研究》,是由北京科技大学的韩晓光博士和北京启明星辰研究院等合作发表的,目测也是仅有的一篇。

    本节介绍最简单的一种恶意代码图像绘制方法。对一个二进制文件,每个字节范围在00FF之间,刚好对应灰度图0255(0为黑色,255为白色)。将一个二进制文件转换为一个矩阵(矩阵元素对应文件中的每一个字节,矩阵的大小可根据实际情况进行调整),该矩阵又可以非常方便的转换为一张灰度图。

    python代码如下

    import numpy
    from PIL import Image
    import binascii
    
    def getMatrixfrom_bin(filename,width):
        with open(filename, 'rb') as f:
            content = f.read()
        hexst = binascii.hexlify(content)  #将二进制文件转换为十六进制字符串
        fh = numpy.array([int(hexst[i:i+2],16) for i in range(0, len(hexst), 2)])  #按字节分割
        rn = len(fh)/width
        fh = numpy.reshape(fh[:rn*width],(-1,width))  #根据设定的宽度生成矩阵
        fh = numpy.uint8(fh)
        return fh
    
    filename = "your_bin_filename"
    im = Image.fromarray(getMatrixfrom_bin(filename,512)) #转换为图像
    im.save("your_img_filename.png")
    

    利用该代码生成的几种病毒样本图像如下所示
    恶意代码图像
    用肉眼可看出,同一个家族的恶意代码图像在纹理上存在一定的相似性,不同的恶意代码家族是有一定区别的。如何用计算机发现和提取这些纹理的相似特征用以分类呢?这就需要用到计算机视觉里的一些技术了。在Nataraj和Karthikeyan的论文中采用的是GIST特征,GIST特征常用于场景分类任务(如城市、森林、公路和海滩等),用一个五维的感知维度来代表一个场景的主要内容(详情请参考文献[xx])。简单来说,输入图像,输出为对应的GIST描述符,如下图所示
    gist descriptor
    在matlab实现里面每个图像的GIST描述符都用一个向量表示,最后用SVM完成分类训练。

    插句题外话,基于深度学习的图像识别技术近几年突猛进,下图截取自Feifei Li老师的TED演讲
    深度学习图像识别

    这已经远远超出了场景识别所能做的。不过,国外有学者利用一些类似前文生成那种不规则图像来欺骗深度学习模型,如下图所示
    欺骗深度学习
    详情请参考@王威廉老师的微博。当然,二者并没有什么直接关联,因为基于深度学习的图像识别系统的训练数据是一些有意义的图像。但这是一个非常有意思的巧合,至于基于深度学习的图像识别能否用于恶意代码图像的特征提取和分类,我认为是一个潜在的研究点,所能做的也不局限于此,如果有做深度学习的朋友可以伙同做安全的朋友一起研究交流。

    4. OpCode n-gram

    n-gram是自然语言处理领域的概念,早期的语音识别技术和统计语言模型与它密不可分。n-gram基于一个简单的假设,即认为一个词出现的概率仅与它之前的n-1个词有关,这个概率可从大量语料中统计得到。例如“吃”的后面出现“苹果”或“披萨”的概率就会比“公路”的概率大(正常的语料中基本不会出现“吃公路”这种组合),可以看出n-gram在一定程度上包含了部分语言特征。

    将n-gram应用于恶意代码识别的想法最早由Tony等人在2004年的论文N-gram-based Detection of New Malicious Code 中提出,不过他们的方法是基于ByteCode的。2008年Moskovitch等人的论文Unknown Malcode Detection Using OPCODE Representation 中提出利用OpCode代替ByteCode更加科学。

    具体来说,一个二进制文件的OpCode n-gram如下图所示
    OpCode n-gram

    针对这次Kaggle比赛提供的数据,用python提取出其n-gram特征

    import re
    from collections import *
    # 从.asm文件获取Opcode序列
    def getOpcodeSequence(filename):
        opcode_seq = []
        p = re.compile(r'\s([a-fA-F0-9]{2}\s)+\s*([a-z]+)')
        with open(filename) as f:
            for line in f:
                if line.startswith(".text"):
                    m = re.findall(p,line)
                    if m:
                        opc = m[0][1]
                        if opc != "align":
                            opcode_seq.append(opc)
        return opcode_seq
    # 根据Opcode序列,统计对应的n-gram
    def getOpcodeNgram(ops ,n = 3):
        opngramlist = [tuple(ops[i:i+n]) for i in range(len(ops)-n)]
        opngram = Counter(opngramlist)
        return opngram
    
    file = "train/0A32eTdBKayjCWhZqDOQ.asm"
    ops = getOpcodeSequence(file)
    opngram = getOpcodeNgram(ops)
    print opngram
    # output
    # Counter({('mov', 'mov', 'mov'): 164, ('xor', 'test', 'setnle'): 155...
    

    5. 决策树和随机森林

    5.1. 决策树

    决策树在我们日常生活中无处不在,在众多机器学习的书籍中提到的一个例子(银行预测客户是否有能力偿还贷款)如下图所示
    决策树例子
    在这个在决策树中,非叶子结点如“拥有房产”、“是否结婚”就是所谓的特征,它们是依靠我们的知识人工提取出来的特征。但如果对某个领域不了解,特征数量又较多时,人工提取特征的方法就不可行了,需要依靠算法来寻找合适的特征构造决策树。

    限于篇幅,决策树的构造等过程本文不进行展开,网上相关资源非常多。(只要能够充分理解熵和信息增益的概念,决策树其实非常简单)

    5.2. 随机森林

    随机森林是一个非常强大的机器学习方法,顾名思义,它是用随机的方式建立一个森林,森林里面有很多的决策树组成,随机森林的每一棵决策树之间是没有关联的。在得到森林之后,当有一个新的输入样本进入的时候,就让森林中的每一棵决策树分别进行一下判断,预测这个样本应该属于哪一类(对于分类算法),然后看看哪一类被选择最多,就预测这个样本为那一类。

    随机森林的思想与Adaboost里面的弱分类器组合成强分类器的思想类似,是一种“集体智慧”的体现。例如,屋子里面有n个人,每个人作出正确判断的概率为p(p略高于0.5,这时每个人可视为一个弱分类器),他们判断的过程独立互不影响,最终以多数人的判断为准。这里我们不从数学上来推导,类比抛硬币,对一枚均匀的硬币,抛n次的结果中,正面和反面的次数是差不多的。而对一枚不均匀的硬币,若出现正面的概率略大于反面,抛n次的结果中出现正面次数比反面次数多的概率就会很大。所以即使每个分类器的准确度不高,但是结合在一起时就可以变成一个强分类器。
    随机森林
    如图所示,将训练数据有放回的抽样出多个子集(即随机选择矩阵中的行),当然在特征选择上也可以进行随机化(即随机选择矩阵中的列,图中没有体现出来),分别在每个子集上生成对应的决策树
    随机森林生成
    决策过程如下图所示(忽略画风不一致的问题…)
    决策过程

    6. 冠军队伍的实现细节

    6.1. ASM文件图像

    但是在Kaggle比赛中冠军队伍采用的方法并不是从二进制文件生成的图像,也不是从.bytes文件,竟然是从.asm文件生成的图像,他们也没有使用GIST特征,而是使用了前800个像素值作为特征,让人非常费解。

    我专门给队伍里的Jiwei Liu同学发了一封邮件进行咨询,他给我的答复是:GIST特征与其他特征综合使用时影响整体效果,所以他们放弃了GIST特征,另外使用.asm文件生成图像纯属意外发现…

    至于为什么是前800个像素,他的解释是通过反复交叉验证得出的,具体原因不清楚。(在后文的分析中我会谈谈我的一些看法)

    6.2. OpCode n-gram

    这部分的实现不复杂,他们选取n=4,在具体的特征选择上通过计算信息增益选取每个分类与其他分类区分度最高的750个特征。

    6.3. 其他特征

    其他一些特征包括统计Headers,Bytecode n-gram(n=2,3,4),分析指令流(将每个循环固定展开5次)来统计指令频数,这些特征虽然不像前面提到的特征那么有效,但是确实可以在一定程度上提升最终成绩。

    7. 实验

    冠军队伍的代码是为了参加比赛而写的,时间仓促,又是多人合作完成,导致组织结构很乱,且基本没有注释,可读性较差。更重要的是自己想动手实践一下,所以按照他们的思路写了几个简单的程序,忽略了一些处理起来比较复杂或者难以理解的过程,代码可以在我的github上下载

    由于只是做一些简单的试验,不需要太多的数据(否则速度会非常慢),我从微软提供的训练数据中抽取了大概1/10左右的训练子集,其中从每个分类的中都随机抽取了100个样本(9个分类,每个样本2个文件,共1800个文件),这样也不需要用到pypy和xgboost,只需要用到numpy、pandas、PIL和scikit-learn这些库即可

    友情提示:要进行这个实验,首先确保有一个比较大的硬盘,推荐使用Linux系统。

    7.1. 训练子集

    这一步需要提前将完整训练集解压好,数量庞大,时间比较久。

    import os
    from random import *
    import pandas as pd
    import shutil
    
    rs = Random()
    # 读取微软提供的训练集标注
    trainlabels = pd.read_csv('trainLabels.csv')
    fids = []
    opd = pd.DataFrame()
    for clabel in range (1,10):
        # 筛选特定分类
        mids = trainlabels[trainlabels.Class == clabel]
        mids = mids.reset_index(drop=True)
        # 在该分类下随机抽取100个
        rchoice = [rs.randint(0,len(mids)-1) for i in range(100)]
        rids = [mids.loc[i].Id for i in rchoice]
        fids.extend(rids)
        opd = opd.append(mids.loc[rchoice])
        
    opd = opd.reset_index(drop=True)
    # 生成训练子集标注
    opd.to_csv('subtrainLabels.csv', encoding='utf-8', index=False)
    
    # 将训练子集拷贝出来(根据实际情况修改这个路径)
    sbase = 'yourpath/train/'
    tbase = 'yourpath/subtrain/'
    for fid in fids:
        fnames = ['{0}.asm'.format(fid),'{0}.bytes'.format(fid)]
        for fname in fnames:
            cspath = sbase + fname
            ctpath = tbase + fname
            shutil.copy(cspath,ctpath)
    

    7.2. 特征抽取

    本实验中只用到了.asm文件,用到了.asm文件图像特征(前1500个像素)和OpCode n-gram特征(本实验取n=3,将总体出现频数大于500次的3-gram作为特征保留),实现代码与前文基本一致,具体细节可参考完整代码。

    7.3. scikit-learn

    因为scikit-learn的存在,将机器学习算法应用到其他领域变得非常方便快捷。例如我们已经抽取了这些恶意代码的OpCode n-gram特征(“3gramfeature.csv”),利用scikit-learn即可快速训练一个随机森林

    from sklearn.ensemble import RandomForestClassifier as RF
    from sklearn import cross_validation
    from sklearn.metrics import confusion_matrix
    import pandas as pd
    
    subtrainLabel = pd.read_csv('subtrainLabels.csv')
    subtrainfeature = pd.read_csv("3gramfeature.csv")
    subtrain = pd.merge(subtrainLabel,subtrainfeature,on='Id')
    labels = subtrain.Class
    subtrain.drop(["Class","Id"], axis=1, inplace=True)
    subtrain = subtrain.as_matrix()
    # 将训练子集划分为训练集和测试集 其中测试集占40%
    X_train, X_test, y_train, y_test = cross_validation.train_test_split(subtrain,labels,test_size=0.4)
    # 构造随机森林 其中包含500棵决策树
    srf = RF(n_estimators=500, n_jobs=-1)
    srf.fit(X_train,y_train)  # 训练
    print srf.score(X_test,y_test)  # 测试
    

    7.4. 实验结果

    这里只对预测的准确度做一个简单的评判。

    在只应用.asm文件图像特征(firstrandomforest.py)或者Opcode n-gram特征(secondrandomforest.py)的情况下,以及二者相结合的情况(combine.py),准确率如下所示
    结果
    由于随机森林训练的过程中存在一定的随机性,因此每次结果不一定完全相同,但总的来说,二者结合的准确率通常要高出许多,基本可以达到98%以上的准确率,而且别忘了我们只用了不到1/10的数据

    7.5. 为什么是前800像素

    观察.asm文件的格式,开头部分其实是IDA生成的一些信息,如下图所示
    IDA info
    可以目测这个长度已经超出了800个像素(800个字节),实际上这800个像素和反汇编代码没有关系!完全就是IDA产生的一些信息,更进一步的说,实际上冠军队伍的方法压根与恶意代码图像没有关系,实际上是用到了IDA产生的信息。

    但是仔细观察这些IDA信息,貌似长的都差不多,也没有什么有价值的信息,为什么可以有效区分恶意软件类型呢?

    一个大胆的猜想是微软提前将这些恶意代码分好类,在调用IDA进行反汇编的时候是按照每个分类的顺序进行的,由于未知的原因可能导致了这些IDA信息在不同分类上有细微差别,恰好能作为一个非常有效的特征!

    8. 其他

    好的方法总是简单又好理解的。这次Kaggle比赛也是如此,冠军队伍的方法没有特别难理解的部分。但是请注意:面上的方法并不能体现背后难度和工作量,真正复杂和耗时的部分在于特征选择和交叉验证上。比如他们最终放弃GIST特征正是经过反复对比验证才做出的决定。
    这次的Kaggle比赛归根结底还是比赛,最终目标是取得最好成绩,不代表这个方法在实际中一定好用。
    放弃GIST特征告诉我们一个宝贵的经验,并不是某个特征好就一定要用,还要考虑它和其他特征综合之后的效果。
    比赛的数据是去除了PE头的,而输入输出表对分析恶意代码是很有帮助的,假如微软提供的数据包含了PE头,将输入输出表作为特征,最终的结果应该还能进一步提升。
    这个方法的能够发现一些静态方法发现不了的变种,但对于未知的新品种依然无能为力(没有数据,机器学习巧妇难为无米之炊…)
    可以尝试将该方法应用到Android和IOS平台的恶意代码检测中。

    9. 资源和参考资料

    9.1. 比赛说明和原始数据

    https://www.kaggle.com/c/malware-classification/

    9.2. 冠军队伍相关资料

    • Kaggle采访
    • JiWei Liu的视频讲解
    • 代码和PDF

    9.3. 本文代码

    https://github.com/bindog/ToyMalwareClassification

    9.4. 参考资料

    • Malware Images: Visualization and Automatic Classification
    • Detecting unknown malicious code by applying classification techniques on OpCode patterns(墙裂推荐)
    • 如何使用GIST+LIBLINEAR分类器提取CIFAR-10 dataset数据集中图像特征,并用测试数据进行实验
    • GIST特征描述符使用
    • 随机森林算法
    • How Random Forest algorithm works
    • Supervised Classification with k-fold Cross Validation on a Multi Family Malware Dataset

    10. Similar Posts

    • 编码的妙用——GCTF2017中The X Sanitizer题解
    • 与前端工程师的较量——Chrome调试工具进阶技巧
    • 安全领域中机器学习的对抗和博弈
    • 利用硬件防御ROP:HA-CFI技术浅析
    • 从SNE到t-SNE再到LargeVis
    展开全文
  • 恶意代码分类

    2020-01-13 18:34:38
    恶意代码分类的间接说明
  • 面对Android恶意代码高速增长的趋势,提出基于字节码图像的Android恶意代码家族分类方法,通过将Android恶意应用的字节码转化为256阶灰度图形式的字节码图像,利用GIST算法提取图像的纹理特征,并结合随机森林算法对...
  • 恶意代码基础知识

    千次阅读 2019-07-12 15:11:01
    (2)恶意代码分类: 1)计算机病毒:显著特点:依附性 需要依附于其他文件进行繁殖; 隐蔽性 (最常见的分类 引导型病毒:感染磁盘的引导系统,在系统启动时载入内存;文件型病毒:感染各类文件,在文件执行时载入...
  • 恶意代码防护

    千次阅读 2018-09-26 10:31:34
    阿里云大学课程:恶意代码防护 课程介绍: 如今恶意代码类型数量和种类众多,为我们的主机造成... 了解云计算环境下主机可能遭受到的恶意代码分类及特征  了解和掌握恶意代码防护的主要技术和手段 课时列表: ...
  • 在这种研究方法中,恶意代码灰度图像纹理特征的描述对恶意代码分类结果的准确性影响较大。为此,提出新的恶意代码图像纹理特征描述方法。通过将全局特征(GIST)与局部特征(LBP或dense SIFT)相融合,构造抗混淆、...
  • 恶意代码分析与防治

    2019-12-14 22:29:09
    (二)恶意代码分类 2 二、恶意代码分析技术 3 (一)静态分析方法 3 (二)动态分析方法 4 (三)恶意代码分析流程 4 (四)恶意代码分析实例一 5 (五)恶意代码分析实例二 8 三、恶意代码的防治 10 (一...
  • 随着互联网的快速发展,计算机安全问题已经...实验结果表明,大样本下,随机森林算法是一种优秀的用于恶意代码检测的算法,即使在恶意代码样本量庞大的情况下,仍然具有良好的分类效果,其在现实应用中具有重要的价值。
  • 为了保护网页不被嵌入恶意代码,提出了一种基于网页文件代码分类检测技术的恶意代码检测系统,并完成了软件设计与开发。该系统采用J2EE技术开发,能够对网页文件进行代码分类扫描,并根据不同的扫描结果进行相应的...
  • 前文从总结恶意代码检测技术,包括恶意代码检测的对象和策略、特征值检测技术、校验和检测技术、启发式扫描技术、虚拟机检测技术和主动防御技术。这篇文章将介绍基于机器学习的恶意代码检测技术,主要参考郑师兄的...
  • 恶意代码检测

    千次阅读 2019-12-15 14:08:32
    恶意代码定义 恶意代码也称为恶意软件,是对各种敌对和入侵软件的概括性术语。包括各种形式的计算机病毒、蠕虫、特洛伊木马、勒索软件、间谍软件、广告软件以及其他的恶意软件。 恶意代码的种类 计算机病毒:指...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,766
精华内容 8,306
关键字:

恶意代码分类