【2021 paper】基于Bert语义理解的二进制代码表示
基于Bert模型建立的原因分析
对归一化的数据集进行归一化分析,可以得到如下图,指令分布的曲线像自然语言一样符合齐普夫定律,而奇普夫定律是词频分布定律。
奇普夫定律:在自然语言的语料库里,一个单词出现的次数与它在频率表里的排名成反比。
f
×
r
=
C
f
是
频
率
,
r
是
序
号
,
C
为
常
数
。
频
率
越
高
,
序
号
越
小
f\times r = C \\ f 是频率, r是序号, C为常数。频率越高,序号越小
f×r=Cf是频率,r是序号,C为常数。频率越高,序号越小
基于作者给出的dataset
, Top 10 normalized 指令和频率如下图所示
Rank | Normalized Instruction | Ratio | Cumulative |
---|---|---|---|
1 | mov_reg8_reg8 | 8.243% | 8.24% |
2 | call_innerfunc | 5.735% | 13.98% |
3 | mov_reg8_qwordptr[bp8-disp] | 4.164% | 18.14% |
4 | je_jmpdst | 3.925% | 22.07% |
5 | jmp_jmpdst | 3.859% | 25.93% |
6 | mov_reg4_immval | 3.486% | 29.41% |
7 | jne_jmpdst | 2.613% | 32.03% |
8 | mov_reg8_qwordptr[reg8+disp] | 2.267% | 34.29% |
9 | pop_reg8 | 1.936% | 36.23% |
10 | mov_reg4_reg4 | 1.860% | 38.09% |
DeepSematic概述
DeepSematic
分两个步骤进行训练。Stage 1是预训练,目的是让Bert学会识别Normlized指令意义。Stage 2是微调。目的是针对下流任务使用新的数据集进行训练。包括相似性检测等。模型整体架构如下图所示。
预训练
采用原始BERT的掩蔽语言模型(MLM),没有采用NSP(即预测下一句),因为两个连续的函数往往在语义上没有联系。使用的函数级别的粒度。
针对下流任务二进制相似性的微调
- Linear层的作用是通过线性变换,将输入维度为2*256+1进行向量维度变换为2的向量。
- Softmax激活函数常用在分类问题中,为模型提供非线性的性质。
BoS包括每个函数的字符串常量和数值常量特征,例如函数A的结果为[1, 0x12, 8, 8, 8, 'hello"]
,其按照它的规则表示为[1, 1, 3, 1]
,通过添加与不添加BoS验证其的有效性。
针对下流任务工具链预测的微调
恢复二进制代码的Toolchain出处是数字取证文献中的一项重要任务。
数据集构建及其归一化处理
数据集构建
本数据集的源码主要包含以下四个部分:Gnutils
,Spec2006
,Spec2017
,Utils(openssl, ngix, vsftpd)
。编译选项包括:gcc(O0, O1, O2, O3),clang(O0, O1, O2, O3)。针对每个函数,提取的信息包括函数名称、libc库调用、交叉引用(如字符串字面、数字常量)、节名称和调用(如内部调用、外部调用)。获得如下表所示的数据集。
其中,FN、BB和IN分别代表一个函数、基本块和指令。
归一化处理
指令归一化的质量是很重要的,过于粗略的归一化,会失去相当多上下文信息;过于细化的归一化接近于指令分解,由于大量的未见指令,会产生OOV问题。而一个归一化分案的好坏,往往就是由这两点决定。
本文采用的规则如下表所示,主要为三条基本规则:
- 一个立即数可以根据字符串字面、静态分配的变量或其他数据,落入跳转或调用目的地址,数值本身,引用。如(2) 0x401d00 → externfunc,(6) 0x425530 → innerfunc;(5) 0x38 → immval;(4) 0x425530 → dispbss
- 一个寄存器默认可以用一个大小分类,但有特殊用途的寄存器保持不变,如堆栈指针、指令指针或基数指针。如(1) r14 → reg8, (4) eax → reg4;(3) ebp → bp4
- 指针表达式遵循原始格式,“基数+索引*刻度+位移”,这样可以保留某些内存访问信息。如(3) DWORD PTR [r14] → dwordptr[reg8]
最终通过归一化处理,获得了17,225个普通token, 5个特殊token([SOS]:句首,[EOS]:句尾,[UNK]:未知token,[MASK]:预测一个词的掩码,[PAD]:填充输入长度的填充符号)。所有归一化的二进制函数的总数为1,690,715;然而,在过滤掉太小(指令数小于或等于5;15.4%)或太大(大于250条指令;4.5%)的函数后,我们只包括大约130万个函数。在测试集的OOV比例约为0.93%,即在8,783个token中只有82个词汇是未知的(训练集的词汇数为17,024)
均衡归一化的有效性分析
为了验证归一化的有效性,与其他的归一化方案进行对比
- 对于没有归一化的规则是将每个直接操作数替换为immval,训练集中的tokens数量为4,917,904,这比均衡归一化大207.4倍。97.8%(130,736中的127,805)的测试集中的所有token没有出现在训练集中,由于严重的OOV问题。
- 所有的immediates和指针都被替换为immval和ptr。训练集token数量缩减到2,022个,包括五个特殊的token(大约减少88.3%),最终通过实验证明,本文采用的归一化方案优于此方案。
二进制代码相似性模型评估
表现很好。
模型局限性分析
- 只针对单一架构,未进行跨架构学习
- 可以通过将操作代码和操作数分开,尽可能减少token集合的大小,而且OOV比较小。
- etc
Paper : Semantic-aware Binary Code Representation with BERT
Paper PPT
Paper 翻译