SPIR-V 字节码是否提供混淆?

Does SPIR-V bytecode provide obfuscation?

逆向工程师可以直接将图形调试器附加到 OpenGL 应用程序以提取着色器源代码。据我了解,另一方面,Vulkan 使用 SPIR-V 字节码,而不是将明文着色器传递给图形 API。

SPIR-V 字节码是否混淆了着色器源代码,还是很容易反编译?

它不做任何真正的混淆。它唯一真正能做的就是去掉变量名。

如果应用程序不愿意将实际计算复杂化,那就差不多了。

它不能对控制流做太多事情,因为 vulkan 需要结构化的控制流。每个条件分支必须有一个合并块,每个循环都有严格的结构。

有一个 entire specification 详细解释了每个 SPIR-V 操作码的行为。这有点像混淆的相反。但不仅如此。

SPIR-V,尽管是 "assembly",但保留了大量关于源程序的信息。它包含结构定义、带参数和 return 类型的函数定义、循环和条件构造等。为 SPIR-V 编写反编译器一点也不难。

SPIR-V 还可以选择包含注释各种 SPIR-V 定义的文本片段。这更多是编译为 SPIR-V 的环境的一个功能,但 SPIR-V 的输出可以包含变量名、结构名等。如果您愿意,这些 OpName 装饰都可以很容易地剔除。

但是即使没有名字,所有重要的结构信息都在那里。因此,与原始 GLSL 相比,SPIR-V 带来的安全收益微乎其微。

SPIR 操作码的行为类似于 Java:

中的字节码
  • 它创建了一个中立的元运算符,操作码,更接近机器原始代码,以便轻松将 Spir 驱动程序转换为原始 GPU 代码。
  • 作为优势,操作码避免了纯源代码的分发,编译后的 spir 操作码应该有编译问题,如拼写错误或语法错误 - 它已经编译;
  • 一个缺点是二进制表示对纯源代码的可逆性。

对于操作码到纯代码的可逆性,没有简单的解决方法。 Java 字段中使用的一些解决方案是:

  • 混淆 - 就像 ProGuard 对 Java 的字节码所做的那样 - 不确定 SPIR 是否可行;
  • 使用对称密钥进行代码加密 - 密钥硬编码在您的 C 代码中。
  • 使用非对称密钥进行代码加密 - 登录服务器后,私钥来自网络。