Windows 小记 5 -- 判断账户是否是管理员账户

devtools/2024/11/17 8:42:43/

判断账户是否位于管理员用户组的方法有:

net localgroup Administrators "账户名" /add

如果返回“操作成功完成”,则表明之前不是管理员账户。那么再调用 /del 删除添加的管理员。

如果返回 “\n发生系统错误 1378。\n指定的帐户名已是此组的成员。\n” 则表明已经位于管理员用户组。

那么怎么通过编程实现更加准确快速的检测呢?

本地账户:

#include <windows.h>
#include <lm.h>
#include <iostream>#pragma comment(lib, "Netapi32.lib")bool IsAccountAdministrator(const std::wstring& userName) {LPLOCALGROUP_USERS_INFO_0 groupInfo = NULL;DWORD entriesRead = 0;DWORD totalEntries = 0;// 使用 NetUserGetLocalGroups 获取本地用户组信息NET_API_STATUS status = NetUserGetLocalGroups(NULL, // 本地计算机userName.c_str(),0,    // 信息级别 0LG_INCLUDE_INDIRECT, // 包含间接组成员关系(LPBYTE*)&groupInfo,MAX_PREFERRED_LENGTH,&entriesRead,&totalEntries);if (status == NERR_Success) {for (DWORD i = 0; i < entriesRead; i++) {// 检查用户是否属于 "Administrators" 组if (_wcsicmp(groupInfo[i].lgrui0_name, L"Administrators") == 0) {NetApiBufferFree(groupInfo);return true; // 用户属于管理员组}}NetApiBufferFree(groupInfo);}else {std::wcerr << L"Failed to get local groups, error code: " << status << std::endl;}return false; // 用户不属于管理员组
}int main() {std::wstring userName = L"XXXXXXXX"; // 替换为要检查的用户名if (IsAccountAdministrator(userName)) {std::wcout << userName << L" is an administrator." << std::endl;}else {std::wcout << userName << L" is not an administrator." << std::endl;}return 0;
}

域用户(针对间接或者嵌套用户组,最佳的获取方式是通过令牌SID,如果用户账户已经登陆,则可以通过进程句柄获取令牌,否则,则需要通过凭据登陆获取令牌)

#include <windows.h>
#include <sddl.h>
#include <iostream>
#include <tchar.h>bool IsSpecifiedUserAdmin(const std::wstring& userName, const std::wstring& domainName, const std::wstring& password) {HANDLE tokenHandle = NULL;DWORD size = 0;PTOKEN_GROUPS tokenGroups = NULL;SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;PSID adminGroup = NULL;bool isAdmin = false;// 尝试使用提供的用户名和密码登录if (!LogonUser(userName.c_str(), domainName.c_str(), password.c_str(),LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &tokenHandle)) {std::wcerr << L"Failed to log on user: " << GetLastError() << std::endl;return false;}// 获取用户令牌中的组信息if (!GetTokenInformation(tokenHandle, TokenGroups, NULL, 0, &size) &&GetLastError() != ERROR_INSUFFICIENT_BUFFER) {std::cerr << "Failed to get token information size." << std::endl;CloseHandle(tokenHandle);return false;}tokenGroups = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);if (tokenGroups == NULL) {std::cerr << "Failed to allocate memory for token groups." << std::endl;CloseHandle(tokenHandle);return false;}if (!GetTokenInformation(tokenHandle, TokenGroups, tokenGroups, size, &size)) {std::cerr << "Failed to get token information." << std::endl;HeapFree(GetProcessHeap(), 0, tokenGroups);CloseHandle(tokenHandle);return false;}// 创建管理员组 SIDif (!AllocateAndInitializeSid(&ntAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &adminGroup)) {std::cerr << "Failed to initialize SID." << std::endl;HeapFree(GetProcessHeap(), 0, tokenGroups);CloseHandle(tokenHandle);return false;}// 检查是否属于管理员组for (DWORD i = 0; i < tokenGroups->GroupCount; i++) {if (EqualSid(adminGroup, tokenGroups->Groups[i].Sid)) {isAdmin = true;break;}}// 清理FreeSid(adminGroup);HeapFree(GetProcessHeap(), 0, tokenGroups);CloseHandle(tokenHandle);return isAdmin;
}int main() {// 替换为要检测的用户名、域和密码std::wstring userName = L"TestUser";std::wstring domainName = L"."; // 本地计算机使用 "."std::wstring password = L"UserPassword";if (IsSpecifiedUserAdmin(userName, domainName, password)) {std::wcout << L"The specified user is an administrator." << std::endl;}else {std::wcout << L"The specified user is not an administrator." << std::endl;}return 0;
}

下面代码未测试域用户等复杂情况。 

添加/删除目标用户到管理员用户组:

#include <windows.h>
#include <lm.h>
#include <iostream>#pragma comment(lib, "Netapi32.lib")bool AddUserToGroup(const std::wstring& userName) {LOCALGROUP_MEMBERS_INFO_3 memberInfo;memberInfo.lgrmi3_domainandname = const_cast<wchar_t*>(userName.c_str());NET_API_STATUS status = NetLocalGroupAddMembers(NULL, L"Administrators", 3, (LPBYTE)&memberInfo, 1);if (status == NERR_Success) {std::wcout << L"User " << userName << L" added to Administrators group." << std::endl;return true;}else {std::wcerr << L"Failed to add user to Administrators group, error code: " << status << std::endl;return false;}
}bool RemoveUserFromGroup(const std::wstring& userName) {LOCALGROUP_MEMBERS_INFO_3 memberInfo;memberInfo.lgrmi3_domainandname = const_cast<wchar_t*>(userName.c_str());NET_API_STATUS status = NetLocalGroupDelMembers(NULL, L"Administrators", 3, (LPBYTE)&memberInfo, 1);if (status == NERR_Success) {std::wcout << L"User " << userName << L" removed from Administrators group." << std::endl;return true;}else {std::wcerr << L"Failed to remove user from Administrators group, error code: " << status << std::endl;return false;}
}int main() {std::wstring userName = L"XXXXX";  // 设置需要操作的用户名// 添加用户到管理员组AddUserToGroup(userName);system("pause");// 从管理员组移除用户RemoveUserFromGroup(userName);return 0;
}

可以通过 net localgroup Administrators 进行验证。

此外需要注意,当账户没有启用时,可能是无法创建和登陆管理员用户的。所以我们也可以查询管理员用户组中用户的状态,使用下面的代码:

#include <windows.h>
#include <lm.h>
#include <iostream>#pragma comment(lib, "Netapi32.lib")void CheckAdministratorsGroup(bool showAllUsers) {LOCALGROUP_MEMBERS_INFO_1* groupMembers = NULL;DWORD entriesRead = 0;DWORD totalEntries = 0;DWORD_PTR resumeHandle = 0;NET_API_STATUS status;// 获取 Administrators 组的成员列表status = NetLocalGroupGetMembers(NULL, // 本地计算机L"Administrators", // 组名1, // 信息级别(LPBYTE*)&groupMembers, // 输出缓冲区MAX_PREFERRED_LENGTH, // 缓冲区大小&entriesRead, // 读取的条目数&totalEntries, // 总条目数&resumeHandle // 分页句柄);if (status != NERR_Success) {std::cerr << "Failed to get group members. Error code: " << status << std::endl;return;}bool hasEnabledUser = false;// 遍历组成员for (DWORD i = 0; i < entriesRead; ++i) {USER_INFO_1* userInfo = NULL;// 获取每个成员的用户信息status = NetUserGetInfo(NULL, groupMembers[i].lgrmi1_name, 1, (LPBYTE*)&userInfo);if (status == NERR_Success) {// 检查用户是否被禁用bool isUserEnabled = !(userInfo->usri1_flags & UF_ACCOUNTDISABLE);if (isUserEnabled) {hasEnabledUser = true;}// 如果开关参数为 true,显示每个用户的状态if (showAllUsers) {std::wcout << L"User: " << groupMembers[i].lgrmi1_name<< L" - Status: " << (isUserEnabled ? L"Enabled" : L"Disabled") << std::endl;}NetApiBufferFree(userInfo);}}NetApiBufferFree(groupMembers);// 如果不显示所有用户,仅报告是否有启用的用户if (!showAllUsers) {if (hasEnabledUser) {std::cout << "The Administrators group has at least one enabled user." << std::endl;}else {std::cout << "No enabled user found in the Administrators group." << std::endl;}}
}int main() {bool showAllUsers = true; // 设置为 true 以显示所有用户及其状态CheckAdministratorsGroup(showAllUsers);return 0;
}

添加或者删除本地用户(出于一些原因,不提供凭据验证过程代码):

#include <windows.h>
#include <lm.h>
#include <iostream>
#include <string>
#include <tchar.h>
#include <strsafe.h>#pragma comment(lib, "Netapi32.lib")
#pragma comment(lib, "Advapi32.lib")// 添加本地用户
bool AddLocalUser(const std::wstring& userName, const std::wstring& password) {USER_INFO_1 userInfo;ZeroMemory(&userInfo, sizeof(userInfo));userInfo.usri1_name = const_cast<wchar_t*>(userName.c_str());userInfo.usri1_password = const_cast<wchar_t*>(password.c_str());userInfo.usri1_priv = USER_PRIV_USER; // 普通用户权限userInfo.usri1_home_dir = NULL;userInfo.usri1_comment = NULL;userInfo.usri1_flags = UF_SCRIPT | UF_DONT_EXPIRE_PASSWD; // 用户必须使用脚本,密码永不过期userInfo.usri1_script_path = NULL;DWORD error = 0;NET_API_STATUS status = NetUserAdd(NULL, 1, (LPBYTE)&userInfo, &error);if (status == NERR_Success) {std::wcout << L"User " << userName << L" added successfully." << std::endl;return true;}else {std::wcerr << L"Failed to add user. Error code: " << status << std::endl;return false;}
}// 删除本地用户
bool DeleteLocalUser(const std::wstring& userName) {NET_API_STATUS status = NetUserDel(NULL, userName.c_str());if (status == NERR_Success) {std::wcout << L"User " << userName << L" deleted successfully." << std::endl;return true;}else {std::wcerr << L"Failed to delete user. Error code: " << status << std::endl;return false;}
}// 验证用户凭据
bool AuthenticateUser() {return true;   // 出于安全考虑,此处代码不提供给大家
}int main() {std::wstring userName;std::wcout << L"Enter the username to add or delete: ";std::getline(std::wcin, userName);// 验证用户凭据std::wcout << L"Please authenticate to proceed." << std::endl;if (!AuthenticateUser()) {std::wcerr << L"Failed to authenticate user." << std::endl;return 1;}std::wcout << L"Do you want to (a)dd or (d)elete the user? (a/d): ";wchar_t action;std::wcin >> action;if (action == L'a' || action == L'A') {std::wstring password;std::wcout << L"Enter the password for the new user: ";std::wcin.ignore(); // 清除输入缓冲区std::getline(std::wcin, password);AddLocalUser(userName, password);}else if (action == L'd' || action == L'D') {DeleteLocalUser(userName);}else {std::wcout << L"Invalid action selected." << std::endl;}return 0;
}

凭据验证模式:

带有凭据验证和询问的安全操作


文章出处链接:[https://blog.csdn.net/qq_59075481/article/details/143821835].


http://www.ppmy.cn/devtools/134665.html

相关文章

【0x001C】HCI_Write_Page_Scan_Activity详解

目录 一、命令概述 二、命令格式和参数说明 2.1. HCI_Write_Page_Scan_Activity命令格式 2.2. Page_Scan_Interval 2.3. Page_Scan_Window 三、响应事件及参数说明 3.1. HCI_Command_Complete事件 3.2. Status 3.3. 示例 四、命令执行流程 4.1. 命令发起阶段(主机端…

基于BERT的命名体识别(NER)

基于BERT的命名实体识别&#xff08;NER&#xff09; 目录 项目背景项目结构环境准备数据准备代码实现 5.1 数据预处理 (src/preprocess.py)5.2 模型训练 (src/train.py)5.3 模型评估 (src/evaluate.py)5.4 模型推理 (src/inference.py) 项目运行 6.1 一键运行脚本 (run.sh)6…

AI写作(十)发展趋势与展望(10/10)

一、AI 写作的崛起之势 在当今科技飞速发展的时代&#xff0c;AI 写作如同一颗耀眼的新星&#xff0c;迅速崛起并在多个领域展现出强大的力量。 随着人工智能技术的不断进步&#xff0c;AI 写作在内容创作领域发挥着越来越重要的作用。据统计&#xff0c;目前已有众多企业开始…

async 和 await的使用

一、需求 点击按钮处理重复提交&#xff0c;想要通过disabled的方式实现。 但是点击按钮调用的方法里有ajax、跳转、弹窗等一系列逻辑操作&#xff0c;需要等方法里流程都走完&#xff0c;再把disabled设为false&#xff0c;这样下次点击按钮时就可以继续走方法里的ajax等操作…

Java读取WPS excel.xlsx嵌入图片

1. 背景&原因 经常有读取Excel文件的需求&#xff0c;开发者大多使用apache poi或者基于此的工具进行excel内容读取&#xff0c;前不久遇到了一个需求&#xff0c;读取每一行内容&#xff0c;但每一行都包含图片文件&#xff0c;发现无法通过已封装的工具读取excel的图片内…

无人机检测车辆——多目标检测

目录 YOLOv3&#xff08;You Only Look Once version 3&#xff09;简介 YOLOv3 的主要特点 YOLOv3 的结构 1. 特征提取网络&#xff08;Backbone&#xff09; 2. 检测头&#xff08;Head&#xff09; 3. 输出层 YOLOv3 损失函数 YOLOv3 的优势 YOLOv3 的应用 YOLOv3…

Scrapy并发请求深度解析:如何高效控制爬虫速度

标题&#xff1a;Scrapy并发请求深度解析&#xff1a;如何高效控制爬虫速度 引言 在Python的Scrapy框架中&#xff0c;合理设置并发请求数量是提高爬虫效率和遵守网站爬取规则的关键。本文将详细解释如何在Scrapy中设置并发请求的数量&#xff0c;并提供代码示例&#xff0c;…

鸿蒙进阶篇-定时器、递归

“在科技的浪潮中&#xff0c;鸿蒙操作系统宛如一颗璀璨的新星&#xff0c;引领着创新的方向。作为鸿蒙开天组&#xff0c;今天我们将一同踏上鸿蒙基础的探索之旅&#xff0c;为您揭开这一神奇系统的神秘面纱。” 各位小伙伴们我们又见面了,我就是鸿蒙开天组,下面让我们进入今…