当前位置: 首页 > news >正文

【Windows】检查当前登陆用户是否需要密码

 检查当前登陆用户是否需要密码的代码:

#define UNICODE
#define SECURITY_WIN32
#include <iostream>
#include <windows.h>
#include <wtsapi32.h>#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "wtsapi32.lib")struct UserInfo {std::wstring userName;std::wstring domainName;
};bool IsRunningAsAdmin() {BOOL isAdmin = FALSE;HANDLE tokenHandle = NULL;// 获取当前进程的访问令牌if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tokenHandle)){TOKEN_ELEVATION elevation{};DWORD cbSize = sizeof(TOKEN_ELEVATION);// 获取令牌中的权限信息,判断是否为管理员权限if (GetTokenInformation(tokenHandle, TokenElevation,&elevation, sizeof(elevation), &cbSize)){isAdmin = elevation.TokenIsElevated;}CloseHandle(tokenHandle);}else {std::cerr << "[-] Unable to obtain process token. Error code: "<< GetLastError() << std::endl;}return isAdmin;
}bool CheckAndStartSeclogonService() {SC_HANDLE scManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (!scManager) {std::cerr << "[-] Error: Failed to open service manager. Error code: "<< GetLastError() << std::endl;return false;}SC_HANDLE seclogonService = OpenService(scManager, L"seclogon",SERVICE_QUERY_STATUS | SERVICE_START);if (!seclogonService) {std::cerr << "[-] Error: Failed to open seclogon service. Error code: "<< GetLastError() << std::endl;CloseServiceHandle(scManager);return false;}SERVICE_STATUS_PROCESS serviceStatus{};DWORD bytesNeeded;if (QueryServiceStatusEx(seclogonService, SC_STATUS_PROCESS_INFO, (LPBYTE)&serviceStatus, sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded)){if (serviceStatus.dwCurrentState != SERVICE_RUNNING) {if (!StartService(seclogonService, 0, NULL)) {std::cerr << "[-] Error: Failed to start seclogon service. Error code: "<< GetLastError() << std::endl;CloseServiceHandle(seclogonService);CloseServiceHandle(scManager);return false;}else {std::cout << "[+] Seclogon service started successfully." << std::endl;}}else {std::cout << "[+] Seclogon service is already running." << std::endl;}}else {std::cerr << "[-] Error: Failed to query seclogon service status. Error code: "<< GetLastError() << std::endl;CloseServiceHandle(seclogonService);CloseServiceHandle(scManager);return false;}CloseServiceHandle(seclogonService);CloseServiceHandle(scManager);return true;
}// 获取当前活动会话的用户名和域名
UserInfo GetActiveUserNameAndDomain() {PWTS_SESSION_INFO pSessionInfo = NULL;DWORD sessionCount = 0;UserInfo activeUserInfo;// 枚举所有会话if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &sessionCount)){for (DWORD i = 0; i < sessionCount; ++i) {// 查找当前活动的会话if (pSessionInfo[i].State == WTSActive) {DWORD sessionId = pSessionInfo[i].SessionId;LPTSTR pUserName = NULL;LPTSTR pDomainName = NULL;DWORD bytesReturned = 0;// 从活动会话获取用户名if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, &pUserName, &bytesReturned) && bytesReturned > 0){activeUserInfo.userName = pUserName;}// 从活动会话获取域名if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSDomainName, &pDomainName, &bytesReturned) && bytesReturned > 0){activeUserInfo.domainName = pDomainName;}// 释放获取到的内存if (pUserName) {WTSFreeMemory(pUserName);}if (pDomainName) {WTSFreeMemory(pDomainName);}break; // 找到活动用户后,退出循环}}WTSFreeMemory(pSessionInfo);}else {std::cerr << "[-] Unable to enumerate sessions, error code: "<< GetLastError() << std::endl;}return activeUserInfo;
}const INT GetAccountPasswordRequirement(const std::wstring& specialArg, const bool IsRunStricted = true
)
{bool isCheckSrvFailed = false;std::wstring passwordW = L"";  // 空密码// 自动解析当前用户名和域名UserInfo activeUser = GetActiveUserNameAndDomain();if (!activeUser.userName.empty()) {// 打印域名和用户名std::wcout << L"[+] Domain: " << activeUser.domainName << std::endl;std::wcout << L"[+] Username: " << activeUser.userName << std::endl;}else {std::wcout << L"[-] No active users were found." << std::endl;return -1;}// 检查并启动 seclogon 服务if (IsRunStricted && !CheckAndStartSeclogonService()) {std::cerr << "[-] Error: Unable to ensure seclogon service is running." << std::endl;isCheckSrvFailed = true;}// 获取当前进程的可执行文件路径WCHAR modulePath[4096];wmemset(modulePath, 0, 4096);GetModuleFileNameW(NULL, modulePath, 4095);// 构造命令行,包括自身路径和特殊参数std::wstring commandLine = L"\"";commandLine += modulePath;commandLine += L"\" ";commandLine += specialArg;  // 添加特殊参数// 创建进程信息结构体PROCESS_INFORMATION processInfo;ZeroMemory(&processInfo, sizeof(processInfo));// 创建启动信息结构体STARTUPINFOW startupInfo;ZeroMemory(&startupInfo, sizeof(startupInfo));startupInfo.cb = sizeof(startupInfo);startupInfo.wShowWindow = SW_HIDE;// 使用 CreateProcessWithLogonW 尝试创建进程BOOL result = CreateProcessWithLogonW(activeUser.userName.c_str(),   // 用户名(activeUser.domainName.empty() ? NULL: activeUser.domainName.c_str()),  // 如果域名为空则传入 NULLpasswordW.c_str(),   // 密码为空LOGON_WITH_PROFILE,  // 登录类型NULL,                // 不需要具体应用程序(LPWSTR)commandLine.c_str(), // 启动参数CREATE_NO_WINDOW,  // 创建新控制台NULL,                // 环境块NULL,                // 当前目录&startupInfo,        // 启动信息&processInfo         // 进程信息);// 检查返回结果if (!result) {DWORD error = GetLastError();if (error == 1326) { // ERROR_LOGON_FAILUREstd::cout << "[+] Password required." << std::endl;return 1;}else if (error == 2) { // ERROR_FILE_NOT_FOUNDstd::cout << "[+] Password not required." << std::endl;return 0;}else if (error == 1385) { // ERROR_LOGON_TYPE_NOT_GRANTEDstd::cerr << "[-] Error 1385: Logon failure, " << "user doesn't have required logon type." << std::endl;return 0;}else if ((!IsRunStricted || isCheckSrvFailed) && error == 5) {std::cerr << "[-] Error 5: Unable to access service controller, "<< "Seclogon service may not start properly." << std::endl;return -1;}else {std::cerr << "[-] Error: " << error << std::endl;return -1;}}// 成功创建进程,关闭句柄CloseHandle(processInfo.hProcess);CloseHandle(processInfo.hThread);return 0; // 无需密码
}int wmain(int argc, wchar_t* argv[]) {// 检查是否有传递的参数if (argc > 1) {std::wstring arg = argv[1];if (arg == L"--terminate") {std::wcout << L"[+] Special argument detected: " << arg << std::endl;std::wcout << L"Process will terminate immediately." << std::endl;return 0;  // 立即退出}}const bool IsRunStricted = IsRunningAsAdmin();if (IsRunStricted) {std::cout << "[+] The current process is running as an administrator." << std::endl;}else {std::cout << "[-] The current process is not running as an administrator." << std::endl;}const INT requireCode = GetAccountPasswordRequirement(L"--terminate", IsRunStricted);if (requireCode == 1) {std::cout << "[*] The current user requires a password. " << std::endl;return 1;}else if(requireCode == 0) {std::cout << "[*] The current user does not require a password. " << std::endl;return 0;}else {std::cout << "[*] Unknown Type. " << std::endl;return requireCode;}
}

支持两种模式:

  • (管理员身份启动):严格检查 Seclogon 服务是否启动;
  • (普通模式):测试程序是否能够以管理员身份启动自身,以此来判断是否需要密码。

返回值:

  • 0   —— 无密码
  • 1   —— 有密码
  • -1 或其他值  —— 未知状态,可能由异常导致

效果截图:

标题

等同于命令:

runas /u:your_domain\a_test_user your_application_name

鸣谢:

@Wormwaker(https://blog.csdn.net/cjz2005)

额外:

【启用/禁用设置中 Windows Hello 登陆选项】

修改以下注册表配置单元:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\default\

Settings\AllowSignInOptions

  1. 进入 AllowSignInOptions 子键后,检查右侧名为 value 的值。

  2. 如果存在,双击它并将数值数据设置为 1(启用)/ 0(禁用)

  3. 如果不存在,请通过右键单击右侧面板,选择新建,然后选择 DWORD(32 位)值来创建一个新的 DWORD(32 位)值。

  4. 将此新值命名为 value 并将值数据设置为 1(启用)/ 0(禁用)

  5. 注销登陆会话或者重启计算机生效(主要是使得 smss 和 winlogon 等登陆验证程序更新其内存中的配置)

禁用后设置灰显,无法再操作

【删除 Windows Hello 登陆容器 -- 清除 PIN 密钥】

注意:此操作不需要权限提升,但需要用户注销后才能生效。清除的是当前用户 SID 下的 PIN 密钥。

命令行参数(C:\Windows\System32\CertUtil.exe):

CertUtil -DeleteHelloContainer

删除成功提示

如果已经删除或者不存在容器存根,则会提示:

找不到存根

另一个非官方的方式是通过手动删除存根文件夹及其目录文件。

Windows Hello 登陆容器的本地存储:

C:\Windows\ServiceProfiles\LocalService\AppData\Local\Microsoft\Ngc

此目录下子文件夹名称即用户账户的 SID,文件夹里面包括了多个 dat 文件。

注意:用户需要 TrustedInstaller 权限才能够访问这些目录和文件。(手动删除是比较危险的,仅当您知晓您正在做什么的情况下完成,并且根据分析,注册表中的一些键值也需要正确清除)

您可以使用两种常用的方式之一,操作此文件夹:

  1. (方法一)使用 takeown 获取所有权,然后使用 icacls 授予当前用户访问文件夹及其子目录和文件的完全控制权限;
  2. (方法二)使用 NSudo 等权限提升工具打开具有 TrustedInstaller 特权组并且进程完整性为“系统” 的 cmd.exe 进程,在此命令行中使用 dir 、del、xcopy 等命令操作此目录。

参考文献:

  • https://serverfault.com/questions/67706/tool-to-test-a-user-account-and-password-test-login
  • https://learn.microsoft.com/zh-cn/windows/win32/api/winbase/nf-winbase-createprocesswithlogonw

文章出处链接:https://blog.csdn.net/qq_59075481/article/details/143081306。


http://www.mrgr.cn/news/54011.html

相关文章:

  • 将本地文件上传到GIT上
  • [近源攻击]badusb制作
  • 解锁文本数据可视化的无限可能:Wordcloud库全解析
  • 项目管理APP推荐_功能对比与用户评价
  • springboot038基于SpringBoot的网上租赁系统设计与实现(论文+源码)_kaic
  • 算法之二分查找法
  • 计算机网络基本架构实例1
  • Spring篇(事务篇 - 基础介绍)
  • 【Java】Java 的反射机制(二):类的加载(拓展)
  • 从多线程到 epoll:如何优雅地处理高并发请求?
  • python 爬虫 入门 三、登录以及代理。
  • 练习题 - Scrapy爬虫框架 Items 数据项
  • Mysql安装与卸载
  • C++虚函数的默认参数是静态绑定还是动态绑定
  • CTFHUB技能树之XSS——DOM反射
  • 从零开始学PHP之helloworld
  • 练习题 - Scrapy爬虫框架 Spider Middleware 爬虫页中间件
  • scrapy案例——链家租房数据的爬取
  • 外部存储器与内部存储器有哪些主要区别
  • [项目详解][boost搜索引擎#1] 概述 | 去标签 | 数据清洗 | scp