1
2 #include "stdafx.h"
3 #include "boinccas.h"
4 #include "launcher.h"
5
6
7 #ifndef SECURITY_MANDATORY_UNTRUSTED_RID
8
9 #define SECURITY_MANDATORY_UNTRUSTED_RID (0x00000000L)
10 #define SECURITY_MANDATORY_LOW_RID (0x00001000L)
11 #define SECURITY_MANDATORY_MEDIUM_RID (0x00002000L)
12 #define SECURITY_MANDATORY_HIGH_RID (0x00003000L)
13 #define SECURITY_MANDATORY_SYSTEM_RID (0x00004000L)
14 #define SECURITY_MANDATORY_PROTECTED_PROCESS_RID (0x00005000L)
15
16 typedef struct _TOKEN_MANDATORY_LABEL {
17 SID_AND_ATTRIBUTES Label;
18 } TOKEN_MANDATORY_LABEL, *PTOKEN_MANDATORY_LABEL;
19
20 typedef enum _MANDATORY_LEVEL {
21 MandatoryLevelUntrusted = 0,
22 MandatoryLevelLow,
23 MandatoryLevelMedium,
24 MandatoryLevelHigh,
25 MandatoryLevelSystem,
26 MandatoryLevelSecureProcess,
27 MandatoryLevelCount
28 } MANDATORY_LEVEL, *PMANDATORY_LEVEL;
29
30 #define TokenVirtualizationEnabled ((TOKEN_INFORMATION_CLASS)24)
31 #define TokenIntegrityLevel ((TOKEN_INFORMATION_CLASS)25)
32
33 #endif //!SECURITY_MANDATORY_UNTRUSTED_RID
34
35 /*!
36 @brief Function enables/disables/removes a privelege associated with the given token
37 @detailed Calls LookupPrivilegeValue() and AdjustTokenPrivileges()
38 @param[in] hToken - access token handle
39 @param[in] lpszPrivilege - name of privilege to enable/disable
40 @param[in] dwAttributes - (SE_PRIVILEGE_ENABLED) to enable or (0) disable or (SE_PRIVILEGE_REMOVED) to remove privilege
41 @return HRESULT code
42 @todo Removing was checked. To check enabling and disabling.
43 */
SetPrivilege(HANDLE hToken,LPCTSTR lpszPrivilege,DWORD dwAttributes=SE_PRIVILEGE_ENABLED)44 inline HRESULT SetPrivilege(
45 HANDLE hToken,
46 LPCTSTR lpszPrivilege,
47 DWORD dwAttributes=SE_PRIVILEGE_ENABLED
48 )
49 {
50 HRESULT hr=S_OK;
51 LUID luid;
52
53 if ( LookupPrivilegeValue(
54 NULL, // lookup privilege on local system
55 lpszPrivilege, // privilege to lookup
56 &luid ) ) // receives LUID of privilege
57 {
58 TOKEN_PRIVILEGES tp;
59 tp.PrivilegeCount = 1;
60 tp.Privileges[0].Luid = luid;
61 tp.Privileges[0].Attributes = dwAttributes;
62
63 // Enable the privilege or disable all privileges.
64
65 if ( !AdjustTokenPrivileges(
66 hToken,
67 FALSE,
68 &tp,
69 sizeof(TOKEN_PRIVILEGES),
70 (PTOKEN_PRIVILEGES) NULL,
71 (PDWORD) NULL) )
72 hr=HRESULT_FROM_WIN32(GetLastError());
73 }//if(LookupPrivilegeValue(...))
74 else
75 hr=HRESULT_FROM_WIN32(GetLastError());
76
77 return hr;
78 }
79
80 /*!
81 Function removes the priveleges which are not associated by default with explorer.exe at Medium Integration Level in Vista
82 @returns HRESULT of the operation on SE_CREATE_GLOBAL_NAME (="SeCreateGlobalPrivilege")
83 */
ReducePrivilegesForMediumIL(HANDLE hToken)84 inline HRESULT ReducePrivilegesForMediumIL(HANDLE hToken)
85 {
86 HRESULT hr=S_OK;
87 hr=SetPrivilege(hToken, SE_CREATE_GLOBAL_NAME, SE_PRIVILEGE_REMOVED);
88
89 SetPrivilege(hToken, SE_BACKUP_NAME, SE_PRIVILEGE_REMOVED);
90 SetPrivilege(hToken, SE_CREATE_PAGEFILE_NAME, SE_PRIVILEGE_REMOVED);
91 SetPrivilege(hToken, TEXT("SeCreateSymbolicLinkPrivilege"), SE_PRIVILEGE_REMOVED);
92 SetPrivilege(hToken, SE_DEBUG_NAME, SE_PRIVILEGE_REMOVED);
93 SetPrivilege(hToken, SE_IMPERSONATE_NAME, SE_PRIVILEGE_REMOVED);
94 SetPrivilege(hToken, SE_INC_BASE_PRIORITY_NAME, SE_PRIVILEGE_REMOVED);
95 SetPrivilege(hToken, SE_INCREASE_QUOTA_NAME, SE_PRIVILEGE_REMOVED);
96 SetPrivilege(hToken, SE_LOAD_DRIVER_NAME, SE_PRIVILEGE_REMOVED);
97 SetPrivilege(hToken, SE_MANAGE_VOLUME_NAME, SE_PRIVILEGE_REMOVED);
98 SetPrivilege(hToken, SE_PROF_SINGLE_PROCESS_NAME, SE_PRIVILEGE_REMOVED);
99 SetPrivilege(hToken, SE_REMOTE_SHUTDOWN_NAME, SE_PRIVILEGE_REMOVED);
100 SetPrivilege(hToken, SE_RESTORE_NAME, SE_PRIVILEGE_REMOVED);
101 SetPrivilege(hToken, SE_SECURITY_NAME, SE_PRIVILEGE_REMOVED);
102 SetPrivilege(hToken, SE_SYSTEM_ENVIRONMENT_NAME, SE_PRIVILEGE_REMOVED);
103 SetPrivilege(hToken, SE_SYSTEM_PROFILE_NAME, SE_PRIVILEGE_REMOVED);
104 SetPrivilege(hToken, SE_SYSTEMTIME_NAME, SE_PRIVILEGE_REMOVED);
105 SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, SE_PRIVILEGE_REMOVED);
106
107 return hr;
108 }
109
110 /*!
111 @brief Gets Integration level of the given process in Vista.
112 In the older OS assumes the integration level is equal to SECURITY_MANDATORY_HIGH_RID
113
114 The function opens the process for all access and opens its token for all access.
115 Then it extracts token information and closes the handles.
116 @param[in] dwProcessId ID of the process to operate
117 @param[out] pdwProcessIL pointer to write the value
118 @return HRESULT
119 @retval <return value> { description }
120 @remarks Function check for OS version by querying the presence of Kernel32.GetProductInfo function.
121 This way is used due to the function is called from InstallShield12 script, so GetVersionEx returns incorrect value.
122 @todo restrict access rights when quering for tokens
123 */
GetProcessIL(DWORD dwProcessId,LPDWORD pdwProcessIL)124 inline HRESULT GetProcessIL(DWORD dwProcessId, LPDWORD pdwProcessIL)
125 {
126 HRESULT hr=S_OK;
127 if(!pdwProcessIL)
128 hr=E_INVALIDARG;
129 if(SUCCEEDED(hr))
130 {
131 bool bVista=false;
132 {
133 // When the function is called from IS12, GetVersionEx returns dwMajorVersion=5 on Vista!
134 HMODULE hmodKernel32=LoadLibrary(L"Kernel32");
135 if(hmodKernel32 && GetProcAddress(hmodKernel32, "GetProductInfo"))
136 bVista=true;
137 if(hmodKernel32) FreeLibrary(hmodKernel32);
138 }
139
140 DWORD dwIL=SECURITY_MANDATORY_HIGH_RID;
141 if(bVista)
142 {//Vista
143 HANDLE hToken=NULL;
144 HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
145 if(hProcess)
146 {
147 if(OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken))
148 {
149 PTOKEN_MANDATORY_LABEL pTIL=NULL;
150 DWORD dwSize=0;
151 if (!GetTokenInformation(hToken, TokenIntegrityLevel, NULL, 0, &dwSize)
152 && ERROR_INSUFFICIENT_BUFFER==GetLastError() && dwSize)
153 pTIL=(PTOKEN_MANDATORY_LABEL)HeapAlloc(GetProcessHeap(), 0, dwSize);
154
155 if(pTIL && GetTokenInformation(hToken, TokenIntegrityLevel, pTIL, dwSize, &dwSize))
156 {
157 LPBYTE lpb=GetSidSubAuthorityCount(pTIL->Label.Sid);
158 if(lpb)
159 dwIL = *GetSidSubAuthority(pTIL->Label.Sid, *lpb-1);
160 else
161 hr=E_UNEXPECTED;
162 }
163 if(pTIL)
164 HeapFree(GetProcessHeap(), 0, pTIL);
165 CloseHandle(hToken);
166 }//if(OpenProcessToken(...))
167 CloseHandle(hProcess);
168 }//if(hProcess)
169 }//if(bVista)
170 if(SUCCEEDED(hr))
171 *pdwProcessIL=dwIL;
172 }//if(SUCCEEDED(hr))
173 return hr;
174 }
175
176 /*!
177 @brief Function launches process with the integration level of Explorer on Vista. On the previous OS, simply creates the process.
178
179 Function gets the integration level of the current process and Explorer, then launches the new process.
180 If the integration levels are equal, CreateProcess is called.
181 If Explorer has Medium IL, and the current process has High IL, new token is created, its rights are adjusted
182 and CreateProcessWithTokenW is called.
183 If Explorer has Medium IL, and the current process has High IL, error is returned.
184 @param[in] szProcessName - the name of exe file (see CreatePorcess())
185 @param[in] szCmdLine - the name of exe file (see CreatePorcess())
186 @return HRESULT code
187 @note The function cannot be used in services, due to if uses USER32.FindWindow() to get the proper instance of Explorer.
188 The parent of new process in taskmgr.exe, but not the current process.
189 @sa ReducePrivilegesForMediumIL()
190 */
CreateProcessWithExplorerIL(LPWSTR szProcessName,LPWSTR szCmdLine)191 HRESULT CreateProcessWithExplorerIL(LPWSTR szProcessName, LPWSTR szCmdLine)
192 {
193 HRESULT hr = S_OK;
194 BOOL bRet;
195 PROCESS_INFORMATION ProcInfo = {0};
196 STARTUPINFO StartupInfo = {0};
197 bool bVista = false;
198
199 // When the function is called from IS12, GetVersionEx returns dwMajorVersion=5 on Vista!
200 HMODULE hmodKernel32 = LoadLibrary(_T("Kernel32"));
201 if (hmodKernel32) {
202 if (GetProcAddress(hmodKernel32, "GetProductInfo")) {
203 bVista = true;
204 }
205 FreeLibrary(hmodKernel32);
206 }
207
208 if(bVista)
209 {
210 HANDLE hToken;
211 HANDLE hNewToken;
212 DWORD dwCurIL = SECURITY_MANDATORY_HIGH_RID, dwExplorerIL = SECURITY_MANDATORY_HIGH_RID;
213 DWORD dwExplorerID = 0;
214 DWORD dwEnableVirtualization = 0;
215
216 HWND hwndShell = ::FindWindow( _T("Progman"), NULL);
217 if(hwndShell) GetWindowThreadProcessId(hwndShell, &dwExplorerID);
218
219 GetProcessIL(dwExplorerID, &dwExplorerIL);
220 GetProcessIL(GetCurrentProcessId(), &dwCurIL);
221
222 if( (dwCurIL == SECURITY_MANDATORY_HIGH_RID) && (dwExplorerIL == SECURITY_MANDATORY_MEDIUM_RID) )
223 {
224 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwExplorerID);
225 if(hProcess)
226 {
227 if(OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken))
228 {
229 if(!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hNewToken)) {
230 hr = HRESULT_FROM_WIN32(GetLastError());
231 }
232
233 if(SUCCEEDED(hr)) {
234
235 hr = ReducePrivilegesForMediumIL(hNewToken);
236
237 SetTokenInformation(
238 hNewToken,
239 TokenVirtualizationEnabled,
240 &dwEnableVirtualization,
241 sizeof(DWORD)
242 );
243
244 if(SUCCEEDED(hr)) {
245 bRet = CreateProcessAsUser(
246 hNewToken,
247 szProcessName,
248 szCmdLine,
249 NULL,
250 NULL,
251 FALSE,
252 NORMAL_PRIORITY_CLASS,
253 NULL,
254 NULL,
255 &StartupInfo,
256 &ProcInfo
257 );
258 if(!bRet) {
259 hr = HRESULT_FROM_WIN32(GetLastError());
260 }
261 }
262 CloseHandle(hNewToken);
263 } else {
264 hr = HRESULT_FROM_WIN32(GetLastError());
265 }
266 CloseHandle(hToken);
267 } else {
268 hr = HRESULT_FROM_WIN32(GetLastError());
269 }
270 CloseHandle(hProcess);
271 }
272 } else if ((dwCurIL == SECURITY_MANDATORY_MEDIUM_RID) && (dwExplorerIL == SECURITY_MANDATORY_HIGH_RID)) {
273 hr = E_ACCESSDENIED;
274 }
275 }
276
277 if(!ProcInfo.dwProcessId) {
278 bRet = CreateProcess(
279 szProcessName,
280 szCmdLine,
281 NULL,
282 NULL,
283 FALSE,
284 0,
285 NULL,
286 NULL,
287 &StartupInfo,
288 &ProcInfo
289 );
290 if(!bRet) {
291 hr = HRESULT_FROM_WIN32(GetLastError());
292 }
293 }
294
295 return hr;
296 }
297
298
299