難読化ビルドとデバッグ ビルド間で逆シリアル化の互換性を維持するにはどうすればよいですか?
-
21-08-2019 - |
質問
{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;
}
}
問題は、難読化されたアプリはバージョン情報を無視しますが、難読化されていないアプリによって保存されたデータを読み取ることができず、その逆も同様であることです。アプリケーションをデバッグするには難読化されていないバージョンが必要なので、これは私たちにとって非常に大きな問題です。この問題を回避する方法はありますか?データクラスを難読化しないほうがよいでしょうか?これはかなり大きなセキュリティホールのようです。
解決
おそらく、型とフィールド名に関連付けられていないシリアライザーを検討してください。例えば、 プロトブフネット はバイナリ シリアライザーですが、各メンバーに対して (属性経由で) 設定された数値タグを使用します。これはつまり:
- シリアル化はアセンブリのバージョンにまったく関連付けられていません
- フィールド名の情報がシリアル化されたファイルにありません
- (上記により) コードが難読化されているかどうかは関係ありません
- (そして) このファイルを使用して難読化を簡単に解除することはできません (ただし、暗号化されていない限り、データは依然として意図を示唆している可能性があります)
例えば:
[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;}
}
他のヒント
難読化はそもそもセキュリティを提供しません。したがって、それを削除することを検討した方がよいかもしれません。
表示されるオプションは次の 2 つです。
- これらの型を難読化しないでください。これでうまくいきます。
- 独自のシリアライザー コードを作成します。
難読化しても何も得られないので、私は #1 を選択します。