WIN32 动态 UAC 提权
UAC(User Account Control) 是 Windows 平台的用户权限控制。它可以让程序使用管理员权限执行某些操作。
静态 UAC 提权
静态 UAC 提权让程序一直运行在管理员权限下,只要在项目设置里把 "UAC Execution Level" 设置为 "requireAdministrator"。这样生成的 exe 文件图标会自动加上一个小盾牌的角标 Overlay。执行 exe 文件会自动弹出 UAC 对话框。

静态 UAC 提权对程序员来说是一种偷懒的办法,只需要修改一个配置就行。但对用户来说非常麻烦,每次打开程序都需要确认 UAC 对话框。比如“小黑盒加速器”,每次打开它都会弹 UAC 对话框。更奇葩的是“小黑盒加速器” 可以设置开机自启,每次开机都会弹一个 UAC 对话框要你确认。
动态 UAC 提权
动态 UAC 提权让程序一直运行在普通用户权限下,并且只有需要管理员权限操作时才会弹出 UAC 对话框。这种做法比静态 UAC 提权更加细致。一个普通的应用程序 99% 的功能都不需要管理员权限,只在极少数情况下才需要。比如“QQ音乐”,它只是一个音乐播放软件。用户大部分的时间都仅使用音乐播放功能。而需要管理员权限的“将QQ音乐设为默认应用”功能很少会被使用。所以动态 UAC 提权很有必要。
按照微软官方文档 Developing Applications that Require Administrator Privilege,有四种方法可以实现动态 UAC 提权:
- Elevated Task Model
- Operating System Service Model
- Administrator Broker Model
- Administrator COM Object Model
可以根据具体需要实现的功能选择合适的方法。比如:“添加防火墙规则”这个功能需要使用 INetFwPolicy2。这是一个 COM 接口,可以直接用第 4 种方法“Administrator COM Object Model”实现。使用这种方法有个前提,就是这个 COM 接口必须在注册表里是配置为可以提权的。比如 INetFwPolicy2 接口,先找到 NetFwPolicy2 的 GUID 为 E2B3C97F-6AE1-41AC-817A-F6F92166D7DD,再打开 regedit,输入 HKLM\Software\Classes\CLSID\{E2B3C97F-6AE1-41AC-817A-F6F92166D7DD}\Elevation。Enabled 值为 1 就可以用。对于这种方法,The COM Elevation Moniker 介绍得比较详细,所以直接贴出完整代码:
#include <Windows.h>
#include <netfw.h>
#include <comdef.h>
#include <spdlog/spdlog.h>
#include <memory>
#include <filesystem>
#include <wil/resource.h>
#include <wil/com.h>
#include <iostream>
int add_firewall_rule();
int main()
{
add_firewall_rule();
}
int add_firewall_rule()
{
auto couninitialize_call = wil::CoInitializeEx();
auto pNetFwPolicy2 = wil::CoCreateInstance<INetFwPolicy2>(__uuidof(NetFwPolicy2));
wil::unique_cotaskmem_string clsid;
RETURN_IF_FAILED(StringFromCLSID(__uuidof(NetFwPolicy2), &clsid));
// https://learn.microsoft.com/en-us/windows/win32/secauthz/developing-applications-that-require-administrator-privilege
// https://learn.microsoft.com/en-us/windows/win32/com/the-com-elevation-moniker
BIND_OPTS3 bo{};
bo.cbStruct = sizeof(bo);
bo.hwnd = GetConsoleWindow();
bo.dwClassContext = CLSCTX_LOCAL_SERVER;
auto moniker = fmt::format(L"Elevation:Administrator!new:{}", clsid.get());
spdlog::info(L"moniker: {}", moniker);
auto hr = (CoGetObject(moniker.c_str(), &bo, IID_PPV_ARGS(&pNetFwPolicy2)));
wil::com_ptr<INetFwRules> pNetFwRules;
RETURN_IF_FAILED(pNetFwPolicy2->get_Rules(&pNetFwRules));
long count{};
RETURN_IF_FAILED(pNetFwRules->get_Count(&count));
spdlog::info("rule count: {}", count);
wil::com_ptr<IUnknown> pEnumerator;
pNetFwRules->get__NewEnum(&pEnumerator);
auto pVariant = pEnumerator.query<IEnumVARIANT>();
std::vector<wchar_t> buf(1024);
GetModuleFileNameW(nullptr, buf.data(), (DWORD)buf.size());
std::filesystem::path exe_path(buf.data());
// https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ics/c-enumerating-firewall-rules
while (true) {
wil::unique_variant var;
ULONG cFecthed = 0;
if (pVariant->Next(1, &var, &cFecthed) != S_OK) {
break;
}
wil::com_ptr<INetFwRule> pNetFwRule;
var.pdispVal->QueryInterface(__uuidof(INetFwRule), (void**)&pNetFwRule);
_bstr_t app_name;
pNetFwRule->get_ApplicationName(app_name.GetAddress());
std::error_code ec{};
if (!app_name || !std::filesystem::equivalent(exe_path, (wchar_t*)app_name, ec)) {
continue;
}
pNetFwRule->put_Name(app_name);
pNetFwRules->Remove(app_name);
spdlog::info(L"remove firewall rule: {}", (wchar_t*)app_name);
}
auto pNetFwRule = wil::CoCreateInstance<INetFwRule3>(__uuidof(NetFwRule));
pNetFwRule->put_Enabled(VARIANT_TRUE);
pNetFwRule->put_Action(NET_FW_ACTION_ALLOW);
pNetFwRule->put_ApplicationName(_bstr_t(exe_path.c_str()));
pNetFwRule->put_Profiles(NET_FW_PROFILE2_ALL);
pNetFwRule->put_Name(_bstr_t(L"firewall-test.exe(TCP-In)"));
pNetFwRule->put_Protocol(NET_FW_IP_PROTOCOL_TCP);
RETURN_IF_FAILED(pNetFwRules->Add(pNetFwRule.get()));
pNetFwRule->put_Name(_bstr_t(L"firewall-test.exe(UDP-In)"));
pNetFwRule->put_Protocol(NET_FW_IP_PROTOCOL_UDP);
RETURN_IF_FAILED(pNetFwRules->Add(pNetFwRule.get()));
spdlog::info("success");
return S_OK;
}
关于动态 UAC 提权的代码只有第 30-36 行。需要注意的点有:
- 第 32 行的
bo.hwnd设置 UAC 对话框的 owner。如果代码是控制台程序,应该设置为GetConsoleWindow(),如果是 GUI 程序可以直接填nullptr。 - 第 33 行的
bo.dwClassContext应填CLSCTX_LOCAL_SERVER,而不是CLSCTX_INPROC_SERVER。否则提权失败,CoGetObject仍然返回S_OK。 - UAC 对话框出现在
CoGetObject调用时,而不是执行需要管理员权限的操作(如pNetFwRules->Add)时。 - 每次执行
add_firewall_rule()都会弹出 UAC 对话框。
很多动态 UAC 提权的程序都会在需要管理员权限的操作按钮上显示一个小盾牌图标
,表示点击它会请求管理员权限,比如:

可以直接调用 SHGetStockIconInfo 方法直接得到它的 HICON 句柄。
SHSTOCKICONINFO sii{};
sii.cbSize = sizeof(sii);
HRESULT hr = SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICON | SHGSI_SMALLICON, &sii);
m_buttonRepairFirewall.SetIcon(sii.hIcon);
DestroyIcon(sii.hIcon);
WIN32 动态 UAC 提权的更多相关文章
- metaspolit下UAC提权以及日志清除
在获得webshell时但权限不够大,这时候为了完全获得受害者机器的权限,使用msf进行后渗透. 一.获取Meterpreter会话 Meterpreter 是msf的一个payload,目标执行之后 ...
- windows UAC 提权实验(CVE-2019-1388)
--------------------------------------------------------------------------------- 声明:本文仅做学习,实验主机为虚拟机 ...
- C++ UAC 提权 以一个管理员身份运行程序
这里是我编译的和一个测试Demo:http://pan.baidu.com/s/1qWNgC6C 大家如果看我下边的不是很清楚,可以下载这个具体工程: 群:103197177 C++进阶讨论:欢迎喜欢 ...
- CVE-2019-1388 Windows UAC提权
漏洞简述 该漏洞位于Windows的UAC(User Account Control,用户账户控制)机制中.默认情况下,Windows会在一个单独的桌面上显示所有的UAC提示——Secure Desk ...
- CVE-2019-1388 UAC提权复现
0x01 前言 该漏洞位于Windows的UAC(User Account Control,用户帐户控制)机制中.默认情况下,Windows会在一个单独的桌面上显示所有的UAC提示--Secure D ...
- 【动态UAC权限】无盾程序(win32&cmd)
可以看到两种不同的提权方式,注意是动态,用代码提权,而不是用清单文件提前处理. 函数都写好了,这里不多做解释. win32程序: 首先需要这俩头文件,第二个我忘了啥函数要用了,总之出问题加上就对了:( ...
- CVE-2014-4113本地提权测试
CVE-2014-4113本地提权漏洞分析 By Netfairy 前言 2014年10月14日, Crowdstrike和FireEye发表了一篇文章, 描述了一个新的针对Windows的提权漏洞. ...
- windows提权操作以及系统开机关机重启代码(用到了LookupPrivilegeValue和AdjustTokenPrivileges调整进程的Token权限)
对于UAC提权操作,一般在编译期间,如果程序有需求要提权,会在编译器里设置,vs2010比较简单,在工程属性里可以直接设置,vs2005稍微有点儿麻烦,参考这篇文章: http://www.seany ...
- Cobalt Strike系列教程第七章:提权与横向移动
Cobalt Strike系列教程分享如约而至,新关注的小伙伴可以先回顾一下前面的内容: Cobalt Strike系列教程第一章:简介与安装 Cobalt Strike系列教程第二章:Beacon详 ...
- 内网渗透 day5-msf本地提权(windows)
msf本地提权 目录 1. 利用uac提权 1 2. 绕过uac认证 2 3. 利用windows本地提权漏洞进行提权 4 1. 利用uac提权 前提与目标机建立会话连接 seach local/as ...
随机推荐
- 容器网络Cilium:DualStack双栈特性分析
本文分享自华为云社区<容器网络Cilium入门系列之DualStack双栈特性分析>,作者: 可以交个朋友. 一 . 关于IPV6/IPV4 双栈 目前很多公司开始将自己的业务由ipv4切 ...
- Mybatis-Flex核心功能之@Id
1.是什么? 在 Entity 类中,MyBatis-Flex 是使用 @Id 注解来标识主键的 2.怎么玩? public @interface Id { /** * ID 生成策略,默认为 non ...
- 16级C程序设计竞赛C题
问题 C: 回文 时间限制: 1 Sec 内存限制: 128 MB提交: 74 解决: 36[提交][状态][讨论版] 题目描述 给定一个字符串,你可以对字符串做任意改动,你可以在任意地方增加一个 ...
- Scrapy如何在爬虫类中导入settings配置
假设我们在settings.py定义了一个IP地址池 ##### 自定义设置 IP_PROXY_POOL = ( "127.0.0.1:6789", "127.0.0.1 ...
- python pycurl 安装使用
python pycurl 安装使用 本文主要讲下pycurl 安装使用. 1.安装 首先使用 pip 命令安装. pip install pycurl 输出如下: Collecting pycurl ...
- MyBatisPlus-使用步骤
MyBatisPlus-使用步骤 第一步 引入maven坐标依赖 <dependency> <groupId>com.baomidou</groupId> < ...
- 从零玩转SpringSecurity+JWT整合前后端分离-从零玩转springsecurityjwt整合前后端分离
title: 从零玩转SpringSecurity+JWT整合前后端分离 date: 2021-05-06 14:56:57.699 updated: 2021-12-26 17:43:19.478 ...
- 从零玩转Nginx-从零玩转nginx
title: 从零玩转Nginx date: 2023-05-13 23:08:49.074 updated: 2023-05-13 23:17:26.474 url: https://www.yby ...
- 某RBAC管理系统审计
某RBAC管理系统审计 前言 这个管理系统的审计我去年就开始了但烂尾了,那时候太热闹了log4j2,cs的cve反制等等.这个都给忘了,所以本篇可能有些图有点老,现在就是旧图没一个个换遇到的新的就加上 ...
- 红日靶场5-wp
红日靶场5 环境搭建 win7 账密及域 leo@sun 123.com sun\Administrator dc123.com 双网卡模拟内外网 外网网卡:192.168.130.150 内网网卡: ...