gpt4 book ai didi

winapi - SendInput 在 UAC 提示时失败

转载 作者:行者123 更新时间:2023-12-04 01:43:02 24 4
gpt4 key购买 nike

我们正在编写一个只运行的远程桌面应用程序,它使用 SendInput 进行键盘(和鼠标)交互。但是它不能与 UAC 提示交互。

我们的应用为此需要哪些许可/权利?

背景信息:该应用程序是由另一个复制 winlogon.exe 访问 token 的进程生成的。这允许在具有系统完整性级别的 SYSTEM 帐户下运行,附加到物理控制台 session 并具有与 winlogon.exe ( https://learn.microsoft.com/en-us/windows/desktop/secauthz/privilege-constants) 相同的 SE 权限,尽管并非所有这些都已启用。

struct MY_TOKEN_PRIVILEGES {
DWORD PrivilegeCount;
LUID_AND_ATTRIBUTES Privileges[2];
};

int RunUnderWinLogon(LPCWSTR executableWithSendInput)
{
DWORD physicalConsoleSessionId = WTSGetActiveConsoleSessionId();

auto winlogonPid = GetWinLogonPid(); // external function

if (!winlogonPid)
{
std::cout << "ERROR getting winlogon pid" << std::endl;
return 0;
}

HANDLE hWinlogonToken, hProcess;
hProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, winlogonPid);

if (!::OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
| TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID
| TOKEN_READ | TOKEN_WRITE, &hWinlogonToken))
{
printf("Process token open Error: %u\n", GetLastError());
}

// Is security descriptor needed for SendInput?
PSECURITY_DESCRIPTOR pSD = NULL;

SECURITY_ATTRIBUTES saToken;
ZeroMemory(&saToken, sizeof(SECURITY_ATTRIBUTES));

saToken.nLength = sizeof (SECURITY_ATTRIBUTES);
saToken.lpSecurityDescriptor = pSD;
saToken.bInheritHandle = FALSE;

HANDLE hWinlogonTokenDup;
if (!DuplicateTokenEx(hWinlogonToken, TOKEN_ALL_ACCESS, &saToken, SecurityImpersonation, TokenPrimary, &hWinlogonTokenDup))
{
printf("DuplicateTokenEx Error: %u\n", GetLastError());
}

if (!SetTokenInformation(hWinlogonTokenDup, TokenSessionId, (void*)physicalConsoleSessionId, sizeof(DWORD)))
{
printf("SetTokenInformation Error: %u\n", GetLastError());
}

//Adjust Token privilege
LUID luidSeDebugName;
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidSeDebugName))
{
printf("Lookup Privilege value Error: %u\n", GetLastError());
}

LUID luidSeTcbName;
if (!LookupPrivilegeValue(NULL, SE_TCB_NAME, &luidSeTcbName))
{
printf("Lookup Privilege value Error: %u\n", GetLastError());
}

MY_TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 2;
tp.Privileges[0].Luid = luidSeDebugName;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

tp.Privileges[1].Luid = luidSeTcbName;
tp.Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;

if (!AdjustTokenPrivileges(hWinlogonTokenDup, FALSE, (PTOKEN_PRIVILEGES)&tp, /*BufferLength*/0, /*PreviousState*/(PTOKEN_PRIVILEGES)NULL, NULL))
{
printf("Adjust Privilege value Error: %u\n", GetLastError());
}

if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("Token does not have the privilege\n");
}

DWORD creationFlags;
creationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;

LPVOID pEnv = NULL;
if (CreateEnvironmentBlock(&pEnv, hWinlogonTokenDup, TRUE))
{
std::cout << "CreateEnvironmentBlock() success" << std::endl;
creationFlags |= CREATE_UNICODE_ENVIRONMENT;
}

SECURITY_ATTRIBUTES saProcess, saThread;
ZeroMemory(&saProcess, sizeof(SECURITY_ATTRIBUTES));
ZeroMemory(&saThread, sizeof(SECURITY_ATTRIBUTES));

saProcess.nLength = sizeof (SECURITY_ATTRIBUTES);
saProcess.lpSecurityDescriptor = pSD;
saProcess.bInheritHandle = FALSE;

saThread.nLength = sizeof (SECURITY_ATTRIBUTES);
saThread.lpSecurityDescriptor = pSD;
saThread.bInheritHandle = FALSE;

STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = (LPWSTR)L"winsta0\\default";

PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));

BOOL bResult = CreateProcessAsUser(
hWinlogonTokenDup, // client's access token
executableWithSendInput, // file using SendInput
NULL, // command line
&saProcess, // pointer to process SECURITY_ATTRIBUTES
&saThread, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
creationFlags, // creation flags
pEnv, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);
}

最佳答案

SendInput,与 SendMessage 和 PostMessage 一样,仅限于在与目标进程相同的登录 session 和相同桌面内的进程之间工作。 UAC 提示显示在 Winlogon's Secure Desktop 中(winsta0\Winlogon) 所以你需要使用 OpenInputDesktop() 定期轮询当前桌面,然后使用 SetThreadDesktop() 启用当前线程发送消息发送到用户的桌面/安全桌面,以事件的为准。

在 UAC 的情况下,您需要在系统帐户下运行您的进程,以遵守 UIPI Integrity Level check ,正如您已经做过的那样。

See also: How to switch a process between default desktop and Winlogon desktop?

关于winapi - SendInput 在 UAC 提示时失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56595640/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com