《web安全之机器学习入门》第7章朴素贝叶斯模型检测webshell

N-gram算法,认为第N个词只与前面的第N-1个词相关。
例如对于一个句子,I love my country.
那么2-gram得到的词集为:
["I love","love my","my country"]

代码如下:


检测webshell的第一种方式的思路为,将php webshell文件按照单词分词后(正则\b\w+\b),按照2-gram算法得到词集,从而得到文件每一行在该词集上的分布情况,得到特征向量;然后将正常的php文件也按照如上方法在如上词集上得到特征向量。

webshell文件的行标记为1,正常php文件的行标记为0,特征向量和标记在一起组成数据集。再在朴素贝叶斯模型上使用交叉验证的方式得的准确度。

代码如下:

#coding:utf-8
import os
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import cross_val_score
from sklearn.naive_bayes import GaussianNB

DATAPATH = os.path.dirname(os.path.abspath(__file__)) + "/data"
BLACKPATH = DATAPATH + "/black"
WHITEPATH = DATAPATH + "/white"

def parse_files(path,rtn):
    files = os.listdir(path)
    for item in files:
        if item in ['.', '..']:
            continue
        cpath = path + "/" + item
        if os.path.isdir(cpath):
            parse_files(cpath, rtn)
        else:
            if cpath.endswith(".php"):
                with open(cpath, "r") as f:
                    for line in f.readlines():
                        line = line.strip()
                        rtn.append(line)

if __name__ == '__main__':
    black_lines = list()
    parse_files(BLACKPATH, black_lines)
    white_lines = list()
    parse_files(WHITEPATH, white_lines)

    webshell_vectorizer = CountVectorizer(ngram_range=(2,2), decode_error="ignore", token_pattern=r'\b\w+\b')
    x1 = webshell_vectorizer.fit_transform(black_lines).toarray()
    vocabulary = webshell_vectorizer.vocabulary_
    y1 = len(x1)*[1]

    white_vectorizer = CountVectorizer(ngram_range=(2,2), decode_error="ignore", token_pattern=r'\b\w+\b', vocabulary=vocabulary)
    x2 = white_vectorizer.fit_transform(white_lines).toarray()
    y2 = len(x2)*[0]

    x = np.concatenate((x1, x2))
    y = np.concatenate((y1, y2))

    model = GaussianNB()
    score = cross_val_score(model, x, y, cv=10)
    print score
    print "precision:", np.mean(score)*100

代码执行的效果如下:


检测webshell的第二种方式的思路为,将php webshell文件按照函数调用或者字符串常量分词后(正则\b\w+\b(|\'\w+\'),按照1-gram算法得到词集(1-gram应该就是指的单个词了),从而得到文件每一行在该词集上的分布情况,得到特征向量;然后将正常的php文件也按照如上方法在如上词集上得到特征向量。

webshell文件的行标记为1,正常php文件的行标记为0,特征向量和标记在一起组成数据集。再在朴素贝叶斯模型上使用交叉验证的方式得的准确度。

代码如下:

#coding:utf-8
import os
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import cross_val_score
from sklearn.naive_bayes import GaussianNB

DATAPATH = os.path.dirname(os.path.abspath(__file__)) + "/data"
BLACKPATH = DATAPATH + "/black"
WHITEPATH = DATAPATH + "/white"

def parse_files(path,rtn):
    files = os.listdir(path)
    for item in files:
        if item in ['.', '..']:
            continue
        cpath = path + "/" + item
        if os.path.isdir(cpath):
            parse_files(cpath, rtn)
        else:
            if cpath.endswith(".php"):
                with open(cpath, "r") as f:
                    for line in f.readlines():
                        line = line.strip()
                        rtn.append(line)

if __name__ == '__main__':
    black_lines = list()
    parse_files(BLACKPATH, black_lines)
    white_lines = list()
    parse_files(WHITEPATH, white_lines)

    webshell_vectorizer = CountVectorizer(ngram_range=(1,1), decode_error="ignore", token_pattern=r'\b\w+\b\(|\'\w+\'')
    x1 = webshell_vectorizer.fit_transform(black_lines).toarray()
    vocabulary = webshell_vectorizer.vocabulary_
    y1 = len(x1)*[1]

    white_vectorizer = CountVectorizer(ngram_range=(1,1), decode_error="ignore", token_pattern=r'\b\w+\b\(|\'\w+\'', vocabulary=vocabulary)
    x2 = white_vectorizer.fit_transform(white_lines).toarray()
    y2 = len(x2)*[0]

    x = np.concatenate((x1, x2))
    y = np.concatenate((y1, y2))

    model = GaussianNB()
    score = cross_val_score(model, x, y, cv=10)
    print score
    print "precision:", np.mean(score)*100

代码执行的效果如下:



文章还提到了用朴素贝叶斯算法识别DGA域名(将域名使用2-gram分词后,得到每个域名在词集上的分布向量,然后使用朴素贝叶斯算法),这个思路还是用得比较多的。另外提到的就是用朴素贝叶斯识别验证码(将验证码的灰度图的每一个像素点的值作为特征向量的一维,再使用朴素贝叶斯算法),不过我之前已经用卷积神经网络识别过验证码(Caffe的LeNet-5模型上修改),且准确率高达99.996%,一个验证码识别比赛的结果,所以就不再展开。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值