這是三個月前的一個瓶頸,在今天終於解決了。
Windows在User登入後,會建立Logon SID這個群組,加入一些關於程式之間互動的權限(例如PROCESS_TERMINATE),並且所有在登入後所執行的程式都會被強迫加入這個群組,使城市之間可以做一些基本互動。
但是在某些狀況下,我們並不希望該程式能和其他程式互動,所以希望它能不要或是加入不同的Logon SID來隔離。因此透過登入另一個帳戶並執行程式,似乎是個不錯的方法。
一開始使我測試
CreateProcessWithLogonW 來達成這樣的效果,結果發現它雖然會使用另一個帳戶執行程式,但是卻使用當前帳戶的Logon SID,並沒有達成目的。
+
這兩天,我突然想到如果結合
LogonUser + CreateProcessAsUser 或許可以。
在呼叫
CreateProcessAsUser時,必須在LocalSystem帳戶下才有足夠權限(不然會有1314錯誤),所以必須寫一個Service。
在Service中,先呼叫LogonUser取得別的帳戶的Token,接著必須設定Token中的SessionId(
SetTokenInformation) 因為Service中的SessionId預設是0,一般使用者是不可見的,必須設定成當前使用者的SessionId。Window Station "WinSta0"和Desktop "Default"也必須設好權限讓LogonUser所登入的帳戶有權限存取。最後即可透過
CreateProcessAsUser執行新程式,加入的也會是個不同LogonSID。
從下面兩張圖可以看到Test.exe擁有跟其他程式不同的Logon SID
程式碼片段:
void test(){
HANDLE hToken;
DWORD SessionId;
STARTUPINFO sInfo;
PROCESS_INFORMATION pInfo;
printf("%08x\n",LogonUser(L"xxxxx",
L"",
L"xxxxx",
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hToken));
SessionId=1;
printf("%08x\n",SetTokenInformation(hToken,TokenSessionId,&SessionId,sizeof(DWORD)));
memset(&sInfo,0,sizeof(STARTUPINFO));
sInfo.cb=sizeof(STARTUPINFO);
sInfo.lpDesktop=L"WinSta0\\Default";
printf("%08x\n",CreateProcessAsUser(hToken,
L"F:\\Test.exe",
NULL,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&sInfo,
&pInfo));
printf("%08x\n",GetLastError());
return;
}