|
5 | 5 | using System.Linq; |
6 | 6 | using System.Runtime.InteropServices; |
7 | 7 | using System.Text; |
| 8 | +using System.Windows.Forms; |
8 | 9 |
|
9 | 10 | namespace DwmLutGUI |
10 | 11 | { |
@@ -35,7 +36,7 @@ static Injector() |
35 | 36 | } |
36 | 37 | catch (Exception) |
37 | 38 | { |
38 | | -#if RELEASE |
| 39 | +#if !DEBUG |
39 | 40 | MessageBox.Show("Failed to enter debug mode – will not be able to apply LUTs."); |
40 | 41 | #endif |
41 | 42 | NoDebug = true; |
@@ -115,8 +116,41 @@ private static void CopyOrConvertLut(string source, string dest) |
115 | 116 | } |
116 | 117 | } |
117 | 118 |
|
| 119 | + private static void ElevatePrivilege() |
| 120 | + { |
| 121 | + var pid = Process.GetProcessesByName("lsass")[0].Id; |
| 122 | + var processHandle = OpenProcess(DesiredAccess.ProcessQueryLimitedInformation, true, (uint)pid); |
| 123 | + var openProcessResult = OpenProcessToken(processHandle, DesiredAccess.MaximumAllowed, out var impersonatedTokenHandle); |
| 124 | + if (!openProcessResult) |
| 125 | + { |
| 126 | + throw new Exception("Failed to open process token"); |
| 127 | + } |
| 128 | + var impersonateResult = ImpersonateLoggedOnUser(impersonatedTokenHandle); |
| 129 | + if (!impersonateResult) |
| 130 | + { |
| 131 | + throw new Exception("Failed to impersonate logged on user"); |
| 132 | + } |
| 133 | + |
| 134 | + // Get username of the current process |
| 135 | + StringBuilder userName = new StringBuilder(1024); |
| 136 | + uint userNameSize = (uint)userName.Capacity; |
| 137 | + var userNameResult = GetUserName(userName, ref userNameSize); |
| 138 | + if (!userNameResult) |
| 139 | + { |
| 140 | + throw new Exception("Failed to get username"); |
| 141 | + } |
| 142 | + |
| 143 | + // Check if the username is SYSTEM |
| 144 | + if (userName.ToString() != "SYSTEM") |
| 145 | + { |
| 146 | + throw new Exception("Not running as SYSTEM"); |
| 147 | + } |
| 148 | + } |
| 149 | + |
118 | 150 | public static void Inject(IEnumerable<MonitorData> monitors) |
119 | 151 | { |
| 152 | + ElevatePrivilege(); |
| 153 | + |
120 | 154 | File.Copy(AppDomain.CurrentDomain.BaseDirectory + DllName, DllPath, true); |
121 | 155 | ClearPermissions(DllPath); |
122 | 156 |
|
@@ -167,10 +201,18 @@ public static void Inject(IEnumerable<MonitorData> monitors) |
167 | 201 | } |
168 | 202 |
|
169 | 203 | Directory.Delete(LutsPath, true); |
| 204 | + |
170 | 205 |
|
171 | | - if (!failed) return; |
| 206 | + if (!failed) |
| 207 | + { |
| 208 | + RevertToSelf(); |
| 209 | + return; |
| 210 | + } |
172 | 211 |
|
173 | 212 | File.Delete(DllPath); |
| 213 | + |
| 214 | + RevertToSelf(); |
| 215 | + |
174 | 216 | throw new Exception( |
175 | 217 | "Failed to load or initialize DLL. This probably means that a LUT file is malformed or that DWM got updated."); |
176 | 218 | } |
@@ -242,6 +284,23 @@ private static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThread |
242 | 284 | [DllImport("kernel32.dll")] |
243 | 285 | private static extern IntPtr CloseHandle(IntPtr hObject); |
244 | 286 |
|
| 287 | + [DllImport("kernel32.dll")] |
| 288 | + private static extern IntPtr OpenProcess(DesiredAccess dwDesiredAccess, bool bInheritHandle, |
| 289 | + uint dwProcessId); |
| 290 | + |
| 291 | + [DllImport("advapi32.dll", SetLastError = true)] |
| 292 | + private static extern bool OpenProcessToken(IntPtr processHandle, DesiredAccess desiredAccess, out IntPtr tokenHandle); |
| 293 | + |
| 294 | + [DllImport("advapi32.dll", SetLastError = true)] |
| 295 | + private static extern bool ImpersonateLoggedOnUser(IntPtr hToken); |
| 296 | + |
| 297 | + [DllImport("advapi32.dll", SetLastError = true)] |
| 298 | + private static extern bool GetUserName(StringBuilder lpBuffer, ref uint nSize); |
| 299 | + |
| 300 | + |
| 301 | + [DllImport("advapi32.dll", SetLastError = true)] |
| 302 | + private static extern bool RevertToSelf(); |
| 303 | + |
245 | 304 | [DllImport("kernel32.dll")] |
246 | 305 | private static extern IntPtr CreateFile(string lpFileName, DesiredAccess dwDesiredAccess, uint dwShareMode, |
247 | 306 | IntPtr lpSecurityAttributes, CreationDisposition dwCreationDisposition, |
@@ -275,7 +334,9 @@ private enum MemoryProtection |
275 | 334 | private enum DesiredAccess |
276 | 335 | { |
277 | 336 | ReadControl = 0x20000, |
278 | | - WriteDac = 0x40000 |
| 337 | + WriteDac = 0x40000, |
| 338 | + ProcessQueryLimitedInformation = 0x1000, |
| 339 | + MaximumAllowed = 0x02000000 |
279 | 340 | } |
280 | 341 |
|
281 | 342 | private enum CreationDisposition |
|
0 commit comments