作者:Xing Zhang, Jiongyi Chen, Chao Feng, Ruilin Li, Yunfei Su, Bin Zhang, Jing Lei, and Chaojing Tang(National University of Defense Technology)
出处:USENIX 2021
概要
fuzzing生成的crash输入由于是随机生成的非预期输入,分析人员在debug这些crash的时候很容易陷入一些没有用的程序逻辑里。事实上只有一部分的crash inputs需要被分析。
因此,我们的任务可以概括为给定一个输入,我们去决定输入的哪些字段是和crash相关的,把这些字段进行保留。作者提出了一种基于深度学习以及注意力机制的方法,叫SCREAM。作者给神经网络crash的输入和没有crash的输入,让这个网络学习如何从程序的入口点到crash位置。为了解释神经网络,作者运用了注意力机制去提取输入中与crash相关的字段的贡献。根据提取的不同字段的权重来生成简化后的输入。
Insight
作者让神经网络去近似从程序入口点到crash点的执行,给定一个造成crash的输入以及一个没有crash的输入,让神经网络去找它们之间的区别,从而更加近似地模拟造成crash的执行路径,进一步用注意力机制去提取输入不同字段的权重,根据权重来简化输入。
注意力机制
作者运用注意力机制来解释神经网络,其实就是用注意力机制按照输入的不同字段对输出的贡献分配不同的权重,使其可视化。对于一个输入向量
(
x
1
⃗
,
x
2
⃗
,
.
.
.
.
.
.
,
x
n
⃗
)
(\vec{x_1},\vec{x_2},......,\vec{x_n})
(x1,x2,......,xn),假设我们有
v
⃗
=
α
1
x
1
⃗
+
α
2
x
2
⃗
+
.
.
.
+
α
n
x
n
⃗
\vec{v}=\alpha_1\vec{x_1}+\alpha_2\vec{x_2}+...+\alpha_n\vec{x_n}
v=α1x1+α2x2+...+αnxn
y
=
f
(
v
⃗
)
,
w
h
e
r
e
Σ
i
α
i
=
1
,
α
i
>
0
y=f(\vec{v}),where \underset{i}\Sigma\alpha_i=1,\alpha_i>0
y=f(v),whereiΣαi=1,αi>0
这个公式的意思就这个输入的不同字段
x
i
x_i
xi分配不同的权重
α
i
\alpha_i
αi,并且权重和为1,去求得这个关于权重的函数y。
权重本身可以看作一个向量,在seq2seq网络中通常就是用
y
=
f
(
x
⃗
)
y=f(\vec{x})
y=f(x)来确定输入的字节对输出的影响,公式长这样:
在数据集里面,
x
i
⃗
\vec{x^i}
xi表示第i个样本,
y
i
⃗
\vec{y^i}
yi表示它对应的标签。平均方差的损失函数为:
然而在用梯度下降方法降低损失的时候很难满足权重和等于一这个条件,因此,作者使用softmax函数最为权重的激活函数,把softmax函数的输出定为1。
损失函数就变为:
测试用例简化
用规范化的语言描述这篇论文要做的事情就是对于一个程序
P
P
P以及一个引起一个crash
C
C
C的输入
x
⃗
=
(
x
1
,
x
2
,
.
.
.
,
x
n
)
\vec{x}=(x_1,x_2,...,x_n)
x=(x1,x2,...,xn),我们去找一个输入的最小集合
x
⃗
=
(
x
i
,
.
.
,
x
j
)
(
1
≤
i
≤
j
≤
n
)
\vec{x}=(x_i,..,x_j) (1\le i \le j \le n)
x=(xi,..,xj)(1≤i≤j≤n)能触发程序同样一个crash。
作者的方法说白了就是给神经网络能造成crash的输入和不能造成crash的输入,让神经网络去判断这个输入是否能够触发crash,并且学习哪些输入字段和crash是相关的,然后用注意力机制去计算一个权重。方法框架如下:
- 输入和输出编码:所有的输入直接转化成16进制。输出就是一个bool值表示是否触发了crash。使用从程序崩溃点开始向后执行的函数调用序列来唯一地表示崩溃。
- 数据集:在crash输入的基础上变异,并且追求diversity。作者设计了一种新的算法:
- 基于遗传算法,决定变异那里以及选择哪个种子去变异。
- 变异因为每次神经网络会输出一个输入不同字段的权重,它就选择在中间范围20%到60%之间的字段去变异。选中间范围的意思就是相关度高的我不去动他,相关度低的它之后就会被简化掉。中间的这些就是不确定的嘛,那我就一直变异它直到它的权重变高或者变低。
- 种子选择主要是想追求diversity,作者用NLP Bi-gram模型去衡量能造成crash的输入之间的diversity。然后用up-sampling去平衡crash和不crash的输入的数量。
- 网络结构:先用CNN把一维的输入长编码成多个高维的短向量。然后用LSTM以及soft马修去学习权重。最后传到全连接层生成label。
- 选择前两个最相关的样本进行简化,对于每一个样本按照权重从高到低简化。通过执行程序来判断简化后还能否触发crash。
总结
- 用CNN划分的字段是否符合程序对输入的处理逻辑?
- 这篇论文和USENIX2020的一篇论文AURORA思路很像,都是给神经网络传crash了的和没有crash的输入,让神经网络去找区别。