mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-12-01 01:29:02 +08:00
use sihost.exe as fallback for run_as_user if no explorer.exe (#8305)
* There is no relevant information, but I found that each session has a unique sihost.exe, and the user name of the process is consistent with the user name of the session, and after using the task manager to kill this process, it will automatically restart. Checking sessionUserName=siHost UserName may be unnecessary, but since there is no evidence, check it anyway. * GetFallbackUserPid is called only when explorer.exe does not exist. * ProcessHacker shows that the tokens of explorer.exe and sihost.exe are the same, I know little about it. Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
parent
f8041a3de5
commit
ec042434be
@ -10,6 +10,9 @@
|
||||
#include <userenv.h>
|
||||
#include <versionhelpers.h>
|
||||
#include <vector>
|
||||
#include <sddl.h>
|
||||
|
||||
extern "C" uint32_t get_session_user_info(PWSTR bufin, uint32_t nin, uint32_t id);
|
||||
|
||||
void flog(char const *fmt, ...)
|
||||
{
|
||||
@ -23,6 +26,95 @@ void flog(char const *fmt, ...)
|
||||
fclose(h);
|
||||
}
|
||||
|
||||
static BOOL GetProcessUserName(DWORD processID, LPWSTR outUserName, DWORD inUserNameSize)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
HANDLE hProcess = NULL;
|
||||
HANDLE hToken = NULL;
|
||||
PTOKEN_USER tokenUser = NULL;
|
||||
wchar_t *userName = NULL;
|
||||
wchar_t *domainName = NULL;
|
||||
|
||||
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, processID);
|
||||
if (hProcess == NULL)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
DWORD tokenInfoLength = 0;
|
||||
GetTokenInformation(hToken, TokenUser, NULL, 0, &tokenInfoLength);
|
||||
if (tokenInfoLength == 0)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
tokenUser = (PTOKEN_USER)malloc(tokenInfoLength);
|
||||
if (tokenUser == NULL)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
if (!GetTokenInformation(hToken, TokenUser, tokenUser, tokenInfoLength, &tokenInfoLength))
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
DWORD userSize = 0;
|
||||
DWORD domainSize = 0;
|
||||
SID_NAME_USE snu;
|
||||
LookupAccountSidW(NULL, tokenUser->User.Sid, NULL, &userSize, NULL, &domainSize, &snu);
|
||||
if (userSize == 0 || domainSize == 0)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
userName = (wchar_t *)malloc((userSize + 1) * sizeof(wchar_t));
|
||||
if (userName == NULL)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
domainName = (wchar_t *)malloc((domainSize + 1) * sizeof(wchar_t));
|
||||
if (domainName == NULL)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
if (!LookupAccountSidW(NULL, tokenUser->User.Sid, userName, &userSize, domainName, &domainSize, &snu))
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
userName[userSize] = L'\0';
|
||||
domainName[domainSize] = L'\0';
|
||||
if (inUserNameSize <= userSize)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
wcscpy(outUserName, userName);
|
||||
|
||||
ret = TRUE;
|
||||
cleanup:
|
||||
if (userName)
|
||||
{
|
||||
free(userName);
|
||||
}
|
||||
if (domainName)
|
||||
{
|
||||
free(domainName);
|
||||
}
|
||||
if (tokenUser != NULL)
|
||||
{
|
||||
free(tokenUser);
|
||||
}
|
||||
if (hToken != NULL)
|
||||
{
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
if (hProcess != NULL)
|
||||
{
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ultravnc has rdp support
|
||||
// https://github.com/veyon/ultravnc/blob/master/winvnc/winvnc/service.cpp
|
||||
// https://github.com/TigerVNC/tigervnc/blob/master/win/winvnc/VNCServerService.cxx
|
||||
@ -54,6 +146,54 @@ DWORD GetLogonPid(DWORD dwSessionId, BOOL as_user)
|
||||
return dwLogonPid;
|
||||
}
|
||||
|
||||
static DWORD GetFallbackUserPid(DWORD dwSessionId)
|
||||
{
|
||||
DWORD dwFallbackPid = 0;
|
||||
const wchar_t* fallbackUserProcs[] = {L"sihost.exe"};
|
||||
const int maxUsernameLen = 256;
|
||||
wchar_t sessionUsername[maxUsernameLen + 1] = {0};
|
||||
wchar_t processUsername[maxUsernameLen + 1] = {0};
|
||||
|
||||
if (get_session_user_info(sessionUsername, maxUsernameLen, dwSessionId) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (hSnap != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
PROCESSENTRY32W procEntry;
|
||||
procEntry.dwSize = sizeof procEntry;
|
||||
|
||||
if (Process32FirstW(hSnap, &procEntry))
|
||||
do
|
||||
{
|
||||
for (int i = 0; i < sizeof(fallbackUserProcs) / sizeof(fallbackUserProcs[0]); i++)
|
||||
{
|
||||
DWORD dwProcessSessionId = 0;
|
||||
if (_wcsicmp(procEntry.szExeFile, fallbackUserProcs[i]) == 0 &&
|
||||
ProcessIdToSessionId(procEntry.th32ProcessID, &dwProcessSessionId) &&
|
||||
dwProcessSessionId == dwSessionId)
|
||||
{
|
||||
memset(processUsername, 0, sizeof(processUsername));
|
||||
if (GetProcessUserName(procEntry.th32ProcessID, processUsername, maxUsernameLen)) {
|
||||
if (_wcsicmp(sessionUsername, processUsername) == 0)
|
||||
{
|
||||
dwFallbackPid = procEntry.th32ProcessID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dwFallbackPid != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (Process32NextW(hSnap, &procEntry));
|
||||
CloseHandle(hSnap);
|
||||
}
|
||||
return dwFallbackPid;
|
||||
}
|
||||
|
||||
// START the app as system
|
||||
extern "C"
|
||||
{
|
||||
@ -63,6 +203,10 @@ extern "C"
|
||||
{
|
||||
BOOL bResult = FALSE;
|
||||
DWORD Id = GetLogonPid(dwSessionId, as_user);
|
||||
if (Id == 0)
|
||||
{
|
||||
Id = GetFallbackUserPid(dwSessionId);
|
||||
}
|
||||
if (pDwTokenPid)
|
||||
*pDwTokenPid = Id;
|
||||
if (HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Id))
|
||||
@ -436,7 +580,7 @@ extern "C"
|
||||
return nout;
|
||||
}
|
||||
|
||||
uint32_t get_session_user_info(PWSTR bufin, uint32_t nin, BOOL rdp, uint32_t id)
|
||||
uint32_t get_session_user_info(PWSTR bufin, uint32_t nin, uint32_t id)
|
||||
{
|
||||
uint32_t nout = 0;
|
||||
PWSTR buf = NULL;
|
||||
|
@ -825,12 +825,12 @@ fn get_current_session_username() -> Option<String> {
|
||||
|
||||
fn get_session_username(session_id: u32) -> String {
|
||||
extern "C" {
|
||||
fn get_session_user_info(path: *mut u16, n: u32, rdp: bool, session_id: u32) -> u32;
|
||||
fn get_session_user_info(path: *mut u16, n: u32, session_id: u32) -> u32;
|
||||
}
|
||||
let buff_size = 256;
|
||||
let mut buff: Vec<u16> = Vec::with_capacity(buff_size);
|
||||
buff.resize(buff_size, 0);
|
||||
let n = unsafe { get_session_user_info(buff.as_mut_ptr(), buff_size as _, true, session_id) };
|
||||
let n = unsafe { get_session_user_info(buff.as_mut_ptr(), buff_size as _, session_id) };
|
||||
if n == 0 {
|
||||
return "".to_owned();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user