最近在做一个恶意脚本检测的小型模型,一些思考过程在这里记录一下
前提
由于模型要在pc端侧部署,考虑到性能和内存占用等限制,RNN、Transformer之类的架构基本上也是没法用了,所以我最初的考虑的就是采用 1D CNN来搞一个端到端的分类模型。(其实之前也做了一个基于CPG异构图的GNN模型,但是效果不佳,可能还是数据集质量不佳或者其他哪里出问题了吧)
恶意脚本的局部性
不管是 javascript / python 还是其他语言的恶意脚本,真正有问题的可能就那么一两句,而 CNN 的感受野也不是无限的,所以我采用了滑动窗口来做训练和预测。
将长脚本看作一个长序列,把它切分成多个有重叠的“块”(chunks),利用模型分别对每个块进行预测,最后聚合所有块的预测结果。比如我们可能得到这样一个概率列表:[0.1, 0.05, 0.98, 0.95, 0.2] (如下图),只要有一个块的恶意概率超过阈值(比如 0.5),就将整个脚本标记为恶意。在上面例子中,因为有 0.98,所以整个脚本是恶意的。
训练思路
要采用上面这个策略,首先我得有一个训练良好的模型,那么遇到的第一个问题就是如何处理在训练阶段,同一个脚本被切分为多个chunk,但是标签一致带来的噪声问题?
一个包含 10 个分块的恶意脚本,可能只有 1 个分块含有真正的恶意代码,而其他 9 个分块是完全良性的(例如,函数定义、注释、良性逻辑等)。如果把这 9 个良性块也当作正样本来训练,会让模型感到“困惑”。
这里我选择多实例学习(MIL)的策略,如下图所示

当然这其中肯定还有很多细节,不再详述,举些例子:
- 超长脚本会引入超大的bag,会爆显存。
- 如何保证模型输出的置信度是校准良好的。
碎碎念,有些还没想好怎么解决的问题
- 抗混淆,有些混淆是真的恶心,人分析起来都费劲,总不能混淆就报毒吧
- 不使用注意力的情况下怎么处理上下文关联,可能在第一块中定义的恶意负载变量,在最后一块中才真的用到(resnet天下无敌?)
- 做数据集好费劲。。。。