Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I maintain deserialization compatibility across obfuscated and debug builds?

I'm trying to get the {smartassembly} .NET obfuscator to work with my system. I currently store user data in a series of serialized dictionary classes, and then deserialize those classes to get the data back. I'm already ignoring assembly version information, just because that way making life a pain. That code is adapted from 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;
    }
}

Problem is, now my obfuscated app will ignore versioning information, but can't read data saved by the non-obfuscated app, and vice versa. We'll need to have a non-obfuscated version in order to debug the application, so this is a pretty big showstopper for us. Any way to get around this problem? Should I just not obfuscate the data classes? That seems like a pretty large security hole.

like image 802
mmr Avatar asked Feb 05 '09 02:02

mmr


1 Answers

Perhaps consider a serializer that isn't tied to the type and field-names? For example, protobuf-net is a binary serializer, but uses numeric tags set (via an attribute) against each member. This means:

  • serialization isn't tied to the assembly version at all
  • the field name information isn't in the serialized file
  • (by the above) it won't matter whether the code is obfuscated
  • (and) the file can't be used to trivially break the obfuscation (although the data might still suggest intent unless encrypted)

For example:

[ProtoContract]
public class Foo {
    [ProtoMember(1)]
    public string Bar {get;set;}
}

Here, the 1 is all that identified the member in the file. The key here is that it is contract-based, so can be deserialized later with an unrelated type:

[ProtoContract]
public class a12 {
    [ProtoMember(1)]
    public string a {get;set;}
}

(which is fine since obfuscation preserves metadata, IIRC).

Contrast this to other contract-based serializers (such as XmlSerializer or DataContractSerializer) - where you would be forced to put the member-name in the attributes, which would pretty much render obfuscation pointless:

[DataContract]
public class a12 {
    [DataMember(Name="Bar")]
    public string a {get;set;}
}
like image 143
Marc Gravell Avatar answered Oct 11 '22 06:10

Marc Gravell