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.

855 lines
35 KiB

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 async Task UninstallDriver()
  609. {
  610. CmdAction cmdAction = new CmdAction();
  611. try
  612. {
  613. Console.WriteLine("Removing driver...");
  614. cmdAction.Command = Environment.Is64BitOperatingSystem
  615. ? $"ProcessHacker\\x64\\ProcessHacker.exe -s -uninstallkph"
  616. : $"ProcessHacker\\x86\\ProcessHacker.exe -s -uninstallkph";
  617. await cmdAction.RunTask();
  618. }
  619. catch (Exception e)
  620. {
  621. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "ProcessHacker ran into an Error while uninstalling the driver.");
  622. throw;
  623. }
  624. }
  625. public class RegistryManager
  626. {
  627. [DllImport("advapi32.dll", SetLastError = true)]
  628. static extern int RegLoadKey(IntPtr hKey, string lpSubKey, string lpFile);
  629. [DllImport("advapi32.dll", SetLastError = true)]
  630. static extern int RegSaveKey(IntPtr hKey, string lpFile, uint securityAttrPtr = 0);
  631. [DllImport("advapi32.dll", SetLastError = true)]
  632. static extern int RegUnLoadKey(IntPtr hKey, string lpSubKey);
  633. [DllImport("ntdll.dll", SetLastError = true)]
  634. static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege, out bool PreviousValue);
  635. [DllImport("advapi32.dll")]
  636. static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref UInt64 lpLuid);
  637. [DllImport("advapi32.dll")]
  638. static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpName, ref UInt64 lpLuid);
  639. public static void LoadFromFile(string path, bool classHive = false)
  640. {
  641. var parentKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default);
  642. string name;
  643. if (path.Contains("Users\\Default\\")) name = classHive ? "AME_UserHive_Default_Classes" : "AME_UserHive_Default";
  644. else name = classHive ? "AME_UserHive_" + (HivesLoaded + 1) + "_Classes" : "AME_UserHive_" + (HivesLoaded + 1);
  645. IntPtr parentHandle = parentKey.Handle.DangerousGetHandle();
  646. RegLoadKey(parentHandle, name, path);
  647. HivesLoaded++;
  648. }
  649. private static void AcquirePrivileges()
  650. {
  651. ulong luid = 0;
  652. bool throwaway;
  653. LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid);
  654. RtlAdjustPrivilege((int)luid, true, false, out throwaway);
  655. LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid);
  656. RtlAdjustPrivilege((int)luid, true, false, out throwaway);
  657. }
  658. private static void ReturnPrivileges()
  659. {
  660. ulong luid = 0;
  661. bool throwaway;
  662. LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid);
  663. RtlAdjustPrivilege((int)luid, false, false, out throwaway);
  664. LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid);
  665. RtlAdjustPrivilege((int)luid, false, false, out throwaway);
  666. }
  667. private static bool HivesHooked;
  668. private static int HivesLoaded;
  669. public static async void HookUserHives()
  670. {
  671. try
  672. {
  673. if (HivesHooked || WinUtil.IsTrustedInstaller() || RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default).GetSubKeyNames().Any(x => x.StartsWith("AME_UserHive_"))) return;
  674. HivesHooked = true;
  675. var usersDir = Environment.GetEnvironmentVariable("SYSTEMDRIVE") + "\\Users";
  676. var ignoreList = new List<string>() { "Default User", "Public", "All Users" };
  677. var userDirs = Directory.GetDirectories(usersDir).Where(x => !ignoreList.Contains(x.Split('\\').Last())).ToList();
  678. var userKeys = Registry.Users.GetSubKeyNames().Where(x => x.StartsWith("S-"));
  679. foreach (var userKey in userKeys)
  680. {
  681. try
  682. {
  683. var userEnv = Registry.Users.OpenSubKey(userKey).OpenSubKey("Volatile Environment");
  684. userDirs.Remove((string)userEnv.GetValue("USERPROFILE"));
  685. }
  686. catch (Exception) { }
  687. }
  688. if (userDirs.Any()) AcquirePrivileges();
  689. foreach (var userDir in userDirs)
  690. {
  691. if (!File.Exists($"{userDir}\\NTUSER.DAT"))
  692. {
  693. ErrorLogger.WriteToErrorLog($"NTUSER.DAT file not found in user folder '{userDir}'.",
  694. Environment.StackTrace, $"Error attempting to load user registry hive.");
  695. continue;
  696. }
  697. LoadFromFile($"{userDir}\\NTUSER.DAT");
  698. if (userDir.EndsWith("\\Default"))
  699. {
  700. try
  701. {
  702. if (!Directory.Exists($@"{userDir}\AppData\Local\Microsoft\Windows")) Directory.CreateDirectory($@"{userDir}\AppData\Local\Microsoft\Windows");
  703. var fs = File.Create($@"{userDir}\AppData\Local\Microsoft\Windows" + @"\UsrClass.dat");
  704. var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("TrustedUninstaller.Shared.Properties.UsrClass.dat");
  705. resource.CopyTo(fs);
  706. fs.Close();
  707. }
  708. catch (Exception e)
  709. {
  710. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace,
  711. $"Failed to create default user class hive.", userDir);
  712. }
  713. }
  714. if (!File.Exists($@"{userDir}\AppData\Local\Microsoft\Windows\UsrClass.dat"))
  715. {
  716. ErrorLogger.WriteToErrorLog($@"UsrClass.dat file not found in user appdata folder '{userDir}\AppData\Local\Microsoft\Windows'.",
  717. Environment.StackTrace, $"Error attempting to load user classes registry hive.");
  718. continue;
  719. }
  720. LoadFromFile($@"{userDir}\AppData\Local\Microsoft\Windows\UsrClass.dat", true);
  721. }
  722. if (userDirs.Any()) ReturnPrivileges();
  723. }
  724. catch (Exception e)
  725. {
  726. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace,
  727. $"Critical error while attempting to mount user hives.");
  728. Console.WriteLine(":AME-ERROR: Failure while mounting user registry hives.");
  729. }
  730. }
  731. public static async void UnhookUserHives()
  732. {
  733. try
  734. {
  735. var usersKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default);
  736. var userHives = usersKey.GetSubKeyNames().Where(x => x.StartsWith("AME_UserHive_")).ToList();
  737. if (userHives.Any()) AcquirePrivileges();
  738. foreach (var userHive in userHives)
  739. {
  740. RegUnLoadKey(usersKey.Handle.DangerousGetHandle(), userHive);
  741. }
  742. if (userHives.Any()) ReturnPrivileges();
  743. usersKey.Close();
  744. }
  745. catch (Exception e)
  746. {
  747. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace,
  748. $"Critical error while attempting to unmount user hives.");
  749. Console.WriteLine(":AME-ERROR: Failure while unmounting user registry hives.");
  750. }
  751. }
  752. }
  753. }
  754. }