我正在寻找能够让我检测来自给定内存转储的代码的算法/技术。
例如,我可以让程序学习一门新语言。新语言是一组尊重给定语法的指令。
通过向程序提供一组十六进制值(随机数据+代码),我想确定存在尊重语言语法的代码的概率。
答案 0 :(得分:0)
已经有some tools这样的内容,所以您可能希望查看现有的实现,看看他们是如何做到的。
那就是说,如果我是从头开始编写这个,我的第一个想法是构建一个n-gram model数据模型,并将它与我们正在寻找的类似代码模型进行比较对于。维基百科的文章似乎对理论有点沉重,实际执行细节也很少,但基本上,你可以这样做:
收集大量的参考语料库"您正在寻找的那种代码。
将参考语料库中的代码分解为(重叠)三个字节的片段,并计算每个片段("三元组")在语料库中出现的次数。这是基本的原始 n -gram模型, n = 3,字节作为基本数据单元。
将所有 n -gram计数递增1;这称为additive smoothing,使匹配过程更加健壮。
通过将以每个双字节前缀开头的(平滑的)3-gram计数相加,预先计算( n -1)-gram(即2-gram)计数。同时预先计算所有平滑的3克计数的总和。 (这只是参考语料库的总字节长度,减去 n -1 =其中单独文件数的2倍,加上256 3 进行平滑。)
为了获得更好的匹配速度和数值稳定性,请取所有(平滑的)3克和2克计数(以及总计数)的对数。将它们存储为实际(平滑,对数) n -gram模型。 (方便地,log(1)= 0,所以通过加1并取对数,在平滑之前原来为零的任何3-gram计数再次变为零;如果你有很多这些,考虑只存储非零计数。)
使用此预处理的 n -gram模型,您可以循环输入文件并计算与参考语料库匹配的近似对数似然值,作为日志计数的总和。在输入文件中找到的每3克,减去输入文件中找到的每2克的对数计数(除了第一个和最后一个),减去平滑的3克计数的总和的对数。我在这里跳过数学的细节,因为这是SO,而不是math.SE,但相信我,它有效。
由此产生的原始数字本身很少使用(尽管通过将其除以输入的长度可以获得更有意义的东西),但可以与的相应对数似然值进行比较。其他 n -gram模型。结果最大的那个是最有可能的匹配。
特别是,作为基线" null模型",您可能希望计算输入的对数似然是纯随机字节。您不必实际构建随机数据的 n -gram模型来做到这一点;输入的纯粹随机字节的对数似然只是字节输入长度的-log(256)倍(这就是为什么在比较它们之前将对数似然除以输入长度可能是有用的。)
(作为对您的实施的一致性检查,您可能希望检查这是否也是您从空建立平滑 n -gram模型时获得的对数可能性语料库。)
最后,如果您怀疑输入可能包含不同类型数据的混合,则可以在分析之前将其分解为块。或者,您可以通过减去每个3克的对数计数(并添加每个3克的对数)来计算某个合适大小(例如,几千字节)的移动窗口的running average对数似然性。当你沿着输入文件移动时,-gram)从对数似然中掉出窗口。