CreateProcessAsUser

微軟從XP/2003開始爲我們提供了一套Windows Terminal Service 的相關API,這些API都以WTS開頭(請安裝MSDN2005以查閱相關說明),要獲得活動Session也不止一個途徑,最簡單的就是直接使用  
DWORD WTSGetActiveConsoleSessionId(void);  
來獲得活動Session Id 。要在程序中使用這些API需要最新的Platform SDK(如果你正在使用Visual Studio 2005那麼它已經具備了相關頭文件和庫文件可以直接使用了),如果你在使用VC++ 6.0 你也沒有或者不打算安裝最新的SDK那麼你可以直接使用LoadLibrary() 裝載wtsapi32.dll然後使用GetProcAddress()獲得相關函數的地址以調用它們。我們獲得了活動SessionId後就可以使用  
BOOL WTSQueryUserToken(  
ULONG SessionId,  
PHANDLE phToken  
);  
來獲取當前活動Session中的用戶令牌(Token),有了這個Token我們的就可以在活動Session中創建新進程了,  
BOOL CreateProcessAsUser(  
HANDLE hToken,  
LPCTSTR lpApplicationName,  
LPTSTR lpCommandLine,  
LPSECURITY_ATTRIBUTES lpProcessAttributes,  
LPSECURITY_ATTRIBUTES lpThreadAttributes,  
BOOL bInheritHandles,  
DWORD dwCreationFlags,  
LPVOID lpEnvironment,  
LPCTSTR lpCurrentDirectory,  
LPSTARTUPINFO lpStartupInfo,  
LPPROCESS_INFORMATION lpProcessInformation  
);  
將我們獲得的Token作爲此API的第一個參數即可,你可以先嚐試一下運行一個notepad.exe看看,怎麼樣?你可以在控制檯桌面上看到新進程了。再查看一下進程列表,該進程的用戶名是當前控制檯登錄的用戶。可是這裏我們又遇到一個問題,我們需要收集當前交本機互式登錄用戶的一些信息,而有些操作需要很高的權限才能完成,而Vista下即使是Administraotrs用戶組成員默認也是以Users權限啓動進程的,所以我們創建的新進程只有Users權限,無法完成一些操作,當然我們可以使用Vista所提供的UI來詢問用戶以提升至管理員權限,可有些操作甚至是管理員Token也無法完成的,而且需要用戶確認實在在易用性上大打折扣,所以我決定在活動Session中以SYSTEM權限啓動我們的用戶交互程序。顯然 WTSQueryUserToken() 是不好用了。  
之前,我們提到過進程所屬的Session是由進程Token中的TokenSessionId來決定的,那麼我們是不是可以複製服務進程的Token然後修改其中的TokenSessionId,從而在用戶桌面上創建一個具有SYSTEM權限的新進程呢?答案是肯定的。一下是實現這個操作的代碼,爲了縮小篇幅我刪除了異常處理代碼  
HANDLEhTokenThis = NULL;  
HANDLEhTokenDup = NULL;  
HANDLEhThisProcess = GetCurrentProcess();  
OpenProcessToken(hThisProcess, TOKEN_ALL_ACCESS, &hTokenThis);  
DuplicateTokenEx(hTokenThis, MAXIMUM_ALLOWED,NULL, SecurityIdentification, TokenPrimary, &hTokenDup); 
DWORDdwSessionId = WTSGetActiveConsoleSessionId();  
SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionId, sizeof(DWORD));  

STARTUPINFOsi;  
PROCESS_INFORMATION pi;  
ZeroMemory(&si, sizeof(STARTUPINFO));  
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));  
si.cb = sizeof(STARTUPINFO);  
si.lpDesktop = "WinSta0//Default";  

LPVOIDpEnv = NULL;  
DWORDdwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;  

CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE);  

CreateProcessAsUser(  
  hTokenDup,  
  NULL,  
  (char *)"notepad",  
  NULL,  
  NULL,  
  FALSE,  
  dwCreationFlag,  
  pEnv,  
  NULL,  
  &si,  
  &pi);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章