如何在混淆和调试版本中保持反序列化兼容性?

mmr*_*mmr 5 .net obfuscation serialization smartassembly

我正在尝试使用{smartassembly} .NET混淆器来处理我的系统.我目前将用户数据存储在一系列序列化的字典类中,然后反序列化这些类以获取数据.我已经忽略了汇编版本信息,只是因为这样会让生活变得痛苦.该代码改编自MSDN:

//to avoid cross-versioning problems
public sealed class CrossVersionDeserializationBinder : SerializationBinder {
    public override Type BindToType(string assemblyName, string typeName) {
        Type typeToDeserialize = null;

        typeToDeserialize = Type.GetType(String.Format("{0}, {1}",
            typeName, assemblyName));

        return typeToDeserialize;
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是,现在我的混淆应用程序将忽略版本控制信息,但无法读取非混淆应用程序保存的数据,反之亦然.为了调试应用程序,我们需要一个非混淆的版本,所以这对我们来说是一个非常大的showstopper.有什么方法可以解决这个问题吗?我应该不混淆数据类吗?这似乎是一个非常大的安全漏洞.

Mar*_*ell 7

也许考虑一个与类型和字段名称无关的序列化器?例如,protobuf-net是二进制序列化程序,但使用针对每个成员设置的数字标记(通过属性).这意味着:

  • 序列化根本不与程序集版本相关联
  • 字段名称信息不在序列化文件中
  • (通过上述)代码是否被混淆无关紧要
  • (和)该文件不能用于轻易打破混淆(虽然数据可能仍然建议意图,除非加密)

例如:

[ProtoContract]
public class Foo {
    [ProtoMember(1)]
    public string Bar {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

在这里,1所有标识了文件中的成员.这里的关键是它是基于契约的,因此可以在以后使用不相关的类型进行反序列化:

[ProtoContract]
public class a12 {
    [ProtoMember(1)]
    public string a {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

(由于混淆保留了元数据,因此很好,IIRC).

将此与其他基于合同的序列化程序(例如XmlSerializerDataContractSerializer)进行对比- 您将被迫将成员名称放在属性中,这几乎会使混淆变得毫无意义:

[DataContract]
public class a12 {
    [DataMember(Name="Bar")]
    public string a {get;set;}
}
Run Code Online (Sandbox Code Playgroud)