检查当前登陆用户是否需要密码的代码:
#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()), // 如果域名为空则传入 NULL
passwordW.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_FAILURE
std::cout << "[+] Password required." << std::endl;
return 1;
}
else if (error == 2) { // ERROR_FILE_NOT_FOUND
std::cout << "[+] Password not required." << std::endl;
return 0;
}
else if (error == 1385) { // ERROR_LOGON_TYPE_NOT_GRANTED
std::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
额外:
【启用/禁用设置中 Windows Hello 登陆选项】
修改以下注册表配置单元:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\default\
Settings\AllowSignInOptions
-
进入 AllowSignInOptions 子键后,检查右侧名为 value 的值。
-
如果存在,双击它并将数值数据设置为
1(启用)/ 0(禁用)
。 -
如果不存在,请通过右键单击右侧面板,选择新建,然后选择 DWORD(32 位)值来创建一个新的 DWORD(32 位)值。
-
将此新值命名为 value 并将其值数据设置为
1(启用)/ 0(禁用)
。 -
注销登陆会话或者重启计算机生效(主要是使得 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 权限才能够访问这些目录和文件。(手动删除是比较危险的,仅当您知晓您正在做什么的情况下完成,并且根据分析,注册表中的一些键值也需要正确清除)
您可以使用两种常用的方式之一,操作此文件夹:
- (方法一)使用 takeown 获取所有权,然后使用 icacls 授予当前用户访问文件夹及其子目录和文件的完全控制权限;
- (方法二)使用 NSudo 等权限提升工具打开具有 TrustedInstaller 特权组并且进程完整性为“系统” 的 cmd.exe 进程,在此命令行中使用 dir 、del、xcopy 等命令操作此目录。
逆向代码(持续更新,目前没有处理错误处理的代码):
此代码等效于 CertUtil.exe ,注意一旦运行将导致 PIN 以及指纹登陆等均被清除(需要注销),且不可逆。下一次登陆将需要用户输入最初设定的登陆密码,所以请谨慎操作!!!
// HelloContainerController.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <Windows.h>
#include <sddl.h>
#include <wincrypt.h>
#include <ncrypt.h>
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "ncrypt.lib")
typedef HRESULT(__fastcall* __NgcDeleteContainerEx)(PSID pSid, INT nNgcKey);
typedef HRESULT(__fastcall* __NgcLocalFindCredential)(PSID pSid, LONG* lpStatus);
typedef HRESULT(__fastcall* __NgcLocalRemoveCredential)(PSID pSid, LONGLONG unKnown);
typedef HRESULT(__fastcall* __NgcEnumUserIdKeys)(LPCWSTR a1, LPCWSTR a2, LPCWSTR a3,
LPWSTR lpSidStr, HLOCAL* a5, LPVOID a6);
typedef HRESULT(__fastcall* __NgcFreeEnumState)(__int64 lpStatus);
__NgcDeleteContainerEx NgcDeleteContainerEx;
__NgcLocalFindCredential NgcLocalFindCredential;
__NgcLocalRemoveCredential NgcLocalRemoveCredential;
__NgcEnumUserIdKeys NgcEnumUserIdKeys;
__NgcFreeEnumState NgcFreeEnumState;
HRESULT myHError(DWORD LastError)
{
DWORD HLastError;
if (LastError >= 1)
{
HLastError = (WORD)LastError | 0x80070000;
if (!(WORD)LastError)
return 0x8000FFFFU;
}
else {
//wprintf(L"S_FALSE == hr, nCode = (0x65F01CAu, 1).\n");
HLastError = LastError;
}
return HLastError;
}
HRESULT myHLastError(void)
{
DWORD LastError = GetLastError();
return myHError(LastError);
}
void* __fastcall myAlloc(size_t _BytesSize, DWORD uFlags)
{
void* _ptr;
switch (uFlags) {
case 1:
_ptr = CoTaskMemAlloc(_BytesSize);
break;
case 2:
_ptr = LocalAlloc(NULL, _BytesSize);
break;
case 4:
_ptr = malloc(_BytesSize);
break;
default:
_ptr = nullptr;
break;
}
if (!_ptr) {
SetLastError(0x8007000EU);
}
return _ptr;
}
void __fastcall myFree(void* Buffer, DWORD uFlags)
{
if (!Buffer)
return;
switch (uFlags)
{
case 1:
CoTaskMemFree(Buffer);
break;
case 2:
LocalFree(Buffer);
break;
case 4:
free(Buffer);
break;
}
}
HRESULT __fastcall myNCFreeObject(NCRYPT_HANDLE hObject)
{
const SECURITY_STATUS status = NCryptFreeObject(hObject);
//CSPrintErrorLineFileData2(0i64, 0xD401C4u, v1, 0);
if (status > 0)
return (WORD)status | 0x80070000U;
return (UINT)status;
}
HRESULT storeGetUserSid(LPWSTR* lpSidStr) {
HRESULT lastError;
PSID* lpSid = nullptr;
SIZE_T uBytes = 0;
LPWSTR stringSid = nullptr;
const BOOL status1 = GetTokenInformation(
(HANDLE)0xFFFFFFFFFFFFFFFA, TokenUser, 0, 0, (PDWORD)&uBytes);
lastError = myHLastError();
if (status1 || lastError == 0x8007007AU || lastError == S_OK)
{
lpSid = (PSID*)LocalAlloc(0, (DWORD)uBytes);
if (!lpSid)
{
lastError = 0x8009000EU;
goto endFunc;
}
const BOOL status2 = GetTokenInformation(
(HANDLE)0xFFFFFFFFFFFFFFFA, TokenUser, lpSid, (DWORD)uBytes, (PDWORD)&uBytes);
lastError = myHLastError();
if (status2 || (lastError == S_OK))
{
const BOOL status3 = ConvertSidToStringSidW(*lpSid, &stringSid);
lastError = myHLastError();
if (status3 || (lastError == S_OK))
{
*lpSidStr = stringSid;
stringSid = nullptr;
lastError = 0;
goto endFunc;
}
lastError = 0x2C430139U;
}
else
{
lastError = 0x2C3D0139U;
}
}
endFunc:
LocalFree(lpSid);
LocalFree(stringSid);
return lastError;
}
HRESULT storeDeleteAllNgcPregenData(void)
{
LSTATUS status_v0; // eax
LSTATUS status_v1; // ebx
status_v0 = RegDeleteTreeW(HKEY_LOCAL_MACHINE, L"AIKCertEnroll");
//CSPrintErrorLineFileData(L"AIKCertEnroll", 0x2BAD0139u, v0);
status_v1 = RegDeleteTreeW(HKEY_LOCAL_MACHINE, L"PregenKeys");
//CSPrintErrorLineFileData(L"PregenKeys", 0x2BB00139u, v1);
if (myHError(status_v0) != S_OK) {
return myHError(status_v0);
}
else {
return myHError(status_v1);
}
}
HRESULT __fastcall myCertNameToStr(
PCERT_NAME_BLOB pName,
DWORD dwStrType,
PWCHAR* ppsz)
{
DWORD csz = NULL;
WCHAR* psz = nullptr;
DWORD cbNeeded;
SECURITY_STATUS status;
while (true)
{
cbNeeded = CertNameToStrW(1u, pName, dwStrType, psz, csz);
csz = cbNeeded;
if (cbNeeded == NULL)
{
status = 0x80070002U;
//CSPrintErrorLineFile(0x75F01CAu, -2147024894);
if (psz)
LocalFree(psz);
return status;
}
if (psz)
{
*ppsz = psz;
return 0;
}
psz = (WCHAR*)LocalAlloc(0, 2 * (static_cast<SIZE_T>(cbNeeded) + 1));
if (!psz)
{
status = 0x8007000EU;
//CSPrintErrorLineFile(0x76B01CAu, -2147024882);
return status;
}
}
}
HRESULT __fastcall myNCOpenKey(
NCRYPT_PROV_HANDLE hProvider,
NCRYPT_KEY_HANDLE* phKey,
LPCWSTR pszKeyName,
DWORD dwFlags)
{
const SECURITY_STATUS status =
NCryptOpenKey(hProvider, phKey, pszKeyName, NULL, dwFlags);
//CSPrintErrorLineFileData2(a3, 0x33901C4u, v6, -2146893811);
if (status > 0)
return (WORD)status | 0x80070000;
return (UINT)status;
}
BOOL __fastcall myCryptExportPublicKeyInfo2(
HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey,
DWORD dwKeySpec, // KeySpec = NULL
PCERT_PUBLIC_KEY_INFO* lpInfo,
DWORD* pcbInfo)
/*
// dwKeySpec --->
// certenrolld_begin -- AT_*
#define AT_KEYEXCHANGE 1
#define AT_SIGNATURE 2
// certenrolld_end
*/
{
BOOL isSuccess;
PCERT_PUBLIC_KEY_INFO keyInfo = nullptr;
LPVOID lpInfoBuffer;
*lpInfo = nullptr;
*pcbInfo = NULL;
while (true)
{
isSuccess = CryptExportPublicKeyInfoEx(hCryptProvOrNCryptKey, dwKeySpec,
1u, nullptr, 0, nullptr, keyInfo, pcbInfo);
if (!isSuccess)
break;
if (!*pcbInfo)
{
SetLastError(0x8007000DU);
isSuccess = FALSE;
break;
}
if (keyInfo) {
*lpInfo = keyInfo;
return isSuccess;
}
lpInfoBuffer = myAlloc(*pcbInfo, 2);
keyInfo = (PCERT_PUBLIC_KEY_INFO)lpInfoBuffer;
if (!lpInfoBuffer) {
*lpInfo = nullptr;
return FALSE;
}
}
if (keyInfo)
{
myFree(keyInfo, 2);
*lpInfo = nullptr;
}
return isSuccess;
}
HRESULT __fastcall storeDeleteCertsByKey(
NCRYPT_PROV_HANDLE hProvider,
LPCWSTR pszKeyName,
HCERTSTORE hCertStore)
{
HRESULT status;
PCCERT_CONTEXT i;
const CERT_CONTEXT* pCertContext = nullptr;
//const unsigned __int16* ResourceString;
const CERT_CONTEXT* pPrevCertContext = nullptr;
WCHAR* lpsz = nullptr;
void* pvFindPara1 = nullptr;
void* pvFindPara2 = nullptr;
HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey;
PCERT_PUBLIC_KEY_INFO lpInfo = nullptr;
hCryptProvOrNCryptKey = 0;
DWORD pcbInfo = 0;
status = myNCOpenKey(hProvider, &hCryptProvOrNCryptKey, pszKeyName, 0x40u);
if (status > 0)
{
//CSPrintErrorLineFileData(a2, 0x2B080139u, v7);
}
else if (myCryptExportPublicKeyInfo2(hCryptProvOrNCryptKey, 0, &lpInfo, &pcbInfo))
{
pvFindPara2 = pvFindPara1;
for (i = CertFindCertificateInStore(hCertStore, 1u, 0,
0x60000u, pvFindPara1, 0);
;
i = CertFindCertificateInStore(hCertStore, 1u, 0,
0x60000u, pvFindPara2, pPrevCertContext))
{
pPrevCertContext = i;
if (!i)
break;
HRESULT result = myCertNameToStr(&i->pCertInfo->Subject,
0x2000003u,(PWCHAR*)&lpsz);
if (result > 0)
//CSPrintErrorLineFile(0x2B290139u, v11);
printf("Error: %lx (0x2B290139)\n", result);
pCertContext = CertDuplicateCertificateContext(pPrevCertContext);
CertDeleteCertificateFromStore(pCertContext);
//ResourceString = myLoadResourceString(0x841u);
//myConsolePrintf(ResourceString, hMem);
LocalFree(lpsz);
lpsz = nullptr;
}
status = 0;
}
else
{
status = myHLastError();
//CSPrintErrorLineFile(0x2B120139u, v8);
pvFindPara2 = pvFindPara1;
}
LocalFree(pvFindPara2);
if (hCryptProvOrNCryptKey)
myNCFreeObject(hCryptProvOrNCryptKey);
return status;
}
HRESULT __fastcall myNCOpenStorageProvider(
NCRYPT_PROV_HANDLE* phProvider, LPCWSTR pszProviderName, DWORD dwFlags)
{
SECURITY_STATUS status;
status = NCryptOpenStorageProvider(phProvider, pszProviderName, dwFlags);
//CSPrintErrorLineFileData2(a2, 0x2DA01C4u, v4, 0);
if (status > 0)
return (WORD)status | 0x80070000;
return (UINT)status;
}
__int64 __fastcall storeDeleteAllNgcCerts(LPWSTR lpSidStr)
{
const WCHAR String = L'\0';
//const WCHAR* v1; // r12
HCERTSTORE v2 = nullptr; // rdi
HCERTSTORE v4 = nullptr; // rsi
unsigned int v5; // eax
//unsigned int v6; // edx
unsigned int v7; // ebx
//const WCHAR* v8; // rcx
unsigned int v9; // eax
//unsigned int v10; // r9d
//__int64 v11; // rbx
//const WCHAR* ResourceString; // rax
int v13; // eax
//unsigned int v14; // r9d
int v15; // eax
HLOCAL hMem = nullptr; // [rsp+68h] [rbp+38h] BYREF
NCRYPT_PROV_HANDLE hProvider = NULL; // [rsp+70h] [rbp+40h] BYREF
__int64 v19; // [rsp+78h] [rbp+48h] BYREF
//v1 = L"MY";
v19 = 0;
v4 = CertOpenStore((LPCSTR)0xD, 1u,
NULL, 0x15200u, L"MY");
if (!v4)
{
v5 = myHLastError();
//v6 = 727318841;
LABEL_3:
v7 = v5;
//v8 = v1;
//LABEL_4:
//CSPrintErrorLineFileData(v8, v6, v5);
//goto LABEL_20;
}
//v1 = L"REQUEST";
v2 = CertOpenStore((LPCSTR)0xD, 1u,
NULL, 0x15200u, L"REQUEST");
if (!v2)
{
v5 = myHLastError();
//v6 = 728105273;
goto LABEL_3;
}
v5 = myNCOpenStorageProvider(&hProvider,
L"Microsoft Passport Key Storage Provider",
0x40u);
v7 = v5;
if (v5)
{
//v6 = 728367417;
//v8 = L"Microsoft Passport Key Storage Provider";
goto LABEL_20;
}
while (1)
{
v9 = NgcEnumUserIdKeys(&String, &String, &String, lpSidStr, &hMem, &v19);
v7 = v9;
if (v9 == -2146893782)
break;
if (v9)
{
//CSPrintErrorLineFile(0x2B7B0139u, v9);
goto LABEL_20;
}
//if (g_fVerbose)
//{
//v11 = *((_QWORD*)hMem + 4);
//ResourceString = myLoadResourceString(0x21Au);
//myConsolePrintf(L"%ws %ws\n", ResourceString, v11);
// }
v13 = storeDeleteCertsByKey(hProvider,
*((const WCHAR**)hMem + 4), v4);
if (v13)
//CSPrintErrorLineFile(0x2B870139u, v13);
;
v15 = storeDeleteCertsByKey(hProvider,
*((const WCHAR**)hMem + 4), v2);
if (v15)
//CSPrintErrorLineFile(0x2B8A0139u, v15);
LocalFree(hMem);
hMem = 0i64;
}
v7 = 0;
LABEL_20:
LocalFree(hMem);
if (v19)
NgcFreeEnumState(v19);
if (hProvider)
myNCFreeObject(hProvider);
if (v4)
CertCloseStore(v4, 0);
if (v2)
CertCloseStore(v2, 0);
return v7;
}
HRESULT __fastcall storeDeleteAllNgcContainerData(PSID* lpSid)
{
UINT status;
LONG lpStatus;
status = NgcLocalFindCredential(lpSid, &lpStatus);
if (!status)
{
if (lpStatus && NgcLocalRemoveCredential)
{
status = NgcLocalRemoveCredential(lpSid, 3);
if (!status)
{
}
}
else
{
status = NgcDeleteContainerEx(lpSid, 1);
if (!status)
{
}
}
}
return status;
}
BOOL InitializeNgcDispacher(void)
{
const HMODULE h_ngclocal = LoadLibraryW(L"ngclocal.dll");
const HMODULE h_cryptngc = LoadLibraryW(L"cryptngc.dll");
if (h_ngclocal)
{
NgcLocalFindCredential = (__NgcLocalFindCredential)
GetProcAddress(h_ngclocal, "NgcLocalFindCredential");
if (!NgcLocalFindCredential)
{
return FALSE;
}
NgcLocalRemoveCredential = (__NgcLocalRemoveCredential)
GetProcAddress(h_ngclocal, "NgcLocalRemoveCredential");
if (!NgcLocalRemoveCredential)
{
return FALSE;
}
}
else
{
return FALSE;
}
if (h_cryptngc)
{
NgcDeleteContainerEx = (__NgcDeleteContainerEx)
GetProcAddress(h_cryptngc, "NgcDeleteContainerEx");
if (!NgcDeleteContainerEx)
{
return FALSE;
}
NgcEnumUserIdKeys = (__NgcEnumUserIdKeys)
GetProcAddress(h_cryptngc, "NgcEnumUserIdKeys");
if (!NgcEnumUserIdKeys)
{
return FALSE;
}
NgcFreeEnumState = (__NgcFreeEnumState)
GetProcAddress(h_cryptngc, "NgcFreeEnumState");
if (!NgcFreeEnumState)
{
return FALSE;
}
}
else
{
return FALSE;
}
return TRUE;
}
HRESULT __fastcall verbDeleteHelloContainer()
{
HRESULT status; // eax
//HRESULT v6; // ecx
int v7; // eax
int v8; // eax
int v9; // ebx
int v10; // eax
//const unsigned __int16* ResourceString; // rax
LPWSTR lpUserSid; // [rsp+20h] [rbp-18h] BYREF
lpUserSid = 0;
status = storeGetUserSid(&lpUserSid);
if (status > 0)
{
//v6 = 0x2C5B0139U;
}
else
{
v7 = storeDeleteAllNgcCerts(lpUserSid);
if (v7)
;//CSPrintErrorLineFile(0x2C600139u, v7);
v8 = storeDeleteAllNgcPregenData();
//if (v8)
//CSPrintErrorLineFile(0x2C650139u, v8);
v9 = RegDeleteTreeW(HKEY_CURRENT_USER,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\WorkplaceJoin\\AADNGC");
//CSPrintErrorLineFileData(L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\WorkplaceJoin\\AADNGC", 0x2BBE0139u, v9);
v10 = myHError(v9);
if (v10)
;//CSPrintErrorLineFile(0x2C6A0139u, v10);
status = storeDeleteAllNgcContainerData((PSID*)lpUserSid);
if (status == 0)
{
//ResourceString = myLoadResourceString(0xC67u);
//myConsolePrintf(L"\n%ws\n", ResourceString);
goto LABEL_13;
}
//v6 = 745472313;
}
//CSPrintErrorLineFile(v6, UserSid);
LABEL_13:
LocalFree(lpUserSid);
return status;
}
int main()
{
/*LPWSTR hMemSid;
if (storeGetUserSid(&hMemSid) != S_OK || !hMemSid)
{
std::wcout << L"错误:获取当前用户 SID 失败。" << std::endl;
}
else
{
wprintf(L"User SID: %s\n", hMemSid);
}
LocalFree(hMemSid);*/
if (!InitializeNgcDispacher())
{
return -1;
}
verbDeleteHelloContainer();
return 0;
}
清除传统密码:
貌似只能 PE 模式或者 DOS 模式下破解?
参考文献:
- 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。