https://github.com/zk2013/windows_remote_lock_unlock_screen
将生成的DLL注册至注册表 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers ,之后的每次锁屏或开机登录都会加载这个DLL。
实现这个DLL有相关的微软文档:
ICredentialProviderCredential 接口
ICredentialProviderCredential2 接口
以上操作只实现了替换解锁Windows的登录界面功能,接下来是实现自动登录(自动解锁)。
实现自动解锁需要有通信机制发送接收Windows账号密码,接收端代码里使用的是 C++的 CreateNamedPipe (命名管道)。
在 ICredentialProviderCredential 接口的现实方法 GetSerialization 内创建了一个 pipe,管道名是 \\.\pipe\NoninteractiveUnlockCredentialProvider,( \\.\管道\管道名。最多可达256个字符的长度,而且不用区分大小写 )。
CPipeListener *pPipeListener = static_cast<CPipeListener *>(lpParameter);
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\NoninteractiveUnlockCredentialProvider");
hPipe = CreateNamedPipe(
lpszPipename,
PIPE_ACCESS_INBOUND,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
BUFSIZE, BUFSIZE,
0,
&sa);
fConnected = ConnectNamedPipe(hPipe, NULL);
fSuccess = FALSE;
cbUsername = 0;
cbPassword = 0;
fSuccess = ReadFile(hPipe, pPipeListener->_pwzUsername, ALLOCSIZE, &cbUsername, NULL);
fSuccess &= ReadFile(hPipe, pPipeListener->_pwzPassword, ALLOCSIZE, &cbPassword, NULL);
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
if (fSuccess && cbUsername && cbUsername)
{
pPipeListener->_fUnlocked = TRUE;
pPipeListener->_pProvider->OnUnlockingStatusChanged();
break;
}
现在实现发送端,使用 C++ 的 CreateFile (这是一个多功能的函数,可打开或创建文件或者I/O设备,并返回可访问的句柄:控制台,通信资源,目录(只读打开),磁盘驱动器,文件,邮槽,管道。)发送账号密码至管道 ( \\.\pipe\NoninteractiveUnlockCredentialProvider ) 。
HANDLE hPipe;
BOOL fSuccess = FALSE;
DWORD cbToWrite, cbWritten;
// Wait pipe
if (!WaitNamedPipe(lpszPipename, 5000))
{
_tprintf(TEXT("Could not open pipe.\n"));
return;
}
// Open pipe
hPipe = CreateFile(
lpszPipename, // pipe name
GENERIC_WRITE, // write access
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
if (hPipe == INVALID_HANDLE_VALUE)
{
_tprintf(TEXT("Could not open pipe. GLE=%d\n"), GetLastError());
return;
}
// Send username
cbToWrite = (lstrlen(lpvUsername) + 1) * sizeof(TCHAR);
fSuccess = WriteFile(
hPipe, // pipe handle
lpvUsername, // message
cbToWrite, // message length
&cbWritten, // bytes written
NULL); // not overlapped
if (!fSuccess)
{
_tprintf(TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError());
CloseHandle(hPipe);
return;
}
// Send password
cbToWrite = (lstrlen(lpvPassword) + 1) * sizeof(TCHAR);
fSuccess = WriteFile(
hPipe, // pipe handle
lpvPassword, // message
cbToWrite, // message length
&cbWritten, // bytes written
NULL); // not overlapped
if (!fSuccess)
{
_tprintf(TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError());
CloseHandle(hPipe);
return;
}
CloseHandle(hPipe);
接收端收到账号密码后,在 GetSerialization 方法内 通过 KerbInteractiveUnlockLogonInit 和 KerbInteractiveUnlockLogonPack 校验登录。正确后触发Windows登录机制并解开屏幕锁。
HRESULT CSampleCredential::GetSerialization(
CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE* pcpgsr,
CREDENTIAL_PROVIDER_CREDENTIAL_