发布于2025年12月5日12月5日 在长汀牧云(云行者)团队中,有一群孜孜不倦、不断探索的研究人员,专门治疗攻防场景中的各种“疑难杂症”。 \r 2022年,超听科技推出“主机安全技术专栏”,分享最实用、最深入的安全研究。 \r ## 简介\r Windows提权是攻防对抗中不可避免的话题。目前,CloudWalker主机安全管理平台已支持通用的Windows提权检测。如需了解更多信息或提交简历,请联系我们:[email protected]\r \r 长亭科技《主机安全技术专栏》推出三期分享Windows提权。本期为应用章节。从权限级别的角度,我们介绍两种Win提权姿势:从普通用户到管理员用户,从服务帐户到SYSTEM。我们分享一下近年来国内外最流行、最广泛的提权方法。应用章节的阅读顺序不分先后。读者可以根据自己的需要选择阅读内容。 \r \r ## 目录\r ### 1.从普通用户到管理员帐户(BypassUAC)\r 1.1 UAC逆向分析\r 1.2 找到可用的BypassUAC\r 1.3 UAC如何进行提权\r 1.4 使用ICMLuaUtil提权\r 1.5 使用白名单程序实现BypassUAC\r \r ### 2.从服务帐户到SYSTEM\r 2.1 热土豆\r 2.2 烂土豆\r 2.3 管道土豆(BadPotato)\r 2.4 PetitPotam提权\r \r 了解Windows操作系统本地提权的原理和方法并提供指导【基本概念】https://mp.weixin.qq.com/s/GuCCdVWV2KjzTB2Br1T28A\r \r ##0x01 从普通用户到管理员帐户(BypassUAC)\r \r 这方面的落实一直是一个经久不衰的话题。这里我要讨论的可能大家已经猜到了,那就是BypassUAC。当然,BypassUAC可能不是这里唯一实现普通用户到管理员用户转变的方法,但目前主流的方法仍然是BypassUAC\r UAC 是Microsoft 在Microsoft Windows Vista 更高版本中引入的一种安全机制。它的工作原理是通知用户应用程序是否正在使用硬盘驱动器和系统文件授权,以帮助防止恶意程序(有时称为“恶意软件”)损坏系统。 \r 通过UAC,应用程序和任务始终可以在非管理员帐户的安全上下文中运行,除非管理员专门授予管理员级别的系统访问权限。 UAC 可防止未经授权的应用程序自动安装并防止无意中更改系统设置。 \r 下图清楚地描述了如何根据是否启用UAC 以及应用程序是否具有UAC 清单来运行应用程序\r \r UAC开启后,如果用户是标准用户,Windows会为该用户分配一个标准的Access Token。如果用户以管理员权限登录,则会生成两种访问令牌,一种是完全管理员访问令牌(Full Access Token),另一种是标准用户令牌。 Token相关的知识前面已经提到过,这里不再赘述\r 在绝大多数BypassUAC实现中,笔者认为利用方式主要可以分为两类:\r 1、各种UAC白名单程序的DLL劫持(Dll Hijack)\r 2. 各类提升权限的COM接口利用(Elevated COM interface)\r 这里我们先以第二种方法为例,结合实际的BypassUAC组件来分析如何将普通用户权限提升到管理员帐户\r \r ### 1.1 UAC逆向分析\r 首先我们需要知道的是,任务管理器中以管理员身份启动的进程的父进程是explorer。但是,如果在资源管理器中的KERNELBASE!CreateProcessW 处设置断点,并且程序以管理员权限运行,则不会中断。然而,正常启动的程序可以正常被破坏。这表明提升的程序很可能不是由资源管理器启动的。 \r 资源管理器本身并不是一个具有SYSTEM权限的进程。如果提权过程是由explorer进程发起的,则无法达到提权的目的。为此,我们首先在KERNELBASE!CreateProcessW中设置断点,然后正常启动一个程序,查看调用堆栈分析:\r \r 从文件名可以看出该函数位于windows_storage.dll中。反编译查看函数:的实现过程\r 发现CInvokeCreateProcessVerb:CallCreateProcess实际上会调用AicLaunchAdminProcess\r \r 我们跟进这个函数:\r \r 可以看到这里实际上是进行了RPC通信。我们可以根据绑定句柄的UUID值找到对应的接口。这里我们使用Rpcview查看:\r \r 其实我们在服务中还可以看到appinfo服务。对应的描述与UAC的实现非常相似\r \r 这里获取的接口对应的DLL是appinfo.dll。我们将其拖入IDA中来分析DLL:\r 我们发现这个dll中的大部分导出函数都使用RPCRT4 :\r \r RPC 函数(远程过程调用)允许一个程序调用另一台计算机上的子例程\r 本地过程调用(LPC,Local procedure Call)在本地进程之间进行通信。 \r 通过前面的了解,我们已经知道UAC验证是利用API AiLaunchAdminProcess来实现的。根据接口地址,我们找到了对应的函数RAiLaunchAdminProcess。在该函数的实现中,我们发现AiLaunchAdminProcess:\r \r 封装了CreateProcessAsUser函数来执行提权操作,所以实际上在整个UAC提权过程中,appinfo服务完成了提权过程\r \r \r ### 1.2 找到可用的BypassUAC\r \r 当然这还没有结束。我们知道UAC过程中会弹出认证框,所以我们还需要分析整个弹窗过程:\r 弹窗的整体流程为\r ```RAiLaunchAdminProcess - AiCheckLUA - AiLaunchConsentUI```\r 从名字上我们很容易想到AiLaunchConsentUI应该是实现弹窗的过程,所以我们继续跟进这个函数进行分析:\r ```swprintf_s(Buffer,0x3Dui64, L\'consent.exe %u %u %p\', CurrentProcessId, phkResult, a2);```\r 然后调用AiLaunchProcess启动consent.exe,也就是真正绘制uac窗口的程序:\r \r 由此我们知道consent.exe程序是一个用来绘制uac窗口的程序,因此我们对该程序进行逆向分析,通过分析解决以下问题\r - 在Consent绘制的UAC窗口中,我们可以看到要提升的程序的路径、命令行等相关信息。 Consent 如何获取这些信息? \r \r consent命令行传入父进程的pid(appinfo服务的进程pid)、一个结构体长度和一个指向该结构体的指针。然后consent调用NtReadVirtualMemory从父进程的内存中读取该结构体的内容。该结构包含需要权限提升的进程信息。 \r - 同意程序如何将用户的操作反馈给appinfo服务进程?\r \r 同样通过调用NtWriteVirtualMemory写入内存并传递给appinfo服务的内存\r 通过分析发现,决定是否弹窗的关键函数是:\r \r 后续发现对COM组件进行了判断,判断主要是根据COM组件的Elevation属性:\r \r 继续返回appinfo.dll查看逻辑。我们已经知道BypassUAC有两个主要方法:\r 1、各种UAC白名单程序的DLL劫持(Dll Hijack)\r 2. 各类提升权限的COM接口利用(Elevated COM interface)\r 找到第一个判断对应的函数AiIsEXESafeToAutoApprove:\r \r 继续关注此功能:\r \r 此时我们已经用autoElevate获取了官方支持的可执行文件列表,即UAC白名单\r \r \r ### 1.3 UAC如何进行提权\r \r 说到这里,你可能还得回到同意程序。其实整个UAC流程就是appinfo和consent的过程。 CuiCheckElevationAutoApprovalMedium判断完成后,通过LABLE_78调用NtQueryInformationToken,获取权限提升token\r \r 但在此之前,判断通过CuiGetTokenForApp获取了权限较高的TokenHandle。由于逆向工程水平较低,我们没有对该函数进行后续进一步的底层分析\r \r 然后通过NtDuplicateObject和NtWriteVirtualMemory将提升的令牌写回appinfo服务进程\r \r \r 至此,UAC的整个流程应该就差不多完成了。最后做个整体总结\r 请求进程通过LPC接口将请求的进程cmdline和进程路径传递给appinfo的RAiLuanchAdminProcess函数。该函数首先验证路径是否在白名单中,并将结果传递给consent.exe进程。该流程验证请求的进程签名和发起者的权限是否满足要求,然后决定是否弹出UAC框让用户确认。这个UAC框将创建一个新的安全桌面并阻止以前的界面。同时,这个UAC盒子进程是一个SYSTEM权限进程,其他普通进程无法与其通信和交互。用户确认后,调用CreateProcessAsUser函数以管理员权限启动请求的进程。 \r \r ### 1.4 使用ICMLuaUtil 进行权限提升\r \r COM Elevation Moniker 技术允许在用户帐户控制(UAC) 下运行的应用程序通过提升权限来激活COM 类,从而提升COM 接口权限。 \r 我们可以从UACME项目中查看相应的使用方法。该组件对应工程中实现的具体函数名称为:ucmCMLuaUtilShellExecMethod\r \r UACME项目迄今为止已经总结了60多种绕过UAC的方法,并列出了UAC白名单程序或具有自动提升功能的接口。 \r \r 该函数的源码如下:\r ````\r NTSTATUS ucmCMLuaUtilShellExecMethod(\r _In_ LPWSTR lpsz可执行文件\r )\r {\r NTSTATUS 方法结果=STATUS_ACCESS_DENIED;\r HRESULT r=E_FAIL, hr_init;\r BOOL b批准=FALSE;\r ICMLuaUtil* CMLuaUtil=NULL;\r \r hr_init=CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);\r \r 做{\r \r //\r //潜在的修复检查。\r //\r if (supIsConsentApprovedInterface(T_CLSID_CMSTPLUA, bApprove)) {\r if (bApprove==FALSE) {\r 方法结果=STATUS_NOINTERFACE;\r 中断;\r }\r }\r \r r=ucmAllocateElevatedObject(\r T_CLSID_CMSTPLUA,\r IID_ICMLuaUtil,\r CLSCTX_LOCAL_SERVER,\r (void**)CMLuaUtil);\r \r if (r !=S_OK)\r 中断;\r \r 如果(CMLuaUtil==NULL){\r r=E_OUTOFMEMORY;\r 中断;\r }\r \r r=CMLuaUtil-lpVtbl-ShellExec(CMLuaUtil,\r lpsz可执行文件,\r 空,\r 空,\r SEE_MASK_DEFAULT,\r SW_SHOW);\r \r if (成功(r))\r 方法结果=STATUS_SUCCESS;\r \r } while (FALSE);\r \r if (CMLuaUtil!=NULL) {\r CMLuaUtil-lpVtbl-Release(CMLuaUtil);\r }\r \r if (hr_init==S_OK)\r CoUninitialize();\r \r 返回方法结果;\r }\r ````\r 结合源码我们可以看到,CMSTPLUA组件中的ICMLuaUtil接口用于查找对应的CLSID,对应的是{3E5FC7F9-9A51-4367-9063-A120244FBEC7}\r \r 我们在上一篇文章中已经了解了UAC的整个流程。我们知道,同意程序会调用CuiIsCOMClassAutoApprovable函数来判断是否存在自动权限提升的COM组件。判断标志为搜索高程属性是否为自动审批\r \r 组件有这个属性,所以如果要使用COM组件进行权限提升,必须满足的条件之一就是Elevation属性中的Enabled和Auto Approval都为True\r \r 这里我们使用的是ICMLuaUtil接口,所以继续分析cmlua.dll\r \r 我们主要看DLL的虚函数表是否有可以使用的函数\r \r 函数原型如下:\r ````\r __int64 __fastcall CCMLuaUtil:ShellExec(\r CCMLuaUtil *这个,\r 常量无符号__int16 *a2,\r 常量无符号__int16 *a3,\r 常量无符号__int16 *a4,\r 无符号整型a5,\r 无符号整型a6)\r /* \r pExecInfo.lpFile=a2;\r pExecInfo.lpParameters=a3;\r pExecInfo.lpDirectory=a4;\r pExecInfo.fMask=a5;\r pExecInfo.nShow=a6;\r */\r ````\r 所以我们在创建并实例化接口时,调用接口的ShellExec方法创建指定进程即可BypassUAC\r \r 这里我们使用该组件编写了一个程序,通过C#进行提权。其核心代码如下:\r \r 编译完成运行后发现程序仍然弹出UAC框进行验证。这是因为如果执行COM Elevation Moniker代码的程序身份不可信,就会触发UAC弹窗。我们这里的程序还没有被验证\r \r 默认情况下可以绕过UAC的文件或程序需要满足以下三个条件:\r •\t该程序配置为自动提升权限并以管理员权限执行\r •\t程序包含签名\r •\t从受信任目录(c:\\windows\\system32)执行\r 因此,我们需要使用系统的可信进程来进行调用。选项包括rundll32.exe、explorer.exe等,你只需要将创建COM组件的代码和执行你要执行的命令的代码放入可信进程中执行,这样就可以BypassUAC。 \r 第一种对应方法是生成DLL文件,将实现放在DLLmain中,调用rundll32.exe或cmstp.exe来执行DLL文件。不过考虑到该文件会落地,而且rundll32.exe本身已经被很多杀毒软件监控,所以这种方法并不是首选方法。 \r 第二种方法导致了另一种称为MasqueradePEB 的技术\r 进程信息,包括命令行参数、映像位置、加载的模块等,都存储在进程控制块中,并且可以在用户空间中访问和修改该结构。通过修改PEB进程控制块,欺骗系统认为该进程是合法进程\r 请注意,修改自己进程的进程控制块时不需要SeDebugPrivilege 权限\r UAC根据PEB结构判断系统进程是否可信。因此,在使用COM组件提权之前,我们将进程信息伪装成可信程序,如c:\\windows\\explorer.exe等来BypassUAC\r 调用伪装成explorer.exe的PEBMasq.MasqueradePEB时\r \r 我们执行程序,发现现在不会弹出UAC框了,成功获得了具有管理员权限的cm。
创建帐户或登录后发表意见