2

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

还有另一种方法可以做到这一点吗?

4

4 回答 4

3

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

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

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

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

也看看这个:链接

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

于 2009-08-14T04:13:38.857 回答
1

在 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),因此如果您想用更短的内容对其进行标记,则需要填充长度。

于 2009-08-15T15:34:31.317 回答
1

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

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

关键考虑因素#2:constreadonly

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

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 结尾的长度小于或等于当前在二进制文件中找到的字符串的长度,就可以进行内联替换。

最后,谷歌报告了以下关于水印软件的文章,您可能想看看。

于 2009-08-15T16:04:50.897 回答
0

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

于 2009-08-14T04:08:39.100 回答