Как мне поддерживать совместимость с десериализацией в обфускированных и отладочных сборках?
-
21-08-2019 - |
Вопрос
Я пытаюсь заставить {smartassembly} .СЕТЕВОЙ обфускатор работать с моей системой.В настоящее время я храню пользовательские данные в серии сериализованных классов словаря, а затем десериализую эти классы, чтобы получить данные обратно.Я уже игнорирую информацию о версии сборки, просто потому, что таким образом усложняю жизнь.Этот код является адаптировано из 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;
}
}
Проблема в том, что теперь мое запутанное приложение будет игнорировать информацию о версии, но не сможет прочитать данные, сохраненные не запутанным приложением, и наоборот.Нам понадобится версия без обфускации, чтобы отлаживать приложение, так что для нас это довольно большая проблема.Есть какой-нибудь способ обойти эту проблему?Должен ли я просто не запутывать классы данных?Это похоже на довольно большую брешь в системе безопасности.
Решение
Возможно, рассмотрите сериализатор, который не привязан к типу и именам полей?Например, protobuf-сеть является двоичным сериализатором, но использует числовые теги, установленные (через атрибут) для каждого элемента.Это означает:
- сериализация вообще не привязана к версии сборки
- информация об имени поля отсутствует в сериализованном файле
- (исходя из вышесказанного) не будет иметь значения, является ли код запутанным
- (и) файл не может быть использован для тривиального нарушения обфускации (хотя данные все еще могут указывать на намерение, если они не зашифрованы)
Например:
[ProtoContract]
public class Foo {
[ProtoMember(1)]
public string Bar {get;set;}
}
Здесь, в 1
это все, что идентифицировало участника в файле.Ключевым моментом здесь является то, что он основан на контракте, поэтому позже может быть десериализован с использованием несвязанного типа:
[ProtoContract]
public class a12 {
[ProtoMember(1)]
public string a {get;set;}
}
(что нормально, поскольку запутывание сохраняет метаданные, IIRC).
Сравните это с другими сериализаторами на основе контрактов (такими как XmlSerializer
или DataContractSerializer
) - где вы были бы вынуждены указать имя участника в атрибутах, что в значительной степени сделало бы запутывание бессмысленным:
[DataContract]
public class a12 {
[DataMember(Name="Bar")]
public string a {get;set;}
}
Другие советы
Обфускация, в первую очередь, не обеспечивает безопасность.Так что, возможно, вы захотите отказаться от этого, и точка.
Два варианта, которые я вижу, таковы:
- Не запутывайте эти типы.Это заставит все просто работать.
- Напишите свой собственный код сериализатора.
Поскольку вы ничего не добьетесь, запутывая, я бы выбрал # 1.