PHP Webshell AI Engine Based On Rendering Sourcecode To Imagefile
1. 样本形式转换 - 代码图像渲染
0x1:文件图像渲染
将源代码文件渲染为一张pixel像素点阵长图,例如下图
通过图像识别领域里的方法论来webshell pixel image进行特征提取和检测。
用Selenium+PhantomJS的方式渲染源代码文件,并通过模拟滚轮截图后,将所有图像逐一拼接起来得到一张完整的图。
0x2:多图拼接
不可能完全严丝合缝的拼接出一个长图,中间允许留白,但是避免少截图,避免漏掉代码
0x3:代码提取
可能需要将asp tag提取出来后再检测
0x4:代码高亮渲染
将代码highlight出来,这样可以在RGB层面上增加样本中的信息量
Relevant Link:
http://chromedriver.chromium.org/getting-started https://code.evink.cn/2018/07/post/python-use-chrome-to-make-a-long-page-screenshot/ https://github.com/ariya/phantomjs https://bitbucket.org/ariya/phantomjs/downloads/ https://www.jianshu.com/p/11d519e2d0cb https://www.jianshu.com/p/4b89c92ff9b4 https://github.com/ariya/phantomjs/tree/master/deploy
3. 特征工程
图像的特征工程主要工作就是将image file pixel矩阵转化为定长的nparray矩阵。
可能对于MINIT这种场景来说,待检测的图像本身就是相对固定大小的image file。
但是在webshell file这个场景中,不同的webshell file image可能大小差别很大,例如下面2个文件:
另一个小文件:
如果采用同样的缩放尺寸进行resize,小图片就会被拉伸失真,大图片就会挤压在一起。
解决的方法可能只有进行固定(width,high)的truncate裁剪。但是裁剪也有问题,裁剪可能导致有效的payload丢失。
另一个可能的解决方向是将图像进行分片切割,逐片进行异常检测。但是这样就需要更细粒度的标签,需要对分片slice的图片具备标签能力。
2. 模型架构设计
0x1:CNN+LSTM+Attention
Relevant Link:
https://www.joinquant.com/view/community/detail/301c73f3088d6d768a499d3f519f00e8
3. 模型合理性理论分析
0x1:神经网络输入层采用连续型概率函数分布代替离散型概率函数分布 - 样本处理接口通用性
1. 离散型随机变量(Char Dispersed Token)输入层
传统的Ascii char、ASM code、VM Opcode、Binfile Binary code检测模型(统称为Char Dispersed Token),本质上是对离散的随机变量进行建模处理,例如下面这个webshell文本文件:
<?php echo 1; ?>
不管深度神经网络整体设计如何复杂,其输入层的结构都是对应一段固定长度(fixed length)的离散正整数随机变量序列。
设 Xi 为输入层单个神经元的值,X为输入层随机变量,值域空间为Z。
随机变量的值域空间Z整体上都属于正整数,在不同的应用场景中略有不同,例如:
- Ascii char:[0,255]
- ASM code:[0,MAX(x86/x64汇编指令数量)]
- VM Opcode:[0,MAX(具体vm指令数量,例如php zend的pvm指令数量为174)]
- Binfile Binary code:[0,255]
从概率分布函数的视角来看输入层,输入层是一个离散阶跃函数,相邻 Xi 和 Xi-1 之间往往跳变很大。还是以上面这段文本为例,将 Xi 序列打印出来:
# -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt if __name__ == '__main__': sourcecode = '<?php echo 1; ?>' x,y = [], [] for i in range(len(sourcecode)): x.append(i) y.append(ord(sourcecode[i])) plt.figure() plt.plot(x, y) plt.show()
Xi 序列之间的跳变很大,如果要用非线性模型来拟合这段数据,需要用非常复杂(或者非常深)的网络来进行拟合。
2. 连续型随机变量(Continuity Pixel Token)输入层
严格意义上说,image pixel并不能算是连续型随机变量,因为不同的pixel token之间还是离散阶跃的关系,但是区别于Char Dispersed Token来说,由于图像自身的连续渐变以及平移不变性等特征,所以对于Continuity Pixel Token来说,它是一种近似连续的随机变量分布函数。
我们还是以上面这段文本为例,将其渲染为图片:
按照pixel的顺序将其展开打印出来:
# -*- coding: utf-8 -*- import matplotlib.pyplot as plt import numpy as np np.set_printoptions(threshold=np.inf) from PIL import Image def a(): sourcecode = '<?php echo 1; ?>' x, y = [], [] for i in range(len(sourcecode)): x.append(i) y.append(ord(sourcecode[i])) plt.figure() plt.plot(x, y) plt.show() def b(): from_img = Image.open("/Users/zhenghan/Downloads/1.png") from_img = from_img.convert('L') im_array = np.array(from_img) x, y = [], [] i = 0 for line in im_array: for colum in line: if i % 20 == 0: x.append(i) y.append(colum) i += 1 print plt.figure() plt.plot(x, y) plt.show() if __name__ == '__main__': b()
可以看到,image pixel的主要有效区域集中在中间某些子区间部分,其他大部分时候都是255(即空白像素)。
3. 将离散的Dispersed Token转化为Pixel Image的数学本质是什么
本质上,将ascii char、opcode这些Dispersed Token渲染为对应的Pixel matrix的本质上是一个映射函数。
设Dispersed Token为随机变量X,Pixel matrix为随机变量Y,F(X) 为对随机变量X的一次映射,F(X) = Y,F()将单个实值随机变量映射为了一个matrix方阵。
4. 需要理论论证和推导的问题
要理论论证的点一:对同样的样本来说,连续型随机变量比离散型随机变量包含的信息更多,深度神经网络这种非线性模型更容易从中提取出有用的信息。
要理论论证的点二:如何用合适的数学工具,量化地分析随机变量X和随机变量Y各自包含的信息量、概率密度的变化情况、X和Y之间的相关系数等关系。
0x2:CNN Filter卷积合理性
1. 通过CNN Filter Reverse Convolution提供模型的可解释性
要理论论证的点三:CNN Filter是否捕捉到了恶意代码的形态边缘特征,这部分类似于MINIST手写代码识别的效果可解释性验证
2. CNN的平移不变性对插马恶意文件的鲁棒性
要理论论证的点四:用两类不同的插马位置,来检验CNN的平移不变性
0x3:LSTM序列的合理性
0x4:Attension机制的合理性
还是从CNN反卷积核这个角度来论证,当同一个训练样本中有多处恶意代码边缘形态特征时,attension机制如何调配cnn filter权重,将主要的权重分配在特别重要的filter上。
要理论论证的点五:
“上层调制”这种机制的作用。很多人对多层神经网络的疑问是:既然多层神经网络号称是对输入特征进行不断组合以获得效果更好的高层特征,那为什么不可以采用自底向上的机制,每次单独训练一层,等训练完再建上一层?我们要论证的是,如果没有上层的监督信号,那底层的特征组合数量会指数级增长,并且生成的特征大多是对上层任务无用的。唯有优化时不停听取来自上层的信号,有针对性地进行组合,才可以以极高的效率获得特定任务的重要特征。而对权重的随机初始化,是赋予它们在优化时滑向任意组合的能力。
0x5:安全领域的恶意文本检测通用策略
1. 恶意文本定义范围
恶意文本包括二进制可执行文件、ASCII-Plain脚本文件、明文URL、明文网络数据包raw_data等。
2. 恶意文件检测的通用方法框架论证
通过对模型中神经元权重的分配进行探索,对安全攻防里的二分类检测问题的总体策略进行一个通用性定义。
要理论论证的点六:恶意特征检测是倾向单点或者说是尽量少的判据,还是倾向多点综合或者说是尽量多的综合判据。采用student-teacher理论框架,对样本的真值概率分布进行定量和定型分析,目标得出的结论如下:
- 样本的真值概率分布倾向于有限的少量概率峰值区间,所以所有的安全分类器都应该尽量多用单点检测和单点hook污点检测
- 样本的真实概率分布非常离散,所以安全领域的专家经验永远只能case by case解决部分问题,需要尽量多用机器学习来进行多判据的综合检测
-