【问题标题】:C#: Location of const variable in a binaryC#:常量变量在二进制文件中的位置
【发布时间】:2009-08-14 04:06:45
【问题描述】:

是否可以知道 const 变量在 exe 中的位置?我们正在考虑为我们的程序添加水印,以便从我们的服务器下载程序的每个用户都将在代码中嵌入一些唯一的密钥。

还有其他方法吗?

【问题讨论】:

    标签: c# .net security compiler-construction watermark


    【解决方案1】:

    您可以构建带有水印的二进制文件,该水印是 .net 类型中 GUID 的字符串表示形式,作为常量。构建后,在二进制文件中搜索 GUID 字符串以检查其位置。您可以将此 GUID 值更改为另一个 GUID 值,然后运行二进制文件并在代码输出中实际看到更改后的值。

    注意:格式很重要,因为长度非常重要,因为您正在处理已编译的二进制文件。例如,您需要保留 GUID 的前导零,以便所有实例在转换为字符串时具有相同的字符长度。

    我实际上已经用 Win32 DLL 甚至 Sql Server 2000 Desktop exe 做过这种事情。 (有一个 hack,您可以通过翻转二进制文件中的开关将桌面版切换到完整的 SQL 服务器。)

    然后,这个过程可以自动化,一个新的 DLL 副本将由一个小的服务器端实用程序以编程方式为每个客户端下载进行更改。

    也看看这个:link

    它讨论了在 .Net DLL 中存储设置的使用,并使用基于类的方法并嵌入应用程序设置文件并在编译后可配置。

    【讨论】:

    • 是的,我在开始之前就在考虑这些方面的事情。然而,我想听听是否有人对此有任何经验以及关于最佳实践的建议。感谢您的回答。
    • 我已经使用十六进制编辑器完成了它。以编程方式执行此操作应该不费吹灰之力。并获得最佳实践???这个解决方案和任何沿着这些思路的解决方案都是一个黑客工作。您正在编译后修改二进制文件!除非 Microsoft 在文件头中创建一个空间来专门保存和编辑此类信息,否则永远不会有“最佳实践”。
    【解决方案2】:

    关键考虑因素 #1:大会签署

    由于您正在分发您的应用程序,显然您正在签署它。因此,由于您正在修改二进制内容,因此您必须将签名过程直接集成到下载过程中。

    关键考虑因素 #2:constreadonly

    constreadonly 变量之间存在许多人不知道的关键区别。特别是,如果我执行以下操作:

    private readonly int SomeValue = 3;
    
    ...
    if (SomeValue > 0)
        ...
    

    然后它会编译成如下的字节码:

    ldsfld [SomeValue]
    ldc.i4.0
    ble.s 
    

    如果您进行以下操作:

    private const int SomeValue = 3;
    
    ...
    if (SomeValue > 0)
        ...
    

    然后它会编译成如下的字节码:

    {contents of if block here}
    

    const 变量[允许] 由编译器替换和评估,而不是在运行时进行评估,其中readonly 变量总是在运行时评估。当您将字段公开给其他程序集时,这会产生很大的不同,因为对 const 变量的更改是一个重大更改,会强制重新编译所有相关程序集。

    我的建议

    我看到两个相当简单的水印选项,虽然我不是该领域的专家,所以不知道它们总体上有多“好”。

    1. 为嵌入的初始屏幕或关于框徽标图像添加水印。
    2. 为加载字符串资源的对称密钥添加水印。保留一个缓存,因此只需要解码一次就不会出现性能问题——这是一个应用于常用混淆技术的变量。字符串以 UTF-8 编码字符串的形式存储在二进制文件中,只要新字符串的以 null 结尾的长度小于或等于当前在二进制文件中找到的字符串的长度,就可以进行内联替换。李>

    最后,Google 报告了以下article on watermarking software,您可能想看看。

    【讨论】:

    • 谢谢!我没有意识到这种差异。但是在我们的示例中,我认为 const 或 readonly 就足够了。不过我会认真考虑你的建议。 +1
    【解决方案3】:

    在 C++ 中(例如):

    #define GUID_TO_REPLACE "CC7839EB7EC047B290D686C65F98E0F4"
    printf(GUID_TO_REPLACE);
    

    在 PHP 中:

    <?php
    exec("sed -e 's/CC7839EB7EC047B290D686C65F98E0F4/replacedreplacedreplacedreplaced/g' TestApp.exe > TestAppTagged.exe");
    ?>
    

    如果您将编译后的二进制文件粘贴到服务器上,请访问 php 脚本,下载标记的 exe,然后运行它...您会看到它现在打印“替换”字符串而不是 GUID :)

    请注意,替换字符串的长度必须与原始字符串的长度相同(在本例中为 32),因此如果您想用更短的内容标记它,则需要填充长度。

    【讨论】:

      【解决方案4】:

      我不确定你所说的 const 值的“位置”是什么意思。您当然可以使用反射之类的项目来访问特定类型的 const 字段。常量字段与具有相同可访问性的任何其他非实例字段一样绑定。我不知道这是否符合您对位置的定义。

      【讨论】:

      • 嗯,应用程序是我们将保存在服务器上的文件集合。当用户决定下载应用程序时,我希望我们可以使用 PHP 通过覆盖其中的预定部分来修改 windows exe。因此,我们可以在自动压缩并为用户提供下载链接之前为每个 exe 添加水印。如果该文件曾经显示为非法种子,我们就会知道它的来源。
      • Pedery,你绝对可以做到。检查我上面编辑的评论。但我想知道您的策略是否已被任何人尝试过。我认为消除水印以隐藏来源可能是一个相当简单的技巧。就像拿一个设备的序列号...
      • 当然,但这当然不是我们将嵌入的唯一安全手段。这只是为每次下载添加水印的一种方式,我相当肯定黑客永远不会发现这一点,因为二进制文件的区域从未被使用过。它只会为我们提供一种方法来查找非法下载并查明它们的来源。
      猜你喜欢
      • 2010-10-16
      • 2010-11-17
      • 2010-12-07
      • 2020-05-26
      • 1970-01-01
      • 1970-01-01
      • 2018-04-09
      • 1970-01-01
      相关资源
      最近更新 更多