Friday, September 17, 2010

使用LogonUser + CreateProcessAsUser 執行擁有不同Logon SID的程式

這是三個月前的一個瓶頸,在今天終於解決了。

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;
}

2 comments:

  1. 用服务方式启动,并且勾上了type= interact,不是会导致Interactive Service Detection启动麽?

    这边试了一下用user启动notepad.exe,总是被提示有消息然后就切换到一个空的桌面环境下面去了,从博主的图片来看却是在当前的用户桌面中正确显示的,很希望指点一下差异。

    ReplyDelete
  2. 能詳述一下 服务方式启动 的細節嗎

    ReplyDelete