我如何获取 Windows AutoLogon 密码?

我如何获取 Windows AutoLogon 密码?

我有一台配置好的电脑自动登录。Windows
重新启动后,它会自动使用预定义的用户登录。

我也想通过远程桌面连接到这台计算机。但是我需要这个特定用户的密码。

我已经知道可以在注册表中配置 AutoLogon:
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
AutoAdminLogon(REG_SZ) = 1
DefaultDomainName(REG_SZ) = MyDomain(或为空)
DefaultUserName(REG_SZ) = MyUser
DefaultPassword(REG_SZ) = MyPass
但在我的例子中没有输入DefaultPassword。尽管缺少密码,AutoLogon 仍然有效。并且密码不是空字符串。

我如何找回密码?

答案1

解决方案:LsaRetrievePrivateData

Windows 可以以隐藏的方式存储键值对,当系统启用自动登录时,密码将存储在 DefaultPassword 字段中。要检索它,请使用以下方式:

  • LsaOpenPolicy(NULL, &attribs, POLICY_ALL_ACCESS, &lsa_handle)打开一个LSA_HANDLE对象
  • 您创建一个LSA_UNICODE_STRING结构并让它指向wchar_t包含的数据缓冲区DefaultPassword
  • 然后调用LsaRetrievePrivateData(lsa_handle, &key, &ptr_value),将字符串结构作为键传递给它。
  • 返回的指针(ptr_value)保存一个新的 Unicode 字符串数据结构,其中应包含解密的密码,如果不存在则不包含。

必须在管理员权限下进行调用,否则访问将被拒绝。

起源:https://www.opengate.at/blog/2021/11/win32-stored-password/

下面是在我的情况下可以运行并显示密码所需的 C 代码:

#include <string>
#include <exception>
#include <wchar.h>
#include <iostream>
#include <sstream>
#include <stdexcept>

#include "windows.h"
#include "Ntsecapi.h"

typedef std::string string_t;
typedef std::wstring wstring_t;

struct LsaHandle
{
private:
    LsaHandle(const LsaHandle&);
    LsaHandle& operator=(const LsaHandle&);
    LSA_HANDLE handle;

public:
    LsaHandle(LSA_HANDLE h = LSA_HANDLE()) 
        : handle(h) 
    {
    }
    
    ~LsaHandle()
    { 
        if(this->handle)
        {
            LsaClose(this->handle);
        }
    }

    LSA_HANDLE& operator*() 
    { 
        return this->handle; 
    }
};

wstring_t getSecretPwd()
{
    LsaHandle hPolicy;
    LSA_OBJECT_ATTRIBUTES attribs;
    ZeroMemory(&attribs, sizeof(attribs));
    NTSTATUS dwStatus = LsaOpenPolicy(NULL, &attribs, POLICY_ALL_ACCESS, &*hPolicy);
    DWORD dwError = LsaNtStatusToWinError(dwStatus);
    if(dwError != 0)
    {
        DWORD dwError = ::GetLastError();
        std::stringstream ss;
        ss << "Failed to open storage, error-code = " << dwError;
        throw std::runtime_error(ss.str());
    }

    WCHAR wstrKeyName[] = L"DefaultPassword";
    LSA_UNICODE_STRING keyName;
    keyName.Buffer = wstrKeyName;
    keyName.Length = static_cast<USHORT>(wcslen(wstrKeyName) * sizeof(wstrKeyName[0]));
    keyName.MaximumLength = static_cast<USHORT>((wcslen(wstrKeyName) + 1) * sizeof(wstrKeyName[0]));

    PLSA_UNICODE_STRING privateData = NULL;

    dwStatus = LsaRetrievePrivateData(*hPolicy, &keyName, &privateData);
    if(dwStatus != 0)
    {
        dwError = LsaNtStatusToWinError(dwStatus);
        std::stringstream ss;
        ss << "Failed to retrieve data, error-code = " << dwError;
        throw std::runtime_error(ss.str());
    }
    wstring_t secret_pwd(privateData->Buffer, privateData->Length / sizeof(privateData->Buffer[0]));
    LsaFreeMemory(privateData);
    return secret_pwd;
}


struct KeyHandle
{
private:
    HKEY    handle;
    KeyHandle(const KeyHandle&);
    KeyHandle& operator=(const KeyHandle&);
public:
    KeyHandle(HKEY h = HKEY()) 
        : handle(h) 
    {
    }
    ~KeyHandle()
    { 
        if(this->handle)
        {
            RegCloseKey(this->handle);
        }
    }
    HKEY& operator*() 
    { 
        return this->handle;
    }
};

wstring_t getRegistryPwd()
{
    wchar_t strPass[2048];
    DWORD dwType;
    DWORD dwSize = sizeof(strPass);

    KeyHandle hKey;
    LONG result = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
                                L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
                                0,
                                KEY_QUERY_VALUE,
                                &*hKey);

    if(ERROR_SUCCESS != result)
    {
        throw std::exception("Failed to open storage");
    }

    result = RegQueryValueExW(*hKey, L"DefaultPassword", 0, &dwType, (LPBYTE)strPass, &dwSize);
    switch(result)
    {
    case ERROR_SUCCESS:
        {
            if(dwType != REG_SZ) 
                return wstring_t();
            else
                return wstring_t(strPass, dwSize / 2);
            break;
        }
    case ERROR_FILE_NOT_FOUND:  
    case ERROR_PATH_NOT_FOUND:
        {
            return wstring_t();
        }
    default:
        {
            throw std::exception("Failed to retrieve data");
        }
    }

}

void showPassword(wstring_t(*pwdfunc)(), char const* pwdname)
{
    wstring_t pwd;
    try
    {
        pwd = pwdfunc();
        if(!pwd.empty())
        {
            std::cout << "[" << pwdname << " = ";
            std::wcout << pwd;
            std::cout << "]" << std::endl;
        }
        else
        {
            std::cout << "No " << pwdname << std::endl;
        }
    }
    catch(std::exception& ex)
    {
        std::cout << "[" << pwdname << "] Exception: " << ex.what() << std::endl;

    }
    catch(...)
    {
        std::cout << "[" << pwdname << "] Unknown exception" << std::endl;
    }
}


int main()
{
    showPassword(&getSecretPwd, "Secret Password");
    showPassword(&getRegistryPwd, "Default Password");

    return 0;
}

答案2

有一些产品可以检索 Windows AutoLogon 密码,但您可能需要暂时禁用 Defender 的实时保护,以免它将其检测为病毒。

以下列出几个:

Nirsoft 网络密码恢复

在此处输入图片描述

解密自动登录程序

在此处输入图片描述

从这两款产品来看,我更信赖Nirsoft。

相关内容