0X01 背景
.NET反序列化漏洞里的核心Gadget:ObjectDataProvider类,封装于WPF核心程序集之一PresentationFramework.dll,处于System.Windows.Data命名空间下,顾名思义就是把一个非静态类实例化后的对象作为数据源提供给WPF控件绑定,常见用法如下
ObjectDataProvider obj = new ObjectDataProvider();
obj.MethodParameters.Add("calc");
obj.MethodName = "Start";
obj.ObjectInstance = new System.Diagnostics.Process();
ObjectDataProvider对象的ObjectInstance设置为Process对象,MethodName设置为Process类的Start方法,MethodParamers为Start方法传递的参数 calc
如上图进入ObjectDataProvider类的定义发现ObjectType可被设置为任意类型, 由于Type是一个抽象类,不能直接被new 关键词创建对象,但可用以下3种方法得到Type实例的引用
第1种:使用C# typeof操作符 获取 Process 类型信息的引用,如下
ObjectDataProvider objectDataProvider = new ObjectDataProvider()
{
ObjectType = typeof(System.Diagnostics.Process)
};
objectDataProvider.MethodParameters.Add("calc");
objectDataProvider.MethodName = "Start";
第2种:可使用 System.Type类的静态成员 GetType(文本,是否抛出异常,区分大小写) , 需在第一个参数指定类型的完全限定名,限定名包含了类所在的命名空间、程序集名、版本、语言、PublicKeyToken,采用这种方法的好处在于可指定文本信息,编译时不需要提供数据类型,如下
ObjectDataProvider objectDataProvider = new ObjectDataProvider()
{
ObjectType = Type.GetType("System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", true,true);
};
objectDataProvider.MethodParameters.Add("calc");
objectDataProvider.MethodName = "Start";
第3种:可使用 System.Object.GetType() , 返回表示当前对象的Type实例,其实从.NET 源码可见ObjectInstance底层实现也是通过对象的GetType()得到类型,改写的代码如下
ObjectDataProvider objectDataProvider = new ObjectDataProvider()
{
ObjectType = new System.Diagnostics.Process().GetType()
};
objectDataProvider.MethodParameters.Add("calc");
objectDataProvider.MethodName = "Start";
0X02 ObjectDataProvider调用链
下图描绘整个WPF项目窗体创建启动到ObjectDataProvider实例化调用对象过程中所有的调用链,右侧是WPF窗体创建过程调用链,左侧是ObjectDataProvider实例化载入任意对象过程的调用栈信息,整张图从右向左看
笔者在MainWindow窗体类中实例化了对象ObjectDataProvider,并且继承了DataSourceProvider类,DataSourceProvider定义了两个重要方法,Refresh方法调用虚方法BeginQuery,这个BeginQuery将来会在ObjectDataProvider类里实现。
public void Refresh()
{
this._initialLoadCalled = true;
this.BeginQuery();
}
protected virtual void BeginQuery()
{
}
然后这个过程干了3件事,第1件事进入ObjectDataProvider类的构造方法实例化集合,该集合ParameterCollection继承于Collection