C++服务 - 模拟用户登录
问题描述:
我已经在我的实验室中的所有计算机上运行了服务,并且需要能够同时登录到所有计算机。C++服务 - 模拟用户登录
所有的计算机都有相同的用户名,所以这不是问题。 但我无法找到以编程方式启动登录的方法。我已阅读有关LogonUser()
及其同行,但他们似乎没有我需要的功能。 有没有人有任何建议,我怎么可以从c + +服务做到这一点?
答
唯一直接支持的方式是使用自动登录功能。主要的缺点是它需要重新启动机器。
下面是我使用(注意,我们的帐户域“SCMS”是硬编码的,所以你需要更改位)代码:
#define _WIN32_WINNT 0x0601
#include <windows.h>
#include <Ntsecapi.h>
#include <stdio.h>
#include <wchar.h>
void setAutologon(void);
void clearAutologon(void);
WCHAR username[128];
WCHAR password[128];
int main(int argc, char ** argv)
{
if (argc == 2 && _stricmp(argv[1], "-clear") == 0)
{
clearAutologon();
return 0;
}
if (argc != 3)
{
printf("Syntax: autologon username password\n");
return 1;
}
swprintf_s(username, _countof(username), L"%hs", argv[1]);
swprintf_s(password, _countof(password), L"%hs", argv[2]);
setAutologon();
return 0;
}
void fail(char * errmsg, DWORD err)
{
// Oops. It didn't work.
printf(errmsg, err);
if (err == 0) err = 1;
exit(err);
}
void storePassword(BOOL store_password)
{
LSA_OBJECT_ATTRIBUTES loa;
LSA_HANDLE lh;
LSA_UNICODE_STRING name;
static const wchar_t name_buffer[] = L"DefaultPassword";
LSA_UNICODE_STRING data;
DWORD dw;
loa.Length = sizeof(loa);
loa.RootDirectory = NULL;
loa.ObjectName = NULL;
loa.Attributes = 0;
loa.SecurityDescriptor = NULL;
loa.SecurityQualityOfService = NULL;
if ((dw = LsaOpenPolicy(NULL, &loa, POLICY_CREATE_SECRET, &lh)) != 0) fail("Error %u opening LSA policy.", LsaNtStatusToWinError(dw));
name.Buffer = (wchar_t *)name_buffer;
name.MaximumLength = name.Length = sizeof(name_buffer) - sizeof(*name_buffer);
if (!store_password)
{
if ((dw = LsaStorePrivateData(lh, &name, NULL)) != 0) fail("Error %u clearing stored password.", LsaNtStatusToWinError(dw));
return;
}
data.Buffer = password;
data.MaximumLength = data.Length = wcslen(password) * sizeof(*password);
if ((dw = LsaStorePrivateData(lh, &name, &data)) != 0) fail("Error %u storing password.", LsaNtStatusToWinError(dw));
LsaClose(lh);
return;
}
void setAutologon()
{
LONG i;
HKEY h;
i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 0, KEY_WOW64_64KEY | KEY_SET_VALUE, &h);
if (i != ERROR_SUCCESS) fail("Unable to open Winlogon subkey (error %u).", i);
i = RegSetValueEx(h, L"DefaultUserName", 0, REG_SZ, (CONST BYTE *)username, (wcslen(username)+1)*2);
if (i != ERROR_SUCCESS) fail("Unable to set default logon user name (error %u).", i);
storePassword(TRUE);
i = RegSetValueEx(h, L"DefaultDomainName", 0, REG_SZ, (CONST BYTE *)L"scms", 10);
if (i != ERROR_SUCCESS) fail("Unable to set default domain name (error %u).", i);
i = RegSetValueEx(h, L"AutoAdminLogon", 0, REG_SZ, (CONST BYTE *)L"1", 2);
if (i != ERROR_SUCCESS) fail("Unable to set automatic logon flag (error %u).", i);
i = RegSetValueEx(h, L"ForceAutoLogon", 0, REG_SZ, (CONST BYTE *)L"1", 2);
if (i != ERROR_SUCCESS) fail("Unable to set forced automatic logon flag (error %u).", i);
}
void clearAutologon(void)
{
LONG i;
HKEY h;
i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 0, KEY_WOW64_64KEY | KEY_SET_VALUE, &h);
if (i != ERROR_SUCCESS) fail("Unable to open Winlogon subkey (error %u).", i);
i = RegSetValueEx(h, L"DefaultUserName", 0, REG_SZ, "", 1);
if (i != ERROR_SUCCESS) fail("Unable to set default logon user name (error %u).", i);
storePassword(FALSE);
// In case the automatic logon was set by the previous version of rpwd or by
// some other means, we clear the registry setting for DefaultPassword as well.
i = RegDeleteValue(h, L"DefaultPassword");
if (i != ERROR_SUCCESS && i != ERROR_FILE_NOT_FOUND) fail("Unable to remove default logon password (error %u).", i);
i = RegDeleteValue(h, L"ForceAutoLogon");
if (i != ERROR_SUCCESS && i != ERROR_FILE_NOT_FOUND) fail("Unable to remove force logon flag (error %u).", i);
i = RegSetValueEx(h, L"AutoAdminLogon", 0, REG_SZ, (CONST BYTE *)"0", 2);
if (i != ERROR_SUCCESS) fail("Unable to clear automatic logon flag (error %u).", i);
}
我用psexec
(可从Microsoft网站)在所有实验室机器上运行代码,然后psshutdown
(同上)重新启动它们。一旦他们开始登录过程,您可以清除自动登录。
毫无疑问,您可以轻松地将相同的方法适用于服务。如果你想避免重启,你需要implement a credential provider。我最后一次看到这个文档令人痛心地稀少,但这可能有所改善。您可能也对pGINA感兴趣,这是一个开源的证书提供者,可能作为一个例子很有用。 (或者,据我所知,可能已经包含了你想要的功能!)
+0
非常感谢,看起来这是我会坚持的方法,直到我可以深入到这些参考:) – Phixle
所以,你的意思是,在计算机用键盘/鼠标/屏幕登录之前坐着的人有同样的效果吗? – deviantfan
@deviantfan是的,没错 – Phixle
为什么你需要这个?服务本身不能可编程地登录到本地工作站上的交互式桌面。 WinLogon屏幕(用户登录的内容)在安全桌面上运行,无法跨会话访问(出于明显的安全原因)。服务可以在需要模拟该用户访问安全对象(文件,注册表,管道等)时登录到用户帐户。 –