攻击者能恢复什么(还原类)

AfterPack 的各项变换所属的静态攻击者类别,以及恢复每一类能让攻击者得到什么。

AfterPack 把它的各项保护分为几类。每一类以不同的方式提高还原的成本。知道你代码的某个区域由哪一类覆盖,你就知道攻击者读它时能恢复出什么。Protection Map 会按复杂度分数为每个词元着色,并标出你所选代码所属的类别。

静态攻击者的定义

这些是静态攻击者类别。它们描述的是读取字节的人所面对的情况:grep、AST 工具、一遍去混淆器处理,或者一个不运行代码就解释代码的 LLM。在插桩环境下运行产物的攻击者是另一种更强的情形,参见威胁模型。

The three reversal-complexity classesRenamed & encodedPolynomial-injectiveAttacker gets:the structure, after real workFreeFlattened & fusedPolynomial-non-injectiveAttacker gets:an equivalent program, not yoursReservedDestroyed & fusedExponential — provenance, staticAttacker gets:behaviour, not your structureReservedFree spans the first two classes. Provenance-destroying fusion is planned and not available on any tier today.Each class is a cost, not a wall — and the cost is charged again on your next build.

各个类别

类别静态攻击者能恢复什么层级
重命名与编码(多项式单射)结构,需要花些功夫。名称、字面量、扁平化的控制流和融合的恒等式,都需要真正的模式识别工作。而这项工作在每次构建上都必须重做一遍。Free
扁平化与融合(多项式非单射)一个行为相同的等价程序。逻辑被重写,使多个不同的原始计算坍缩为同一个输出,能映射回你究竟写的是哪一个的线索已经不存在了。目前没有任何已发布的变换能达到这一类别。—

Free 层级在你的整个 bundle 上产生重命名与编码类别(完整矩阵见套餐与层级)。更高的预设会在这一类别内部推得更远。默认预设是 light(复杂度目标 5);更强的预设,例如 --preset=hard,推得更远,同时会使整个 bundle 的页面启动时间成倍增加(加载代价)。从 medium 起,引擎会在整个 bundle 上统一加入控制流扁平化、恒等式融合和常量破坏,这些都在重命名与编码类别之内。

目前不会产生扁平化与融合和破坏与融合类别

没有任何构建会达到它们,也从来没有任何区域被归为“扁平化与融合”或“破坏与融合”。/* @afterpack preset=extreme */ 会把一个区域提升到复杂度目标 25 并开启字符串下限,这是重命名与编码类别内部真实、可衡量的保护。

恢复一个类别能让攻击者得到什么

一个类别能让攻击者得到什么,取决于他们的目标是什么。

  • 一个密钥(API 密钥、许可证阈值、硬编码的表):两个类别本身都无法隐藏它。任何与你的程序行为相同的程序都会暴露出密钥,包括从受保护区域恢复出的程序。保护密钥需要另一种机制。参见保护密钥。
  • 理解并克隆你的代码:静态阅读者可以恢复出一个可运行、可读的等价程序,但前提是完成重命名与编码类别所要求的真正的模式识别工作,而这项工作每次构建都必须重做。这一特性的局限参见 AfterPack 不能替代什么。
  • 定位并修补一处校验(关掉付费墙、把某个 return true 翻转):这两个类别单独都帮不上太多忙。攻击者只需要找到那一个节点。重新找到它要付出一些代价,而这份代价会在每次发布时重置。自完整性检查(transforms.selfIntegrity.enabled)拦不住这种修补:它只检测对它自身校验表的修改。关于轮换,参见最佳实践。

在你自己的构建上验证

Protection Map 展示逐词元的证据:你的原始源代码,按每个词元的复杂度分数着色,悬停时还能看到它所属的类别以及其背后的变换栈。打开在线演示,或者用 npx afterpack@latest 生成你自己的。

下一步

  • 威胁模型:这些类别所针对的对手阶梯。
  • Protection Map:你自己构建的逐词元视图。
  • 最佳实践:该标记什么,以及为什么。
  • 指令:让某个区域在类别之间移动的标记。
  • 预设:阶梯,以及每一级设定的复杂度目标。