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

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

net localgroup Administrators "账户名" /add

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

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

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

本地账户:

cpp 复制代码
#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,    // 信息级别 0
        LG_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,如果用户账户已经登陆,则可以通过进程句柄获取令牌,否则,则需要通过凭据登陆获取令牌)

cpp 复制代码
#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;
    }

    // 创建管理员组 SID
    if (!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;
}

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

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

cpp 复制代码
#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 进行验证。

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

cpp 复制代码
#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;
}

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

cpp 复制代码
#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].

相关推荐
蚁景网络安全1 小时前
Cobalt Strike 4.8 用户指南-第十四节 Aggressor 脚本
windows·microsoft
Camllia371 小时前
电脑运行库DirectX出问题怎么办?
windows·经验分享·电脑
总是学不会.2 小时前
【集合】Java 8 - Stream API 17种常用操作与案例详解
java·windows·spring boot·mysql·intellij-idea·java集合
CW_ZB6663 小时前
【无标题】
windows
0xdadream3 小时前
powershell美化
windows
Mr-Apple5 小时前
windows编译googletest框架搭配vscode调试
ide·windows·vscode
慕羽★14 小时前
详细介绍如何使用rapidjson读取json文件
linux·c++·windows·json·file·param·rapidjson
sukalot15 小时前
windows C#-命名实参和可选实参(下)
windows·c#
只抄20 小时前
Windows “高性能”模式既不高效,也不节能?
windows
不坑老师1 天前
不坑盒子2024.1218更新了,模板库上线、一键添加拼音、一键翻译……支持Word、Excel、PPT、WPS
microsoft·word·powerpoint·excel·wps