我是靠谱客的博主 幸福山水,最近开发中收集的这篇文章主要介绍使用深度学习识别webshell,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在做毕设的时候选的这个题目,实际在完成的过程中也有了一些收获,在这里记录下
首先是样本,webshell黑样本主要来源于github上的webshell收集项目,白样本来自于github上的开源框架。我也尝试过asp,jsp语言的恶意脚本识别,其实识别效果也很不错,能有95%左右,但是asp,jsp这些语言的恶意脚本数量太少,只有大约1000个左右,说服力不是很强。php样本的数量和质量都要高一些,最终我所搜集到了5000个webshell,以及10000个php白样本
样本链接:https://pan.baidu.com/s/1AdpfAgL3sT2C77RYLwImaQ
提取码:dj4w
完整代码链接:https://pan.baidu.com/s/13sBlnuSbatsdNEkPoDJg9Q
提取码:3tym

词向量提取特征方法:用的是sklearn自带的词向量化器,提词方法是用正则匹配来匹配单词边界,最后生成两个numpy数组,x里存放提取的词向量,y里存放黑白样本的标记。实际实验下来,词向量提取特征识别webshell正确率只有70%左右,和其他的方法相比还是不行。

def get_feature_by_bag_tfidf():
global white_count
global black_count
global max_features
print("max_features=%d" % max_features)
webshell_files_list = load_files(webshell_dir)
y1 = [1] * len(webshell_files_list)
black_count = len(webshell_files_list)
wp_files_list = load_files(whitefile_dir)
y2 = [0] * len(wp_files_list)
white_count = len(wp_files_list)
x = webshell_files_list + wp_files_list
y = y1 + y2
CV = CountVectorizer(ngram_range=(1, 1), max_features=10000,
token_pattern=r'bw+b', min_df=1, max_df=1.0)
x = CV.fit_transform(x).toarray()
transformer = TfidfTransformer(smooth_idf=False)
x_tfidf = transformer.fit_transform(x)
x = x_tfidf.toarray()
print("黑样本", black_count, "白样本", white_count)
x = np.array(x)
y = np.array(y)
return x, y

tf-idf算法,即逆词频统计,即是在词向量提取特征的基础上进行逆词频统计,可以看到实际代码也就比词向量提取特征多了个tf-idf转换。这里的ngram_range其实用处不大,特别是限定最大长度为10000的时候,因为实际webshell里词与词的组合变化非常多,就算只计算连续两个词的组合也有很多种,所以在词库上限定死为10000的情况下,实际n-gram和1-gram是没有区别的,我的实验结果也说明了这一点。实际实验下来,tf-idf提取特征识别webshell正确率还是可以的差不多能有95%左右

def get_feature_by_bag_tfidf():
global white_count
global black_count
global max_features
print("max_features=%d" % max_features)
webshell_files_list = load_files(webshell_dir)
y1 = [1] * len(webshell_files_list)
black_count = len(webshell_files_list)
wp_files_list = load_files(whitefile_dir)
y2 = [0] * len(wp_files_list)
write_txt_byline(all_file_name)
white_count = len(wp_files_list)
x = webshell_files_list + wp_files_list
y = y1 + y2
CV = CountVectorizer(ngram_range=(1, 1), max_features=10000,
token_pattern=r'bw+b', min_df=1, max_df=1.0)
x = CV.fit_transform(x).toarray()
transformer = TfidfTransformer(smooth_idf=False)
x_tfidf = transformer.fit_transform(x)
x = x_tfidf.toarray()
print("黑样本", black_count, "白样本", white_count)
x = np.array(x)
y = np.array(y)
return x, y

文件字节分布+区间熵:这个特征提取方法是从识别exe文件参考来的,一般来说恶意exe文件,比如勒索软件一类的,因为难以提取直接的静态文本特征所以采用这种方法,但是webshell有直接的文本特征,而且大小相比于exe文件要小很多。字节分布就是文件以二进制读入时,0-255个字节出现的次数,区间熵就是计算每1024字节的熵,计算文件最后256个1024字节区间的熵,不够的补0,多了的话取最后256个,最后组合成512维的特征向量。实际实验下来,这种特征提取方法的识别准确率最高,在训练集:测试集大小为1:9的时候都能有97%的测试集正确率,缺点是有一定的不可解释性。

def generate_byte_feature(file_name):
with open(file_name, mode='rb') as f:
file_rb = np.fromfile(f, dtype=np.ubyte)
byte_laymap = Counter(file_rb)
file_length = len(file_rb)
byte_layout = []
# 统计0-255个字节出现的次数
for byte in range(0, 256):
# 0-255字节出现的次数
byte_layout.append(byte_laymap[byte])
current_loc = 0
# 滑动窗口统计熵
step = 1024
# 滑动窗口一次移动字节数
entro_list = []
while current_loc <= file_length:
if current_loc + step > file_length:
end = file_length
else:
end = current_loc + step
entro_list.append(Entropy(file_rb[current_loc:end]))
current_loc = current_loc + step
final_result = byte_layout + entro_list
if len(final_result) < 512:
final_result = np.array(final_result)
final_result = list(np.pad(final_result, (0, 512 - len(final_result)), 'constant', constant_values=(0, 0)))
return final_result[0:512]
else:
return final_result[0:512]

文件灰度图化:本质上也是通过文件的二进制特征来识别webshell,只不过是把文件读取的字节转换成一维数组,然后再reshape成64乘64,128乘128,256乘256这样形式的二维数组,然后以灰度图的形式保存,就得到了webshell的灰度图,然后通过图像识别的方法来识别这些灰度图。实验下来发现识别效果还行,128*128大小的灰度图识别效果最好,能达到95%左右。

def myresize_image(myimage, padding_mode=1,size=data_pic_size ):
# 两种填充方式,1和2,1为重复填充,2为补0填充
pixel_num = myimage.shape[0]
if pixel_num <= 5:
# 如果文件大小极小,视作空文件处理
return np.array([0]), -1
total_pixel = size * size
if total_pixel >= pixel_num:
if padding_mode == 1:
recycle_num = total_pixel // pixel_num
result = myimage
for temp in range(0, recycle_num - 1):
result = np.hstack((result, myimage))
result = np.hstack((result, myimage[0:total_pixel - result.shape[0]]))
result = result.reshape(size, size)
return result, 1
else:
result = np.pad(myimage, (0, total_pixel - pixel_num), 'constant', constant_values=(0, 0))
result = result.reshape(size, size)
return result,1
if total_pixel < pixel_num:
result = myimage[pixel_num - total_pixel:pixel_num]
# 如果字节过多,取最后的文本
result = result.reshape(size, size)
return result, 1
def generate_pic_data(dir, type):
g = os.walk(dir)
file_count = 0
for path, d, filelist in g:
# print d;
for filename in filelist:
# print os.path.join(path, filename)
if filename.endswith('.php') or filename.endswith('.txt'):
fulepath = os.path.join(path, filename)
# print("正在转成图片 %s" % fulepath)
file_count = file_count + 1
f = open(fulepath, mode='rb')
image = np.fromfile(f, dtype=np.ubyte)
pic_array, flag = myresize_image(image)
temp = random.randint(0, 100)
if temp >= 90:
# >=n,表示n%的数据作为测试集
save_dir = "picdata/"
else:
save_dir = "picdata_test/"
if flag == 1:
save_path = save_dir + type + "/" + str(file_count) + ".png"
cv2.imwrite(save_path, pic_array)
print(save_path + "已保存")
if file_count >= max_sample_num:
cv2.waitKey(0)
return
cv2.waitKey(0)

最后

以上就是幸福山水为你收集整理的使用深度学习识别webshell的全部内容,希望文章能够帮你解决使用深度学习识别webshell所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(64)

评论列表共有 0 条评论

立即
投稿
返回
顶部