Windows Telemetry服务特权提升
今天,我们将研究“互联的用户体验和遥测服务”,也称为“ diagtrack”。本文大量涉及与NTFS相关的术语,因此您需要对其有一个很好的了解。
反馈中心中称为“高级诊断”的功能引起了我的兴趣。它可由所有用户触发,并导致文件活动在C:WindowsTemp
,该目录对所有用户都可写。
对功能进行逆向工程并复制所需的交互是一个很大的挑战,因为它使用WinRT IPC而不是COM,而且我不知道WinRT的存在,因此我有一些工作要做。
在中C:Program FilesWindowsAppsMicrosoft.WindowsFeedbackHub_1.2003.1312.0_x64__8wekyb3d8bbweHelper.dll
,我发现了一个具有令人惊讶的可能性的函数:
WINRT_IMPL_AUTO(void) StartCustomTrace(param::hstring const& customTraceProfile) const;
此函数将执行WindowsPerformanceRecorder
在XML文件中定义的配置文件,该XML文件在Diagtrack服务的安全上下文中指定为自变量。
该文件路径是相对于该System32
文件夹进行解析的,因此我将一个XML文件放入了所有可写目录中,System32SpoolDriversColor
并将该文件路径相对于上述系统目录传递给了voila-Diagtrack开始了跟踪记录!
如果我们查看最低限度的WindowsPerformanceRecorder
配置文件,我们将看到以下内容:
<WindowsPerformanceRecorder Version="1">
<Profiles>
<SystemCollector Id="SystemCollector">
<BufferSize Value="256" />
<Buffers Value="4" PercentageOfTotalMemory="true" MaximumBufferSpace="128" />
</SystemCollector>
<EventCollector Id="EventCollector_DiagTrack_1e6a" Name="DiagTrack_1e6a_0">
<BufferSize Value="256" />
<Buffers Value="0.9" PercentageOfTotalMemory="true" MaximumBufferSpace="4" />
</EventCollector>
<SystemProvider Id="SystemProvider" />
<Profile Id="Performance_Desktop.Verbose.Memory" Name="Performance_Desktop"
Description="exploit" LoggingMode="File" DetailLevel="Verbose">
<Collectors>
<SystemCollectorId Value="SystemCollector">
<SystemProviderId Value="SystemProvider" />
</SystemCollectorId>
<EventCollectorId Value="EventCollector_DiagTrack_1e6a">
<EventProviders>
<EventProviderId Value="EventProvider_d1d93ef7" />
</EventProviders>
</EventCollectorId>
</Collectors>
</Profile>
</Profiles>
</WindowsPerformanceRecorder>
信息披露
完全控制文件会带来一些可能性。EventCollector
元素的name属性用于创建记录的跟踪的文件名。文件路径变为:
C:WindowsTempDiagTrack_alternativeTraceWPR_initiated_DiagTrackAlternativeLogger_DiagTrack_XXXXXX.etl
(其中XXXXXX是name属性的值。)
通过将名称设置为:....file.txt:
可以轻松获得对文件名和路径的完全控制:
C:WindowsTempDiagTrack_alternativeTraceWPR_initiated_DiagTrackAlternativeLogger_DiagTrack....file.txt:.etl
这导致C:WindowsTempfile.txt
被使用。
SYSTEM使用FILE_OVERWRITE_IF作为配置打开记录的跟踪,因此可以覆盖SYSTEM可以写入的任何文件。::$INDEX_ALLOCATION
也可以在SYSTEM可以写的位置中创建文件和目录(通过添加)。
从信息公开的角度来看,为服务执行的跟踪选择任何ETW提供程序的能力也很有趣。
我可以看到自己使用数据的一种情况是您不知道文件名,因为服务在您无权列出文件的文件夹中创建文件。
这样的文件名可能会被Microsoft-Windows-Kernel-File
提供程序泄漏,如本摘要所示,从添加22FB2CD6-0E7B-422B-A0C7-2FAD1FD0E716
到WindowsPerformanceRecorder
配置文件中记录的etl文件中泄漏出来。
<EventData>
<Data Name="Irp">0xFFFF81828C6AC858</Data>
<Data Name="FileObject">0xFFFF81828C85E760</Data>
<Data Name="IssuingThreadId"> 10096</Data>
<Data Name="CreateOptions">0x1000020</Data>
<Data Name="CreateAttributes">0x0</Data>
<Data Name="ShareAccess">0x3</Data>
<Data Name="FileName">DeviceHarddiskVolume2UsersjonasOneDriveDokumenterFeedbackHubDiagnosticLogsInstall and Update-Post-update app experience2019-12-13T05.42.15-SingleEscalations_132206860759206518file_14_ProgramData_USOShared_Logs__</Data>
</EventData>
这种泄漏可能会在看似无法开采的情况下产生开采可能性。
其他安全绕过提供程序:
Microsoft-Windows-USB-UCX {36DA592D-E43A-4E28-AF6F-4BC57C5A11E8}
-
Microsoft-Windows-USB-USBPORT {C88A4EF5-D048-4013-9408-E04B7DB2814A}
(捕获原始USB数据,从而启用键盘记录) Microsoft-Windows-WinINet {43D1A55C-76D6-4F7E-995C-64C711E5CAFE}
-
Microsoft-Windows-WinINet-Capture {A70FF94F-570B-4979-BA5C-E59C9FEAB61B}
(捕获了来自iexplore,Microsoft Store等的原始HTTP流量-SSL流获得了预加密的捕获。) -
Microsoft-PEF-WFP-MessageProvider
(IPSEC VPN数据预加密)
代码执行
关于信息公开已经足够了,我们如何将其转变为代码执行?
控制.etl
文件目标的能力很可能不会轻易导致代码执行;寻找另一个入口点可能是必要的。对文件内容的有限控制使利用变得非常困难。也许设计一个可执行的PowerShell脚本或bat文件是合理的,但是然后就有了使这些脚本执行的问题。
相反,我选择将我的活动跟踪记录与对以下调用的结合:
WINRT_IMPL_AUTO(Windows::Foundation::IAsyncAction) SnapCustomTraceAsync(param::hstring const& outputDirectory)
当提供一个outputDirectory
位于内部的值%WINDIR%tempDiagTrack_alternativeTrace
(.etl
保存正在运行的跟踪文件的位置)时,就会出现一个有趣的行为。
Diagtrack服务会将所有创建的.etl
文件重命名DiagTrack_alternativeTrace
到作为outputDirectory
参数指定的目录中SnapCustomTraceAsync
。这允许获取目标控制,因为可以利用重命名操作来执行在授予非特权用户写访问权限的文件夹中创建源文件的位置。这是由于文件及其父目录的权限继承。通过重命名操作移动文件时,DACL不会更改。这意味着,如果我们可以使目标变为%WINDIR%System32
,并且以某种方式移动文件,那么我们仍将对该文件具有写权限。因此,我们知道我们控制的outputDirectory
参数SnapCustomTraceAsync
,但是存在一些限制。
如果选择outputDirectory
的不是的子项%WINDIR%tempDiagTrack_alternativeTrace
,则不会重命名。在outputDirectory
不能存在,因为Diagtrack服务必须创建它。创建后,将以SYSTEM作为其所有者来创建它。仅将READ权限授予用户。
这是有问题的,因为我们无法将目录放入挂载点。即使我们具有必需的权限,也无法通过清空目录来停止它,因为Diagtrack已将快照输出etl文件放在其中。幸运的是,我们可以通过在outputDirectory
目标和之间创建两个间接级别来规避这些障碍DiagTrack_alternativeTrace
。
通过创建文件夹DiagTrack_alternativeTraceextraindirections
并提供%WINDIR%tempDiagTrack_alternativeTraceextraindirectionssnap
,outputDirectory
我们就可以让Diagtrack创建具有有限权限的snap文件夹,就像我们在里面一样DiagTrack_alternativeTrace
。这样,我们可以重命名该extra
文件夹,因为它是由我们创建的。由于Diagtrack在目录内有打开的文件,因此需要两个间接级别来绕过目录的锁定。当extra
被重命名,我们可以重新创建%WINDIR%tempDiagTrack_alternativeTraceextraindirectionssnap
(现在为空),我们有充分的权限,把它作为我们的主人!
现在,我们可以将DiagTrack_alternativeTraceextraindirectionssnap
目标指向一个挂载点%WINDIR%system32
,Diagtrack会将所有匹配的文件WPR_initiated_DiagTrack*.etl*
移入%WINDIR%system32
。在授予用户写入权限的文件夹中创建文件后,这些文件仍将是可写的。不幸的是,对System32中的文件进行完全控制还不足以执行代码……也就是说,除非我们有一种执行用户可控制的文件名的方法,例如James Forshaw流行的DiagnosticHub插件方法。尽管有一个警告,但DiagnosticHub现在需要它加载的所有DLL都必须由Microsoft签名,但是我们确实有一些方法可以在SYSTEM安全上下文中的system32中执行DLL文件-如果文件名是特定的。但是,另一个缺点是文件名不可控。那么,我们该如何控制?
如果不是以安装点为目标System32,而是以NT命名空间为对象目录,并创建一个与重命名目标文件同名的符号链接,则可以控制文件名。符号链接的目标将成为重命名操作的目标。例如,将其设置??%WINDIR%system32phoneinfo.dll
为对文件的写许可权,当错误报告提交到进程外时,错误报告服务将加载并执行。对于我的安装点目标,我选择了RPC Control
它,因为它允许所有用户在其中创建符号链接。
试试吧!
当Diagtrack应该进行重命名时,什么也没发生。这是因为在完成重命名操作之前,已打开目标文件夹,但现在是对象目录。这意味着无法通过文件/目录API调用打开它。通过将创建挂载点的时间设置为在打开文件夹之后但重命名之前,可以避免这种情况。通常在这种情况下,我会在目标文件夹中创建一个与重命名目标文件同名的文件。然后我在文件上放了一个oplock,当锁中断时,我知道文件夹检查已完成,并且重命名操作即将开始。在释放锁之前,我将文件移动到另一个文件夹,然后在当前为空的文件夹上设置安装点。尽管由于将重命名操作配置为不覆盖已经存在的文件,所以该技巧这次将不起作用。这也意味着重命名将由于现有文件而中止-不会触发oplock。
在放弃的时刻,我意识到了一些事情:
如果我每隔一毫秒就将良性文件夹和对象目录之间的交接点切换目标作为目标,那么在完成文件夹检查时就有50%的机会获得良性目录,而在重命名发生时有50%的机会获得对象目录。这样就有25%的机会进行重命名以验证支票,但最终结果是phoneinfo.dll
在System32中。如果可能,我会尽量避免出现比赛情况,但是在这种情况下,似乎没有其他前进的方向,我可以通过重复该过程来弥补失败的机会。为了适应失败的可能性,我决定触发任意数量的重命名,幸运的是,对于我们来说,有一个流程的细节可以触发同一记录中想要的尽可能多的重命名。重命名未链接到诊断服务知道其已创建的文件,因此唯一的要求是它们必须存在%WINDIR%tempDiagTrack_alternativeTrace
并匹配WPR_initiated_DiagTrack*.etl*
既然我们有权限在目标文件夹中创建的文件,我们现在可以创建WPR_initiated_DiagTrack0.etl
,WPR_initiated_DiagTrack1.etl
等,他们都将获得改名!
由于目标是像phoneinfo.dll
System32一样最终的文件之一,为什么不仅仅将文件创建为指向预期有效负载的硬链接呢?这样,移动后无需使用WRITE权限覆盖文件。
经过一些实验后,我得出以下解决方案:
- 创建文件夹
%WINDIR%tempDiagTrack_alternativeTraceextraindirections
- 开始诊断跟踪
-
%WINDIR%tempDiagTrack_alternativeTraceWPR_initiated_DiagTrackAlternativeLogger_WPR System Collector.etl
被建造
-
- 创建
%WINDIR%tempDiagTrack_alternativeTraceWPR_initiated_DiagTrack[0-100].etl
到有效负载的硬链接。 - 创建符号链接
RPC ControlWPR_initiated_DiagTrack[0-100.]etl
定位%WINDIR%system32phoneinfo.dll
- 打开OPLOCK
WPR_initiated_DiagTrack100.etl
; 损坏时,检查是否%WINDIR%system32phoneinfo.dll
存在。如果没有,请重复创建WPR_initiated_DiagTrack[].etl
文件和匹配的符号链接。 - 打开OPLOCK
WPR_initiated_DiagTrack0.etl
; 当它损坏时,我们知道重命名流程已经开始,但是第一次重命名操作尚未发生。
破损时:
- 重命名
%WINDIR%tempDiagTrack_alternativeTraceextra
为%WINDIR%tempDiagTrack_alternativeTrace{RANDOM-GUID}
- 建立资料夹
%WINDIR%tempDiagTrack_alternativeTraceextraindirectionssnap
- 循环中的启动线程
%WINDIR%tempDiagTrack_alternativeTraceextraindirectionssnap
在作为安装点目标%WINDIR%tempDiagTrack_alternativeTraceextra
和RPC Control
在NT对象名称空间之间切换。 - 使用
%WINDIR%tempDiagTrack_alternativeTraceextraindirectionssnap
as启动快照跟踪outputDirectory
执行后,将重命名100个文件。如果它们都不phoneinfo.dll
在system32中,它将重复直到成功。
然后,我添加了检查%WINDIR%system32phoneinfo.dll
切换连接点的线程中是否存在的检查。切换之间的延迟增加似乎增加了重命名之一创建的机会phoneinfo.dll
。测试显示循环在前100次迭代结束时结束。
检测到时%WINDIR%system32phoneinfo.dll
,会将空白错误报告提交给Windows错误报告服务,该错误报告配置为从proc之外提交,从而导致在SYSTEM安全上下文中wermgmr.exe
加载刚创建的错误报告phoneinfo.dll
。
有效负载是一个DLL,DLL_PROCESS_ATTACH
将检查SeImpersonatePrivilege
并在启用cmd.exe
后将其生成在当前活动桌面上。如果没有特权检查,则会生成其他命令提示符,因为phoneinfo.dll
启动错误报告的进程也试图加载该命令。
此外,还会使用显示一条消息,WTSSendMessage
因此即使无法在正确的会话/桌面中生成命令提示符,我们也可以获取成功的指示。
红色是因为我的命令提示自动执行echo test> C:windows:stream && color 4E
; 这使得所有UAC提升的命令提示符的背景颜色为红色,以此指示我。
尽管我在存储库中的示例包含私有库,但对它的工作原理进行总体概述可能仍然是有益的。
- sed的粉丝
- 在Managed Code通过Google Gmail发送邮件以及如何通过Outlook配置Gmail
- 平方根的C语言实现(一) —— 浮点数的存储
- 用awk写递归
- bc计算A股上市新股依次涨停股价
- ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式
- python访问http的GET/POST
- 用openssl库RSA加密解密
- Kobject浅析
- ASP.NET Core应用的错误处理[2]:DeveloperExceptionPageMiddleware中间件如何呈现“开发者异常页面”
- RSA简介(二)——模幂算法
- 为虚拟机vCPU绑定物理CPU
- RSA简介(三)——寻找质数
- RSA简介(四)——求逆算法
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 解决vue+axios请求报错POST http: net::ERR_CONNECTION_REFUSED,在封装的请求中统一处理请求异常的问题
- PAT (Basic Level) Practice (中文)1025 反转链表 (25 分)
- Pytest+Allure接口自动化一些学习分享
- 数据结构___马踏棋盘详尽实现+报告+通俗易懂注释
- 使用elasticsearch-dump迁移elasticsearch集群数据
- PAT (Basic Level) Practice (中文)1027 打印沙漏 (20 分)
- PAT (Advanced Level) Practice 1002 A+B for Polynomials (25 分)
- 关于MySQL varchar类型最大值,原来一直都理解错了
- PAT (Basic Level) Practice (中文)1028 人口普查 (20 分)
- 稀疏矩阵计算器(三元组实现矩阵加减乘法)
- PAT (Basic Level) Practice (中文)1029 旧键盘 (20 分)
- WPF 获取屏幕某个点的颜色
- 谈一谈递归算法
- 二、类加载器与类初始化深度剖析
- PAT (Basic Level) Practice (中文)1030 完美数列 (25 分)