C++ 在用户上下文中以管理员身份运行用户登录

问题描述 投票:0回答:1

我有一个 C++ 程序,它使用 BitBlt 捕获屏幕并通过网络将其发送到另一台计算机。现在,为了使其正常工作,我的程序需要在用户会话中运行,因为像 BitBlt 或桌面复制 Api 这样的函数会捕获当前会话的屏幕。由于我的程序有一些需要管理员权限的其他功能,我在用户登录时自动启动时遇到了一些问题。这是因为如前所述,它需要在用户会话中运行。

我尝试使用自己编写的 Windows 服务和 CreateProcessAsUser 来运行我的程序,但是如果用户不是管理员,则它不会以这些权限运行。当具有管理员权限的用户登录时,它会按预期工作。我还尝试使用任务计划程序和缓存的凭据;但是,这会导致我的程序在缓存凭据的用户的会话中运行。

windows winapi
1个回答
0
投票

在我发布问题后,我发现了一个旧的论坛帖子,里面有解决方案。 在 32 位和 64 位架构中颠覆 Vista UAC

DWORD GetWinlogonPIDInSession(DWORD dwSessionId) {
    DWORD dwWinlogonPID = 0;
    PWTS_PROCESS_INFO pProcessInfo = NULL;
    DWORD dwProcessCount = 0;

    if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1, 
        &pProcessInfo, &dwProcessCount)) {
        for (DWORD i = 0; i < dwProcessCount; ++i) {
            if (_wcsicmp(pProcessInfo[i].pProcessName, L"winlogon.exe") == 0 && pProcessInfo[i].SessionId == dwSessionId) {
                dwWinlogonPID = pProcessInfo[i].ProcessId;
                break;
            }
        }
        WTSFreeMemory(pProcessInfo);
    }
    else {
        std::cerr << "WTSEnumerateProcesses failed. Error: " << GetLastError() << std::endl;
    }

    return dwWinlogonPID;
}

const wchar_t* exePath = L"Program.exe";
DWORD winlogonPID = GetWinlogonPIDInSession(newSessionId);
if (winlogonPID == 0) {
    return 1;
}

HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, winlogonPID);
if (hProcess == NULL) {
    return 1;
}

// Get access token of winlogon.exe
HANDLE hToken = NULL;
if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, &hToken)) {
    CloseHandle(hProcess);
    return 1;
}

// Duplicate the token to get a primary token
HANDLE hPrimaryToken = NULL;
if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hPrimaryToken)) {
    CloseHandle(hToken);
    CloseHandle(hProcess);
    return 1;
}

// Close handles
CloseHandle(hToken);
CloseHandle(hProcess);

// Start the process in the user's session with elevated privileges
STARTUPINFO si = { sizeof(si) };
si.lpDesktop = L"winsta0\\default"; // Ensure it runs on the interactive desktop
PROCESS_INFORMATION pi;
if (!CreateProcessAsUser(
    hPrimaryToken,  // User token   
    exePath,    // Path to the executable
    NULL,       // Command line
    NULL,       // Process attributes
    NULL,       // Thread attributes
    FALSE,      // Inherit handles
    CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_PROCESS_GROUP | CREATE_BREAKAWAY_FROM_JOB,      // Creation flags
    NULL,       // Environment
    NULL,       // Current directory
    &si,        // Startup info
    &pi         // Process information
)) {
    CloseHandle(hPrimaryToken);
}
else {
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    CloseHandle(hPrimaryToken);
}
© www.soinside.com 2019 - 2024. All rights reserved.