const和static readonly在字符串混淆中有什么区别?

5
我们会通过混淆器来运行我们的.NET二进制文件(至少启用字符串混淆),然后在构建过程中进行一些基本检查以验证此操作。我惊讶地发现,将字符串从static readonly string更改为const string后,当查看反汇编代码(通过ildasm输出)时,更改后的字符串现在以明文形式可见。
关于字符串混淆,const stringstatic readonly string之间有什么区别? 编辑: 为了举例说明,这里是一个小程序:
class Program
{
    private const string MyConstString = "MyConstString";
    private static readonly string MyStaticReadonlyString = "MyStaticReadonlyString";

    static void Main(string[] args)
    {
        string myLocalString = "myLocalString";

        Console.WriteLine(MyConstString);
        Console.WriteLine(MyStaticReadonlyString);
        Console.WriteLine(myLocalString);

        Console.WriteLine("Hit <ENTER> to exit");
        Console.ReadLine();
    }
}

在查看.il代码后,唯一以明文形式呈现的值是const string。这对于两个不同的混淆工具都是正确的:

.field private static literal string a = "MyConstString"       // using Dotfuscator
.field private static literal string '[SOH]' = "MyConstString" // using RedGate SmartAssembly

2
使用您的混淆器,以下代码中的字符串“Foo”是否会被混淆?Console.WriteLine("Foo"); - Daniel Hilgarth
@DanielHilgarth 是的,那是混淆的。 - jglouie
@Blam RedGate的SmartAssembly 6也会出现这种情况。 - jglouie
2个回答

5
对于 const 字段,它们的值必须直接包含在程序集中,这是无法避免的。因为编译器必须能够获取此类字段的值,而不执行任何自定义代码。
对于 static readonly 字段,混淆器可以使用静态构造函数执行任何想要的代码,这意味着它们可以被混淆。

为什么混淆器不能修改常量值并调整使用该常量值的每个位置? - jglouie
1
因为它不可能知道“每个其他地方”是什么。您可以使用反射检索const的值,混淆器无法调整该值。对于public类型中的public consts来说,情况更糟,因为任何人都可以从外部使用它。 - svick
同样的论点也可以用于静态只读字符串,对吧?混淆器不知道这些值是通过反射读取还是被外部使用,但它仍然对它们进行了混淆。 - jglouie
@jglouie 但是通过反射加载混淆的readonly字段仍然可以工作,因为在执行混淆代码后,您会得到正确的值。对于const,不同之处在于不能有任何代码。 - svick

0
如果是静态的,那么字符串值存在于程序的数据段中,它有一个地址,并且在代码中通过其地址引用。
而如果是常量,则存在于代码段中的字符串字面量。

那对字符串混淆有什么影响? - jglouie
我将这个回答设为“社区维基”,因为我不确定这个答案是否正确,但我没有删除它,以防它有帮助。 - ChrisW
@jglouie 这取决于你的混淆器是如何实现的:例如,也许混淆器会在运行时解密数据段,或者在从数据段读取字符串值时即时解密。 - ChrisW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接