CLI tool for running Playbooks
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

937 lines
39 KiB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Management;
  8. using System.Management.Automation;
  9. using System.Net.Http;
  10. using System.Reflection;
  11. using System.Runtime.InteropServices;
  12. using System.Security.Principal;
  13. using System.ServiceProcess;
  14. using System.Text.RegularExpressions;
  15. using System.Threading;
  16. using System.Threading.Tasks;
  17. using System.Windows;
  18. using System.Windows.Interop;
  19. using Microsoft.Win32;
  20. using TrustedUninstaller.Shared.Actions;
  21. namespace TrustedUninstaller.Shared
  22. {
  23. using SLID = Guid; //SLID id declared as typedef GUID SLID; in slpublic.h
  24. public static class WinUtil
  25. {
  26. public enum SHSTOCKICONID : uint
  27. {
  28. SIID_DOCNOASSOC = 0,
  29. SIID_DOCASSOC = 1,
  30. SIID_APPLICATION = 2,
  31. SIID_FOLDER = 3,
  32. SIID_FOLDEROPEN = 4,
  33. SIID_DRIVE525 = 5,
  34. SIID_DRIVE35 = 6,
  35. SIID_DRIVEREMOVE = 7,
  36. SIID_DRIVEFIXED = 8,
  37. SIID_DRIVENET = 9,
  38. SIID_DRIVENETDISABLED = 10,
  39. SIID_DRIVECD = 11,
  40. SIID_DRIVERAM = 12,
  41. SIID_WORLD = 13,
  42. SIID_SERVER = 15,
  43. SIID_PRINTER = 16,
  44. SIID_MYNETWORK = 17,
  45. SIID_FIND = 22,
  46. SIID_HELP = 23,
  47. SIID_SHARE = 28,
  48. SIID_LINK = 29,
  49. SIID_SLOWFILE = 30,
  50. SIID_RECYCLER = 31,
  51. SIID_RECYCLERFULL = 32,
  52. SIID_MEDIACDAUDIO = 40,
  53. SIID_LOCK = 47,
  54. SIID_AUTOLIST = 49,
  55. SIID_PRINTERNET = 50,
  56. SIID_SERVERSHARE = 51,
  57. SIID_PRINTERFAX = 52,
  58. SIID_PRINTERFAXNET = 53,
  59. SIID_PRINTERFILE = 54,
  60. SIID_STACK = 55,
  61. SIID_MEDIASVCD = 56,
  62. SIID_STUFFEDFOLDER = 57,
  63. SIID_DRIVEUNKNOWN = 58,
  64. SIID_DRIVEDVD = 59,
  65. SIID_MEDIADVD = 60,
  66. SIID_MEDIADVDRAM = 61,
  67. SIID_MEDIADVDRW = 62,
  68. SIID_MEDIADVDR = 63,
  69. SIID_MEDIADVDROM = 64,
  70. SIID_MEDIACDAUDIOPLUS = 65,
  71. SIID_MEDIACDRW = 66,
  72. SIID_MEDIACDR = 67,
  73. SIID_MEDIACDBURN = 68,
  74. SIID_MEDIABLANKCD = 69,
  75. SIID_MEDIACDROM = 70,
  76. SIID_AUDIOFILES = 71,
  77. SIID_IMAGEFILES = 72,
  78. SIID_VIDEOFILES = 73,
  79. SIID_MIXEDFILES = 74,
  80. SIID_FOLDERBACK = 75,
  81. SIID_FOLDERFRONT = 76,
  82. SIID_SHIELD = 77,
  83. SIID_WARNING = 78,
  84. SIID_INFO = 79,
  85. SIID_ERROR = 80,
  86. SIID_KEY = 81,
  87. SIID_SOFTWARE = 82,
  88. SIID_RENAME = 83,
  89. SIID_DELETE = 84,
  90. SIID_MEDIAAUDIODVD = 85,
  91. SIID_MEDIAMOVIEDVD = 86,
  92. SIID_MEDIAENHANCEDCD = 87,
  93. SIID_MEDIAENHANCEDDVD = 88,
  94. SIID_MEDIAHDDVD = 89,
  95. SIID_MEDIABLURAY = 90,
  96. SIID_MEDIAVCD = 91,
  97. SIID_MEDIADVDPLUSR = 92,
  98. SIID_MEDIADVDPLUSRW = 93,
  99. SIID_DESKTOPPC = 94,
  100. SIID_MOBILEPC = 95,
  101. SIID_USERS = 96,
  102. SIID_MEDIASMARTMEDIA = 97,
  103. SIID_MEDIACOMPACTFLASH = 98,
  104. SIID_DEVICECELLPHONE = 99,
  105. SIID_DEVICECAMERA = 100,
  106. SIID_DEVICEVIDEOCAMERA = 101,
  107. SIID_DEVICEAUDIOPLAYER = 102,
  108. SIID_NETWORKCONNECT = 103,
  109. SIID_INTERNET = 104,
  110. SIID_ZIPFILE = 105,
  111. SIID_SETTINGS = 106,
  112. SIID_DRIVEHDDVD = 132,
  113. SIID_DRIVEBD = 133,
  114. SIID_MEDIAHDDVDROM = 134,
  115. SIID_MEDIAHDDVDR = 135,
  116. SIID_MEDIAHDDVDRAM = 136,
  117. SIID_MEDIABDROM = 137,
  118. SIID_MEDIABDR = 138,
  119. SIID_MEDIABDRE = 139,
  120. SIID_CLUSTEREDDRIVE = 140,
  121. SIID_MAX_ICONS = 175
  122. }
  123. [Flags]
  124. public enum SHGSI : uint
  125. {
  126. SHGSI_ICONLOCATION = 0,
  127. SHGSI_ICON = 0x000000100,
  128. SHGSI_SYSICONINDEX = 0x000004000,
  129. SHGSI_LINKOVERLAY = 0x000008000,
  130. SHGSI_SELECTED = 0x000010000,
  131. SHGSI_LARGEICON = 0x000000000,
  132. SHGSI_SMALLICON = 0x000000001,
  133. SHGSI_SHELLICONSIZE = 0x000000004
  134. }
  135. [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
  136. public struct SHSTOCKICONINFO
  137. {
  138. public UInt32 cbSize;
  139. public IntPtr hIcon;
  140. public Int32 iSysIconIndex;
  141. public Int32 iIcon;
  142. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260 /*MAX_PATH*/)]
  143. public string szPath;
  144. }
  145. [DllImport("Shell32.dll", SetLastError = false)]
  146. public static extern Int32 SHGetStockIconInfo(SHSTOCKICONID siid, SHGSI uFlags, ref SHSTOCKICONINFO psii);
  147. [DllImport("user32.dll", SetLastError = true)]
  148. public static extern bool DestroyIcon(IntPtr hIcon);
  149. public static bool IsAdministrator()
  150. {
  151. using var identity = WindowsIdentity.GetCurrent();
  152. var principal = new WindowsPrincipal(identity);
  153. return principal.IsInRole(WindowsBuiltInRole.Administrator);
  154. }
  155. public static string GetUserName()
  156. {
  157. var wi = WindowsIdentity.GetCurrent();
  158. var groups = from g in wi.Groups
  159. select new SecurityIdentifier(g.Value)
  160. .Translate(typeof(NTAccount)).Value;
  161. var msAccount = (from g in groups
  162. where g.StartsWith(@"MicrosoftAccount\")
  163. select g).FirstOrDefault();
  164. return msAccount == null ? Environment.UserName : msAccount.Substring(@"MicrosoftAccount\".Length);
  165. }
  166. public static bool IsLocalAccount()
  167. {
  168. var wi = WindowsIdentity.GetCurrent();
  169. var groups = from g in wi.Groups
  170. select new SecurityIdentifier(g.Value)
  171. .Translate(typeof(NTAccount)).Value;
  172. var msAccount = (from g in groups
  173. where g.StartsWith(@"MicrosoftAccount\")
  174. select g).FirstOrDefault();
  175. return msAccount == null;
  176. }
  177. public enum SL_GENUINE_STATE
  178. {
  179. SL_GEN_STATE_IS_GENUINE = 0,
  180. // SL_GEN_STATE_INVALID_LICENSE = 1,
  181. // SL_GEN_STATE_TAMPERED = 2,
  182. SL_GEN_STATE_LAST = 3
  183. }
  184. [DllImport("Slwga.dll", EntryPoint = "SLIsGenuineLocal", CharSet = CharSet.None, ExactSpelling =
  185. false, SetLastError = false, PreserveSig = true, CallingConvention = CallingConvention.Winapi, BestFitMapping =
  186. false, ThrowOnUnmappableChar = false)]
  187. [PreserveSigAttribute()]
  188. internal static extern uint SLIsGenuineLocal(ref SLID slid, [In, Out] ref SL_GENUINE_STATE genuineState, IntPtr val3);
  189. public static bool IsGenuineWindows()
  190. {
  191. // Microsoft-Windows-Security-SPP GUID
  192. // http://technet.microsoft.com/en-us/library/dd772270.aspx
  193. var windowsSlid = new SLID("55c92734-d682-4d71-983e-d6ec3f16059f");
  194. var genuineState = SL_GENUINE_STATE.SL_GEN_STATE_LAST;
  195. var resultInt = SLIsGenuineLocal(ref windowsSlid, ref genuineState, IntPtr.Zero);
  196. #if DEBUG
  197. return true;
  198. #else
  199. return resultInt == 0 && genuineState == SL_GENUINE_STATE.SL_GEN_STATE_IS_GENUINE;
  200. #endif
  201. }
  202. private static IEnumerable<string> GetWindowsGroups(WindowsIdentity id)
  203. {
  204. var irc = id.Groups ?? new IdentityReferenceCollection();
  205. return irc.Select(ir => (NTAccount)ir.Translate(typeof(NTAccount))).Select(acc => acc.Value).ToList();
  206. }
  207. public static bool HasWindowsGroup(string groupName)
  208. {
  209. var appDomain = Thread.GetDomain();
  210. appDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
  211. var currentPrincipal = (WindowsPrincipal)Thread.CurrentPrincipal;
  212. var groups = GetWindowsGroups((WindowsIdentity)currentPrincipal.Identity);
  213. return groups.Any(group => group == groupName);
  214. }
  215. public static bool IsTrustedInstaller()
  216. {
  217. return HasWindowsGroup(@"NT SERVICE\TrustedInstaller");
  218. }
  219. public static bool RelaunchAsTrustedInstaller()
  220. {
  221. var controller = new ServiceController("TrustedInstaller");
  222. if (controller.Status != ServiceControllerStatus.Running)
  223. {
  224. controller.Start();
  225. controller.WaitForStatus(ServiceControllerStatus.Running);
  226. }
  227. var targetProcess = Process.GetProcessesByName("TrustedInstaller").FirstOrDefault();
  228. if (targetProcess == null)
  229. {
  230. return false;
  231. }
  232. var currentProcess = Process.GetCurrentProcess();
  233. var currentModule = currentProcess.MainModule;
  234. if (currentModule == null)
  235. {
  236. return false;
  237. }
  238. var currentExecutable = currentModule.FileName;
  239. return NativeProcess.StartProcess(currentExecutable, targetProcess.Id, AmeliorationUtil.Playbook.Path);
  240. }
  241. [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
  242. public static extern Boolean ChangeServiceConfig(
  243. IntPtr hService,
  244. UInt32 nServiceType,
  245. UInt32 nStartType,
  246. UInt32 nErrorControl,
  247. String lpBinaryPathName,
  248. String lpLoadOrderGroup,
  249. IntPtr lpdwTagId,
  250. [In] char[] lpDependencies,
  251. String lpServiceStartName,
  252. String lpPassword,
  253. String lpDisplayName);
  254. [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  255. static extern IntPtr OpenService(
  256. IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
  257. [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode,
  258. SetLastError = true)]
  259. public static extern IntPtr OpenSCManager(
  260. string machineName, string databaseName, uint dwAccess);
  261. [DllImport("advapi32.dll", EntryPoint = "CloseServiceHandle")]
  262. public static extern int CloseServiceHandle(IntPtr hSCObject);
  263. private const uint SERVICE_NO_CHANGE = 0xFFFFFFFF;
  264. private const uint SERVICE_QUERY_CONFIG = 0x00000001;
  265. private const uint SERVICE_CHANGE_CONFIG = 0x00000002;
  266. private const uint SC_MANAGER_ALL_ACCESS = 0x000F003F;
  267. public static void ChangeStartMode(ServiceController svc, ServiceStartMode mode)
  268. {
  269. var scManagerHandle = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS);
  270. if (scManagerHandle == IntPtr.Zero)
  271. {
  272. throw new ExternalException("Open Service Manager Error");
  273. }
  274. var serviceHandle = OpenService(
  275. scManagerHandle,
  276. svc.ServiceName,
  277. SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG);
  278. if (serviceHandle == IntPtr.Zero)
  279. {
  280. throw new ExternalException("Open Service Error");
  281. }
  282. var result = ChangeServiceConfig(
  283. serviceHandle,
  284. SERVICE_NO_CHANGE,
  285. (uint)mode,
  286. SERVICE_NO_CHANGE,
  287. null,
  288. null,
  289. IntPtr.Zero,
  290. null,
  291. null,
  292. null,
  293. null);
  294. if (result == false)
  295. {
  296. var nError = Marshal.GetLastWin32Error();
  297. var win32Exception = new Win32Exception(nError);
  298. throw new ExternalException("Could not change service start type: "
  299. + win32Exception.Message);
  300. }
  301. CloseServiceHandle(serviceHandle);
  302. CloseServiceHandle(scManagerHandle);
  303. }
  304. [StructLayout(LayoutKind.Sequential)]
  305. struct RM_UNIQUE_PROCESS
  306. {
  307. public int dwProcessId;
  308. public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime;
  309. }
  310. const int RmRebootReasonNone = 0;
  311. const int CCH_RM_MAX_APP_NAME = 255;
  312. const int CCH_RM_MAX_SVC_NAME = 63;
  313. enum RM_APP_TYPE
  314. {
  315. RmUnknownApp = 0,
  316. RmMainWindow = 1,
  317. RmOtherWindow = 2,
  318. RmService = 3,
  319. RmExplorer = 4,
  320. RmConsole = 5,
  321. RmCritical = 1000
  322. }
  323. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
  324. struct RM_PROCESS_INFO
  325. {
  326. public RM_UNIQUE_PROCESS Process;
  327. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_APP_NAME + 1)]
  328. public string strAppName;
  329. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)]
  330. public string strServiceShortName;
  331. public RM_APP_TYPE ApplicationType;
  332. public uint AppStatus;
  333. public uint TSSessionId;
  334. [MarshalAs(UnmanagedType.Bool)] public bool bRestartable;
  335. }
  336. [DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
  337. static extern int RmRegisterResources(uint pSessionHandle,
  338. UInt32 nFiles,
  339. string[] rgsFilenames,
  340. UInt32 nApplications,
  341. [In] RM_UNIQUE_PROCESS[] rgApplications,
  342. UInt32 nServices,
  343. string[] rgsServiceNames);
  344. [DllImport("rstrtmgr.dll", CharSet = CharSet.Auto)]
  345. static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, string strSessionKey);
  346. [DllImport("rstrtmgr.dll")]
  347. static extern int RmEndSession(uint pSessionHandle);
  348. [DllImport("rstrtmgr.dll")]
  349. static extern int RmGetList(uint dwSessionHandle,
  350. out uint pnProcInfoNeeded,
  351. ref uint pnProcInfo,
  352. [In, Out] RM_PROCESS_INFO[] rgAffectedApps,
  353. ref uint lpdwRebootReasons);
  354. /// <summary>
  355. /// Find out what process(es) have a lock on the specified file.
  356. /// </summary>
  357. /// <param name="path">Path of the file.</param>
  358. /// <returns>Processes locking the file</returns>
  359. /// <remarks>See also:
  360. /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa373661(v=vs.85).aspx
  361. /// http://wyupdate.googlecode.com/svn-history/r401/trunk/frmFilesInUse.cs (no copyright in code at time of viewing)
  362. ///
  363. /// </remarks>
  364. public static List<Process> WhoIsLocking(string path)
  365. {
  366. string key = Guid.NewGuid().ToString();
  367. List<Process> processes = new List<Process>();
  368. int res = RmStartSession(out uint handle, 0, key);
  369. if (res != 0)
  370. {
  371. ErrorLogger.WriteToErrorLog("Could not begin restart session. Unable to determine file locker.",
  372. Environment.StackTrace, $"Error while attempting to get locking processes of file {path}");
  373. throw new Exception("Could not begin restart session. Unable to determine file locker.");
  374. }
  375. try
  376. {
  377. const int ERROR_MORE_DATA = 234;
  378. uint pnProcInfoNeeded = 0,
  379. pnProcInfo = 0,
  380. lpdwRebootReasons = RmRebootReasonNone;
  381. string[] resources = new string[] { path }; // Just checking on one resource.
  382. res = RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null);
  383. if (res != 0) throw new Exception("Could not register resource.");
  384. //Note: there's a race condition here -- the first call to RmGetList() returns
  385. // the total number of process. However, when we call RmGetList() again to get
  386. // the actual processes this number may have increased.
  387. res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons);
  388. if (res == ERROR_MORE_DATA)
  389. {
  390. // Create an array to store the process results
  391. RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded];
  392. pnProcInfo = pnProcInfoNeeded;
  393. // Get the list
  394. res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons);
  395. if (res == 0)
  396. {
  397. processes = new List<Process>((int)pnProcInfo);
  398. // Enumerate all of the results and add them to the
  399. // list to be returned
  400. for (int i = 0; i < pnProcInfo; i++)
  401. {
  402. try
  403. {
  404. processes.Add(Process.GetProcessById(processInfo[i].Process.dwProcessId));
  405. }
  406. // catch the error -- in case the process is no longer running
  407. catch (ArgumentException) { }
  408. }
  409. }
  410. else throw new Exception("Could not list processes locking resource.");
  411. }
  412. else if (res != 0)
  413. throw new Exception("Could not list processes locking resource. Could not get size of result." + $" Result value: {res}");
  414. }
  415. finally
  416. {
  417. RmEndSession(handle);
  418. }
  419. return processes;
  420. }
  421. /// <summary>
  422. /// Finds active anti-viruses in the system.
  423. /// </summary>
  424. /// <returns>a list of ProviderStatus.</returns>
  425. /// <remarks>See also:
  426. /// https://jdhitsolutions.com/blog/powershell/5187/get-antivirus-product-status-with-powershell/
  427. /// https://docs.microsoft.com/en-us/windows/win32/api/iwscapi/ne-iwscapi-wsc_security_product_state?redirectedfrom=MSDN
  428. /// https://mspscripts.com/get-installed-antivirus-information-2/
  429. /// https://social.msdn.microsoft.com/Forums/pt-BR/6501b87e-dda4-4838-93c3-244daa355d7c/wmisecuritycenter2-productstate?forum=vblanguage
  430. /// https://stackoverflow.com/questions/4700897/wmi-security-center-productstate-clarification/4711211
  431. /// https://blogs.msdn.microsoft.com/alejacma/2008/05/12/how-to-get-antivirus-information-with-wmi-vbscript/#comment-442
  432. /// https://www.magnumdb.com/search?q=parent:WSC_SECURITY_PRODUCT_STATE
  433. /// https://web.archive.org/web/20190121133247/http://neophob.com/2010/03/wmi-query-windows-securitycenter2/
  434. /// </remarks>
  435. public static List<ProviderStatus> GetEnabledAvList(bool ensureWMI = true)
  436. {
  437. if (ensureWMI)
  438. {
  439. var svc = new ServiceController("Winmgmt");
  440. ChangeStartMode(svc, ServiceStartMode.Automatic);
  441. }
  442. List<ProviderStatus> avList = new List<ProviderStatus>();
  443. string computer = Environment.MachineName;
  444. string wmipath = @"\\" + computer + @"\root\SecurityCenter2";
  445. string query = @"SELECT * FROM AntivirusProduct WHERE displayName != ""Windows Defender""";
  446. try
  447. {
  448. using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmipath, query))
  449. {
  450. ManagementObjectCollection results = searcher.Get();
  451. foreach (var o in results)
  452. {
  453. // You can find if an AV is active or not by accessing the hex code of the productState
  454. // (from the right) 19th bit == Anti Virus is on
  455. // (from the right) 13th bit == On Access Scanning
  456. // 00000000 00000[1]10 000[1]0000 000[0]0000
  457. // 19th bit (yes) = Av on
  458. // 13th bit (yes) = On Access Scanning
  459. // The third byte defines if the .dat file is up-to-date
  460. var result = (ManagementObject)o;
  461. var productState = result["productState"];
  462. string hex = Hex(Convert.ToInt32(productState));
  463. string bin = Binary(Convert.ToInt32(productState));
  464. string reversed = Reverse(bin);
  465. var enabled = GetBit(reversed, 18);
  466. var scanning = GetBit(reversed, 12);
  467. var outdated = GetBit(reversed, 4);
  468. static string Binary(int value)
  469. {
  470. return Convert.ToString(value, 2).PadLeft(24, '0');
  471. }
  472. static string Hex(int value)
  473. {
  474. return Convert.ToString(value, 16).PadLeft(6, '0');
  475. }
  476. static bool GetBit(string value, int index)
  477. {
  478. return value.Substring(index, 1).Equals("1");
  479. }
  480. static string Reverse(string value)
  481. {
  482. return new string(value.Reverse().ToArray());
  483. }
  484. if (!enabled) continue;
  485. var av = new ProviderStatus()
  486. {
  487. DisplayName = result["displayName"].ToString(),
  488. AVStatus = enabled ? AVStatusFlags.Enabled : AVStatusFlags.Unknown,
  489. SecurityProvider = ProviderFlags.ANTIVIRUS,
  490. SignatureStatus = outdated ? SignatureStatusFlags.OutOfDate : SignatureStatusFlags.UpToDate
  491. };
  492. avList.Add(av);
  493. }
  494. }
  495. }
  496. catch (Exception e)
  497. {
  498. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "Error while retrieving the AV list.");
  499. }
  500. return avList;
  501. }
  502. //Checks if Visual C++ redistributable is installed.
  503. public static bool IsVCInstalled()
  504. {
  505. string dependenciesPath = @"SOFTWARE\Classes\Installer\Dependencies";
  506. using (RegistryKey dependencies = Registry.LocalMachine.OpenSubKey(dependenciesPath))
  507. {
  508. if (dependencies == null) return false;
  509. foreach (string subKeyName in dependencies.GetSubKeyNames().Where(n => !n.ToLower().Contains("dotnet") && !n.ToLower().Contains("microsoft")))
  510. {
  511. using (RegistryKey subDir = Registry.LocalMachine.OpenSubKey(dependenciesPath + "\\" + subKeyName))
  512. {
  513. var value = subDir.GetValue("DisplayName")?.ToString() ?? null;
  514. if (string.IsNullOrEmpty(value))
  515. {
  516. continue;
  517. }
  518. if (Environment.Is64BitOperatingSystem)
  519. {
  520. if (Regex.IsMatch(value, @"C\+\+ 2015.*\((x64|x86)\)"))
  521. {
  522. return true;
  523. }
  524. }
  525. else
  526. {
  527. if (Regex.IsMatch(value, @"C\+\+ 2015.*\(x86\)"))
  528. {
  529. return true;
  530. }
  531. }
  532. }
  533. }
  534. }
  535. return false;
  536. }
  537. public static async Task RemoveProtectionAsync()
  538. {
  539. var cmdAction = new CmdAction();
  540. if (!IsVCInstalled())
  541. {
  542. Console.WriteLine(Environment.NewLine + "Installing VC 15...");
  543. try
  544. {
  545. //Install Visual C++ 2015 redistributable package silently
  546. cmdAction.Command = "vc_redist.x64.exe /q /norestart";
  547. await cmdAction.RunTask();
  548. }
  549. catch (Exception e)
  550. {
  551. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "Error while installing VC 15.");
  552. throw;
  553. }
  554. }
  555. try
  556. {
  557. Console.WriteLine(Environment.NewLine + "Installing driver...");
  558. cmdAction.Command = Environment.Is64BitOperatingSystem
  559. ? $"ProcessHacker\\x64\\ProcessHacker.exe -s -installkph"
  560. : $"ProcessHacker\\x86\\ProcessHacker.exe -s -installkph";
  561. var res = await cmdAction.RunTask();
  562. }
  563. catch (Exception e)
  564. {
  565. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "ProcessHacker ran into an error while installing its driver.");
  566. throw;
  567. }
  568. }
  569. private const int GWL_STYLE = -16;
  570. private const int WS_SYSMENU = 0x80000;
  571. [DllImport("user32.dll", SetLastError = true)]
  572. private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
  573. [DllImport("user32.dll")]
  574. private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
  575. //public static void RemoveCloseButton(Window window)
  576. //{
  577. //var hwnd = new WindowInteropHelper(window).Handle;
  578. //SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);
  579. //}
  580. public static bool IsVM()
  581. {
  582. try
  583. {
  584. using (var searcher = new System.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem"))
  585. {
  586. using (var items = searcher.Get())
  587. {
  588. foreach (var item in items)
  589. {
  590. string manufacturer = item["Manufacturer"].ToString().ToLower();
  591. if ((manufacturer == "microsoft corporation" && item["Model"].ToString().ToUpperInvariant().Contains("VIRTUAL"))
  592. || manufacturer.Contains("vmware")
  593. || item["Model"].ToString() == "VirtualBox")
  594. {
  595. return true;
  596. }
  597. }
  598. }
  599. }
  600. return false;
  601. }
  602. catch (Exception e)
  603. {
  604. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "Error while checking if running system is a VM.");
  605. return false;
  606. }
  607. }
  608. public static void PrepareSystemCLI()
  609. {
  610. try
  611. {
  612. var defenderStop = new RunAction()
  613. {
  614. RawPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
  615. Exe = $"NSudoLC.exe",
  616. Arguments = "-U:T -P:E -M:S -ShowWindowMode:Hide -Priority:RealTime -Wait cmd /c \"" +
  617. "sc sdset \"WinDefend\" \"D:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)(A;;CCLCSWRPLOCRRC;;;BA)(A;;CCLCSWRPLOCRRC;;;BU)(A;;CCLCSWRPLOCRRC;;;IU)(A;;CCLCSWRPLOCRRC;;;SU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-80-1913148863-3492339771-4165695881-2087618961-4109116736)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)\"&" +
  618. "sc config WinDefend start=disabled&" +
  619. "net stop WinDefend\"",
  620. CreateWindow = false,
  621. Timeout = 7500,
  622. };
  623. defenderStop.RunTask().Wait();
  624. } catch (Exception e)
  625. {
  626. }
  627. var defenderValues = new RunAction()
  628. {
  629. RawPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
  630. Exe = $"NSudoLC.exe",
  631. Arguments = "-U:T -P:E -M:S -ShowWindowMode:Hide -Priority:RealTime -Wait cmd /c \"reg delete \"HKLM\\SOFTWARE\\Microsoft\\Windows Defender\" /v \"ProductAppDataPath\" /f &" +
  632. " reg delete \"HKLM\\SOFTWARE\\Microsoft\\Windows Defender\" /v \"InstallLocation\" /f\"",
  633. CreateWindow = false
  634. };
  635. defenderValues.RunTask().Wait();
  636. var defenderKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows Defender");
  637. if (defenderKey != null && defenderKey.GetValueNames().Contains("InstallLocation"))
  638. {
  639. throw new Exception("Could not remove defender install values.");
  640. }
  641. var defenderService = new RunAction()
  642. {
  643. RawPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
  644. Exe = $"NSudoLC.exe",
  645. Arguments = "-U:T -P:E -M:S -ShowWindowMode:Hide -Priority:RealTime -Wait reg delete \"HKLM\\SYSTEM\\CurrentControlSet\\Services\\WinDefend\" /f",
  646. CreateWindow = false
  647. };
  648. defenderService.RunTask().Wait();
  649. if (Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Services\\WinDefend") != null)
  650. {
  651. throw new Exception("Could not remove WinDefend service.");
  652. }
  653. // MpOAV.dll normally in use by a lot of processes. This prevents that.
  654. var MpOAVCLSID = new RunAction()
  655. {
  656. RawPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
  657. Exe = $"NSudoLC.exe",
  658. Arguments = @"-U:T -P:E -M:S -Priority:RealTime -ShowWindowMode:Hide -Wait reg delete ""HKCR\CLSID\{2781761E-28E0-4109-99FE-B9D127C57AFE}\InprocServer32"" /f",
  659. CreateWindow = false
  660. };
  661. MpOAVCLSID.RunTask().Wait();
  662. if (Registry.ClassesRoot.OpenSubKey(@"CLSID\{2781761E-28E0-4109-99FE-B9D127C57AFE}\InprocServer32") != null)
  663. {
  664. throw new Exception("Could not remove MpOAV mapping.");
  665. }
  666. // Can cause ProcessHacker driver warnings without this
  667. AmeliorationUtil.SafeRunAction(new RegistryValueAction()
  668. {
  669. KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity",
  670. Value = "Enabled",
  671. Data = 0,
  672. }).Wait();
  673. AmeliorationUtil.SafeRunAction(new RegistryValueAction()
  674. {
  675. KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\CI\Config",
  676. Value = "VulnerableDriverBlocklistEnable",
  677. Data = 0,
  678. }).Wait();
  679. }
  680. public static async Task UninstallDriver()
  681. {
  682. CmdAction cmdAction = new CmdAction();
  683. try
  684. {
  685. Console.WriteLine("Removing driver...");
  686. cmdAction.Command = Environment.Is64BitOperatingSystem
  687. ? $"ProcessHacker\\x64\\ProcessHacker.exe -s -uninstallkph"
  688. : $"ProcessHacker\\x86\\ProcessHacker.exe -s -uninstallkph";
  689. await cmdAction.RunTask();
  690. }
  691. catch (Exception e)
  692. {
  693. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "ProcessHacker ran into an Error while uninstalling the driver.");
  694. throw;
  695. }
  696. }
  697. public class RegistryManager
  698. {
  699. [DllImport("advapi32.dll", SetLastError = true)]
  700. static extern int RegLoadKey(IntPtr hKey, string lpSubKey, string lpFile);
  701. [DllImport("advapi32.dll", SetLastError = true)]
  702. static extern int RegSaveKey(IntPtr hKey, string lpFile, uint securityAttrPtr = 0);
  703. [DllImport("advapi32.dll", SetLastError = true)]
  704. static extern int RegUnLoadKey(IntPtr hKey, string lpSubKey);
  705. [DllImport("ntdll.dll", SetLastError = true)]
  706. static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege, out bool PreviousValue);
  707. [DllImport("advapi32.dll")]
  708. static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref UInt64 lpLuid);
  709. [DllImport("advapi32.dll")]
  710. static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpName, ref UInt64 lpLuid);
  711. public static void LoadFromFile(string path, bool classHive = false)
  712. {
  713. var parentKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default);
  714. string name;
  715. if (path.Contains("Users\\Default\\")) name = classHive ? "AME_UserHive_Default_Classes" : "AME_UserHive_Default";
  716. else name = classHive ? "AME_UserHive_" + (HivesLoaded + 1) + "_Classes" : "AME_UserHive_" + (HivesLoaded + 1);
  717. IntPtr parentHandle = parentKey.Handle.DangerousGetHandle();
  718. RegLoadKey(parentHandle, name, path);
  719. HivesLoaded++;
  720. }
  721. private static void AcquirePrivileges()
  722. {
  723. ulong luid = 0;
  724. bool throwaway;
  725. LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid);
  726. RtlAdjustPrivilege((int)luid, true, false, out throwaway);
  727. LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid);
  728. RtlAdjustPrivilege((int)luid, true, false, out throwaway);
  729. }
  730. private static void ReturnPrivileges()
  731. {
  732. ulong luid = 0;
  733. bool throwaway;
  734. LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid);
  735. RtlAdjustPrivilege((int)luid, false, false, out throwaway);
  736. LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid);
  737. RtlAdjustPrivilege((int)luid, false, false, out throwaway);
  738. }
  739. private static bool HivesHooked;
  740. private static int HivesLoaded;
  741. public static async void HookUserHives()
  742. {
  743. try
  744. {
  745. if (HivesHooked || WinUtil.IsTrustedInstaller() || RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default).GetSubKeyNames().Any(x => x.StartsWith("AME_UserHive_"))) return;
  746. HivesHooked = true;
  747. var usersDir = Environment.GetEnvironmentVariable("SYSTEMDRIVE") + "\\Users";
  748. var ignoreList = new List<string>() { "Default User", "Public", "All Users" };
  749. var userDirs = Directory.GetDirectories(usersDir).Where(x => !ignoreList.Contains(x.Split('\\').Last())).ToList();
  750. var userKeys = Registry.Users.GetSubKeyNames().Where(x => x.StartsWith("S-"));
  751. foreach (var userKey in userKeys)
  752. {
  753. try
  754. {
  755. var userEnv = Registry.Users.OpenSubKey(userKey).OpenSubKey("Volatile Environment");
  756. userDirs.Remove((string)userEnv.GetValue("USERPROFILE"));
  757. }
  758. catch (Exception) { }
  759. }
  760. if (userDirs.Any()) AcquirePrivileges();
  761. foreach (var userDir in userDirs)
  762. {
  763. if (!File.Exists($"{userDir}\\NTUSER.DAT"))
  764. {
  765. ErrorLogger.WriteToErrorLog($"NTUSER.DAT file not found in user folder '{userDir}'.",
  766. Environment.StackTrace, $"Error attempting to load user registry hive.");
  767. continue;
  768. }
  769. LoadFromFile($"{userDir}\\NTUSER.DAT");
  770. if (userDir.EndsWith("\\Default"))
  771. {
  772. try
  773. {
  774. if (!Directory.Exists($@"{userDir}\AppData\Local\Microsoft\Windows")) Directory.CreateDirectory($@"{userDir}\AppData\Local\Microsoft\Windows");
  775. var fs = File.Create($@"{userDir}\AppData\Local\Microsoft\Windows" + @"\UsrClass.dat");
  776. var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("TrustedUninstaller.Shared.Properties.UsrClass.dat");
  777. resource.CopyTo(fs);
  778. fs.Close();
  779. }
  780. catch (Exception e)
  781. {
  782. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace,
  783. $"Failed to create default user class hive.", userDir);
  784. }
  785. }
  786. if (!File.Exists($@"{userDir}\AppData\Local\Microsoft\Windows\UsrClass.dat"))
  787. {
  788. ErrorLogger.WriteToErrorLog($@"UsrClass.dat file not found in user appdata folder '{userDir}\AppData\Local\Microsoft\Windows'.",
  789. Environment.StackTrace, $"Error attempting to load user classes registry hive.");
  790. continue;
  791. }
  792. LoadFromFile($@"{userDir}\AppData\Local\Microsoft\Windows\UsrClass.dat", true);
  793. }
  794. if (userDirs.Any()) ReturnPrivileges();
  795. }
  796. catch (Exception e)
  797. {
  798. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace,
  799. $"Critical error while attempting to mount user hives.");
  800. Console.WriteLine(":AME-ERROR: Failure while mounting user registry hives.");
  801. }
  802. }
  803. public static async void UnhookUserHives()
  804. {
  805. try
  806. {
  807. var usersKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default);
  808. var userHives = usersKey.GetSubKeyNames().Where(x => x.StartsWith("AME_UserHive_")).ToList();
  809. if (userHives.Any()) AcquirePrivileges();
  810. foreach (var userHive in userHives)
  811. {
  812. RegUnLoadKey(usersKey.Handle.DangerousGetHandle(), userHive);
  813. }
  814. if (userHives.Any()) ReturnPrivileges();
  815. usersKey.Close();
  816. }
  817. catch (Exception e)
  818. {
  819. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace,
  820. $"Critical error while attempting to unmount user hives.");
  821. Console.WriteLine(":AME-ERROR: Failure while unmounting user registry hives.");
  822. }
  823. }
  824. }
  825. }
  826. }