有些程序员的代码写得像推理小说一样复杂。
当需要临时变量时,他们可能使用teMp,而多个变量则可能被命名为vaR1、vaR2。
甚至有些人会用拼音缩写作为函数名,例如查询订单的函数就叫cxdd。
要理解这样的代码,往往需要结合上下文反复推敲,才能明白每个部分的真正意义。
这个过程被称为反混淆(Deobfuscation)。
确实相当麻烦,是否有更简单的方法呢?
不妨让AI来帮忙!
最近,FACEbook推出了一种名为DOBF的语言模型,专门处理代码混淆问题。
如下面的示例中,所有不影响程序运行的变量名、函数名和类名都被替换为无意义的符号,AI能够进行推测并尝试还原。

对比正确的答案,虽然不完全相同,但AI的改写显著提升了代码的可读性。

例如,源代码中的FUNC_0代表“重置参数”,AI将其改为“初始化权重”,这也是合理的。
DOBF模型目前支持Python、C++和Java等语言。
虽然不规范命名的程序员相对较少,这一模型的更广泛用途在于恢复故意混淆以保护知识产权的代码,例如:

在代码编写完成后,不影响编译和运行的部分会被批量替换为人类难以辨识的符号,从而增加破解的难度。
此前也有掩码语言模型(Masked Language Model)用于恢复被遮蔽的文本。
用于代码恢复的有哈工大与微软联合开发的codeBERT,以及FACEbook之前推出的TRanscodeR,但效果都不如最新的DOBF。
DOBF的成功并不在于模型架构的创新或数据集的完善,而是引入了新的预训练任务。
合理的任务指导AI的学习。
之前的掩码语言模型通常随机选择需要遮蔽的部分,经常选到括号、逗号等对AI来说难度不大的元素。
DOBF则是指定遮蔽变量名、函数名和类名,让AI进行恢复,这一任务的难度更高,促使AI学习到更深层次的规律。
同时,使用相同的符号替代多次出现的同一名称,防止AI通过复制粘贴的方式轻易学习。

在上述示例中,变量V3的定义表明其为List类型,而第5行调用的是POP(0),这表明是先进先出的结构,因此AI会将其命名为queue(队列)而非stack(堆栈)。
更为出色的是,DOBF能够通过代码内容判断出相应函数的功能,例如生成斐波那契数列或进行向量点积。

DOBF在架构上并没有特别的设计,为了公平比较,它分别训练了两个与codeBERT、TRanscodeR层数相同的模型。
成功的关键在于合理的训练任务。
经过验证该方法有效后,FACEbook将这一训练任务提炼为DOBF任务,且可应用于其他语言模型的训练。
例如,在TRanscodeR模型上使用DOBF作为预训练任务,再结合codeXGLUE基准测试中的下游任务进行微调。
结果在代码抄袭检测、代码生成文档总结和自然语言搜索代码片段这三个任务中,采用DOBF或MLM+DOBF预训练均取得了更优的成绩。

FACEbook的下一步计划是利用DOBF作为指导,探索是否能为自然语言设计出更理想的预训练目标。
然而,代码混淆的挑战远未结束,人类在混淆代码上可谓用尽心思。
期待有一天,AI能理解国际C语言混乱代码大赛中的复杂代码。

GIThub地址:
https://Github.coM/fACEbookReSeaRch/codeGen/blob/Master/docs/dobf.Md
论文地址:
https://aRxiv.oRg/abs/2102.07492
国际C语言混乱代码大赛:
http://www.ioccc.oRg/
