Как обеспечить совместимость десериализации между запутанными и отладочными сборками?

Я пытаюсь заставить обфускатор {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;
    }
}

Проблема в том, что теперь мое запутанное приложение будет игнорировать информацию о версиях, но не сможет прочитать данные, сохраненные не запутанным приложением, и наоборот. Нам понадобится не запутанная версия для отладки приложения, поэтому для нас это довольно большая проблема. Любой способ обойти эту проблему? Должен ли я просто не запутывать классы данных? Это похоже на довольно большую дыру в безопасности.


person mmr    schedule 05.02.2009    source источник


Ответы (2)


Возможно, стоит рассмотреть сериализатор, который не привязан к типу и именам полей? Например, protobuf-net – это двоичный сериализатор, но он использует набор числовых тегов (через атрибут) для каждого члена. Это означает:

  • сериализация вообще не привязана к версии сборки
  • информация об имени поля отсутствует в сериализованном файле
  • (из вышеизложенного) не имеет значения, запутан ли код
  • (и) файл не может быть использован для тривиального нарушения обфускации (хотя данные могут указывать на намерение, если только они не зашифрованы)

Например:

[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;}
}
person Marc Gravell    schedule 05.02.2009

Обфускация не обеспечивает безопасность в первую очередь. Таким образом, вы можете подумать о том, чтобы отказаться от него, и точка.

Я вижу два варианта:

  1. Не запутывайте эти типы. Это заставит все работать.
  2. Напишите свой собственный код сериализатора.

Поскольку вы ничего не получаете, запутывая, я бы выбрал № 1.

person MichaelGG    schedule 05.02.2009
comment
Мне нужно запутать, чтобы заставить работать ключ, потому что без запутывания будет легко удалить вызовы ключа. - person mmr; 05.02.2009
comment
Новость: будет очень легко удалить вызовы ключа даже с обфускацией. - person MichaelGG; 05.02.2009
comment
Может быть, даже со всеми специфическими приложениями, которые мы собираемся поместить в ключ. Это не предназначено для того, чтобы остановить преданного хакера, это предназначено для того, чтобы остановить бездельника, который удаляет ключ и может продолжать использовать программное обеспечение. - person mmr; 05.02.2009
comment
Ну, я не знаю вашего бизнеса, так что, может быть, это отличная идея. Но риск ключей для клиентов (ломается ключ = программное обеспечение мертво?), вкупе с тем, что его нужно взломать только одному человеку... - person MichaelGG; 05.02.2009
comment
Как правило, клиент отказывается платить, а затем ключ просто отключается. Затем, как только они заплатят, мы даем им работающий ключ. Сообразительный человек с Reflector или Ildasm просто проигнорирует проблему. - person mmr; 05.02.2009
comment
Ну, как я уже сказал, я не знаю ваших клиентов и т. д. Если это работает для вашей компании, отлично. Просто кажется интересным, что у вас есть клиенты, достаточно умные, чтобы разбирать и собирать заново, но недостаточно умные, чтобы использовать что-то вроде Cecil. - person MichaelGG; 05.02.2009
comment
Но в том-то и дело, что Cecil, Reflector и IlDasm относятся к одному и тому же классу декомпиляторов, и запутывание призвано помешать такому подходу. Поставщики обфускации гордятся тем, что ломают декомпиляторы. - person mmr; 06.02.2009
comment
Дизассемблеры и инспекторы метаданных не являются декомпиляторами. Пример. Переключение Reflector в режим IL позволяет проверять методы, которые в противном случае могли бы вызвать сбой в другой системе. Сесил тоже, кажется, рвется сквозь все подряд. Но эй, если это делает тебя счастливым, дерзай. - person MichaelGG; 06.02.2009