1 //
2 // FUNCTION: CreateLowIntegrityProcess(PCWSTR)
3 //
4 // PURPOSE: The function launches an application at low integrity level.
5 //
6 // PARAMETERS:
7 // * pszCommandLine - The command line to be executed. The maximum length
8 // of this string is 32K characters. This parameter cannot be a pointer
9 // to read-only memory (such as a const variable or a literal string).
10 // If this parameter is a constant string, the function may cause an
11 // access violation.
12 //
13 // RETURN VALUE: If the function succeeds, the return value is TRUE. If the
14 // function fails, the return value is zero. To get extended error
15 // information, call GetLastError.
16 //
17 // COMMENT:
18 // To start a low-integrity process,
19 // 1) Duplicate the handle of the current process, which is at medium
20 // integrity level.
21 // 2) Use SetTokenInformation to set the integrity level in the access
22 // token to Low.
23 // 3) Use CreateProcessAsUser to create a new process using the handle to
24 // the low integrity access token.
25 //
26 BOOL CreateLowIntegrityProcess(LPCTSTR pszApplicationName)
27 {
28 DWORD dwError = ERROR_SUCCESS;
29 HANDLE hToken = NULL;
30 HANDLE hNewToken = NULL;
31 SID_IDENTIFIER_AUTHORITY MLAuthority = SECURITY_MANDATORY_LABEL_AUTHORITY;
32 PSID pIntegritySid = NULL;
33 TOKEN_MANDATORY_LABEL tml = { 0 };
34 STARTUPINFO si = { sizeof(si) };
35 PROCESS_INFORMATION pi = { 0 };
36
37 // Open the primary access token of the process.
38 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY |
39 TOKEN_ADJUST_DEFAULT | TOKEN_ASSIGN_PRIMARY, &hToken))
40 {
41 dwError = GetLastError();
42 goto Cleanup;
43 }
44
45 // Duplicate the primary token of the current process.
46 if (!DuplicateTokenEx(hToken, 0, NULL, SecurityImpersonation,
47 TokenPrimary, &hNewToken))
48 {
49 dwError = GetLastError();
50 goto Cleanup;
51 }
52
53 // Create the low integrity SID.
54 if (!AllocateAndInitializeSid(&MLAuthority, 1, SECURITY_MANDATORY_LOW_RID,
55 0, 0, 0, 0, 0, 0, 0, &pIntegritySid))
56 {
57 dwError = GetLastError();
58 goto Cleanup;
59 }
60
61 tml.Label.Attributes = SE_GROUP_INTEGRITY;
62 tml.Label.Sid = pIntegritySid;
63
64 // Set the integrity level in the access token to low.
65 if (!SetTokenInformation(hNewToken, TokenIntegrityLevel, &tml,
66 (sizeof(tml) + GetLengthSid(pIntegritySid))))
67 {
68 dwError = GetLastError();
69 goto Cleanup;
70 }
71
72 // Create the new process at the Low integrity level.
73 if (!CreateProcessAsUser(hNewToken, pszApplicationName, NULL, NULL, NULL,
74 FALSE, 0, NULL, NULL, &si, &pi))
75 {
76 dwError = GetLastError();
77 goto Cleanup;
78 }
79
80 Cleanup:
81 // Centralized cleanup for all allocated resources.
82 if (hToken)
83 {
84 CloseHandle(hToken);
85 hToken = NULL;
86 }
87 if (hNewToken)
88 {
89 CloseHandle(hNewToken);
90 hNewToken = NULL;
91 }
92 if (pIntegritySid)
93 {
94 FreeSid(pIntegritySid);
95 pIntegritySid = NULL;
96 }
97 if (pi.hProcess)
98 {
99 CloseHandle(pi.hProcess);
100 pi.hProcess = NULL;
101 }
102 if (pi.hThread)
103 {
104 CloseHandle(pi.hThread);
105 pi.hThread = NULL;
106 }
107
108 if (ERROR_SUCCESS != dwError)
109 {
110 // Make sure that the error code is set for failure.
111 SetLastError(dwError);
112 return FALSE;
113 }
114 else
115 {
116 return TRUE;
117 }
118 }