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.

936 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 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. }
  411. }
  412. else throw new Exception("Could not list processes locking resource.");
  413. }
  414. else if (res != 0)
  415. throw new Exception("Could not list processes locking resource. Could not get size of result." + $" Result value: {res}");
  416. } finally
  417. {
  418. RmEndSession(handle);
  419. }
  420. return processes;
  421. }
  422. /// <summary>
  423. /// Finds active anti-viruses in the system.
  424. /// </summary>
  425. /// <returns>a list of ProviderStatus.</returns>
  426. /// <remarks>See also:
  427. /// https://jdhitsolutions.com/blog/powershell/5187/get-antivirus-product-status-with-powershell/
  428. /// https://docs.microsoft.com/en-us/windows/win32/api/iwscapi/ne-iwscapi-wsc_security_product_state?redirectedfrom=MSDN
  429. /// https://mspscripts.com/get-installed-antivirus-information-2/
  430. /// https://social.msdn.microsoft.com/Forums/pt-BR/6501b87e-dda4-4838-93c3-244daa355d7c/wmisecuritycenter2-productstate?forum=vblanguage
  431. /// https://stackoverflow.com/questions/4700897/wmi-security-center-productstate-clarification/4711211
  432. /// https://blogs.msdn.microsoft.com/alejacma/2008/05/12/how-to-get-antivirus-information-with-wmi-vbscript/#comment-442
  433. /// https://www.magnumdb.com/search?q=parent:WSC_SECURITY_PRODUCT_STATE
  434. /// https://web.archive.org/web/20190121133247/http://neophob.com/2010/03/wmi-query-windows-securitycenter2/
  435. /// </remarks>
  436. public static List<ProviderStatus> GetEnabledAvList(bool ensureWMI = true)
  437. {
  438. if (ensureWMI)
  439. {
  440. var svc = new ServiceController("Winmgmt");
  441. ChangeStartMode(svc, ServiceStartMode.Automatic);
  442. }
  443. List<ProviderStatus> avList = new List<ProviderStatus>();
  444. string computer = Environment.MachineName;
  445. string wmipath = @"\\" + computer + @"\root\SecurityCenter2";
  446. string query = @"SELECT * FROM AntivirusProduct WHERE displayName != ""Windows Defender""";
  447. try
  448. {
  449. using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmipath, query))
  450. {
  451. ManagementObjectCollection results = searcher.Get();
  452. foreach (var o in results)
  453. {
  454. // You can find if an AV is active or not by accessing the hex code of the productState
  455. // (from the right) 19th bit == Anti Virus is on
  456. // (from the right) 13th bit == On Access Scanning
  457. // 00000000 00000[1]10 000[1]0000 000[0]0000
  458. // 19th bit (yes) = Av on
  459. // 13th bit (yes) = On Access Scanning
  460. // The third byte defines if the .dat file is up-to-date
  461. var result = (ManagementObject)o;
  462. var productState = result["productState"];
  463. string hex = Hex(Convert.ToInt32(productState));
  464. string bin = Binary(Convert.ToInt32(productState));
  465. string reversed = Reverse(bin);
  466. var enabled = GetBit(reversed, 18);
  467. var scanning = GetBit(reversed, 12);
  468. var outdated = GetBit(reversed, 4);
  469. static string Binary(int value)
  470. {
  471. return Convert.ToString(value, 2).PadLeft(24, '0');
  472. }
  473. static string Hex(int value)
  474. {
  475. return Convert.ToString(value, 16).PadLeft(6, '0');
  476. }
  477. static bool GetBit(string value, int index)
  478. {
  479. return value.Substring(index, 1).Equals("1");
  480. }
  481. static string Reverse(string value)
  482. {
  483. return new string(value.Reverse().ToArray());
  484. }
  485. if (!enabled) continue;
  486. var av = new ProviderStatus()
  487. {
  488. DisplayName = result["displayName"].ToString(),
  489. AVStatus = enabled ? AVStatusFlags.Enabled : AVStatusFlags.Unknown,
  490. SecurityProvider = ProviderFlags.ANTIVIRUS,
  491. SignatureStatus = outdated ? SignatureStatusFlags.OutOfDate : SignatureStatusFlags.UpToDate
  492. };
  493. avList.Add(av);
  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. } catch (Exception e)
  549. {
  550. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "Error while installing VC 15.");
  551. throw;
  552. }
  553. }
  554. try
  555. {
  556. Console.WriteLine(Environment.NewLine + "Installing driver...");
  557. cmdAction.Command = Environment.Is64BitOperatingSystem
  558. ? $"ProcessHacker\\x64\\ProcessHacker.exe -s -installkph"
  559. : $"ProcessHacker\\x86\\ProcessHacker.exe -s -installkph";
  560. var res = await cmdAction.RunTask();
  561. } catch (Exception e)
  562. {
  563. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "ProcessHacker ran into an error while installing its driver.");
  564. throw;
  565. }
  566. }
  567. private const int GWL_STYLE = -16;
  568. private const int WS_SYSMENU = 0x80000;
  569. [DllImport("user32.dll", SetLastError = true)]
  570. private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
  571. [DllImport("user32.dll")]
  572. private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
  573. //public static void RemoveCloseButton(Window window)
  574. //{
  575. //var hwnd = new WindowInteropHelper(window).Handle;
  576. //SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);
  577. //}
  578. public static bool IsVM()
  579. {
  580. try
  581. {
  582. using (var searcher = new System.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem"))
  583. {
  584. using (var items = searcher.Get())
  585. {
  586. foreach (var item in items)
  587. {
  588. string manufacturer = item["Manufacturer"].ToString().ToLower();
  589. if ((manufacturer == "microsoft corporation" && item["Model"].ToString().ToUpperInvariant().Contains("VIRTUAL"))
  590. || manufacturer.Contains("vmware")
  591. || item["Model"].ToString() == "VirtualBox")
  592. {
  593. return true;
  594. }
  595. }
  596. }
  597. }
  598. return false;
  599. } catch (Exception e)
  600. {
  601. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "Error while checking if running system is a VM.");
  602. return false;
  603. }
  604. }
  605. public static void PrepareSystemCLI()
  606. {
  607. try
  608. {
  609. var defenderStop = new RunAction()
  610. {
  611. RawPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
  612. Exe = $"NSudoLC.exe",
  613. Arguments = "-U:T -P:E -M:S -ShowWindowMode:Hide -Priority:RealTime -Wait cmd /c \"" +
  614. "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)\"&" +
  615. "sc config WinDefend start=disabled&" +
  616. "net stop WinDefend\"",
  617. CreateWindow = false,
  618. Timeout = 7500,
  619. };
  620. defenderStop.RunTask().Wait();
  621. } catch (Exception e)
  622. {
  623. }
  624. var defenderValues = new RunAction()
  625. {
  626. RawPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
  627. Exe = $"NSudoLC.exe",
  628. Arguments = "-U:T -P:E -M:S -ShowWindowMode:Hide -Priority:RealTime -Wait cmd /c \"reg delete \"HKLM\\SOFTWARE\\Microsoft\\Windows Defender\" /v \"ProductAppDataPath\" /f &" +
  629. " reg delete \"HKLM\\SOFTWARE\\Microsoft\\Windows Defender\" /v \"InstallLocation\" /f\"",
  630. CreateWindow = false
  631. };
  632. defenderValues.RunTask().Wait();
  633. var defenderKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows Defender");
  634. if (defenderKey != null && defenderKey.GetValueNames().Contains("InstallLocation"))
  635. {
  636. throw new Exception("Could not remove defender install values.");
  637. }
  638. var defenderService = new RunAction()
  639. {
  640. RawPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
  641. Exe = $"NSudoLC.exe",
  642. Arguments = "-U:T -P:E -M:S -ShowWindowMode:Hide -Priority:RealTime -Wait reg delete \"HKLM\\SYSTEM\\CurrentControlSet\\Services\\WinDefend\" /f",
  643. CreateWindow = false
  644. };
  645. defenderService.RunTask().Wait();
  646. if (Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Services\\WinDefend") != null)
  647. {
  648. throw new Exception("Could not remove WinDefend service.");
  649. }
  650. // MpOAV.dll normally in use by a lot of processes. This prevents that.
  651. var MpOAVCLSID = new RunAction()
  652. {
  653. RawPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
  654. Exe = $"NSudoLC.exe",
  655. Arguments = @"-U:T -P:E -M:S -Priority:RealTime -ShowWindowMode:Hide -Wait reg delete ""HKCR\CLSID\{2781761E-28E0-4109-99FE-B9D127C57AFE}\InprocServer32"" /f",
  656. CreateWindow = false
  657. };
  658. MpOAVCLSID.RunTask().Wait();
  659. if (Registry.ClassesRoot.OpenSubKey(@"CLSID\{2781761E-28E0-4109-99FE-B9D127C57AFE}\InprocServer32") != null)
  660. {
  661. throw new Exception("Could not remove MpOAV mapping.");
  662. }
  663. // Can cause ProcessHacker driver warnings without this
  664. AmeliorationUtil.SafeRunAction(new RegistryValueAction()
  665. {
  666. KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity",
  667. Value = "Enabled",
  668. Data = 0,
  669. }).Wait();
  670. AmeliorationUtil.SafeRunAction(new RegistryValueAction()
  671. {
  672. KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\CI\Config",
  673. Value = "VulnerableDriverBlocklistEnable",
  674. Data = 0,
  675. }).Wait();
  676. }
  677. public static async Task UninstallDriver()
  678. {
  679. CmdAction cmdAction = new CmdAction();
  680. try
  681. {
  682. Console.WriteLine("Removing driver...");
  683. cmdAction.Command = Environment.Is64BitOperatingSystem
  684. ? $"ProcessHacker\\x64\\ProcessHacker.exe -s -uninstallkph"
  685. : $"ProcessHacker\\x86\\ProcessHacker.exe -s -uninstallkph";
  686. await cmdAction.RunTask();
  687. }
  688. catch (Exception e)
  689. {
  690. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "ProcessHacker ran into an Error while uninstalling the driver.");
  691. throw;
  692. }
  693. }
  694. public class RegistryManager
  695. {
  696. [DllImport("advapi32.dll", SetLastError = true)]
  697. static extern int RegLoadKey(IntPtr hKey, string lpSubKey, string lpFile);
  698. [DllImport("advapi32.dll", SetLastError = true)]
  699. static extern int RegSaveKey(IntPtr hKey, string lpFile, uint securityAttrPtr = 0);
  700. [DllImport("advapi32.dll", SetLastError = true)]
  701. static extern int RegUnLoadKey(IntPtr hKey, string lpSubKey);
  702. [DllImport("ntdll.dll", SetLastError = true)]
  703. static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege, out bool PreviousValue);
  704. [DllImport("advapi32.dll")]
  705. static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref UInt64 lpLuid);
  706. [DllImport("advapi32.dll")]
  707. static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpName, ref UInt64 lpLuid);
  708. public static void LoadFromFile(string path, bool classHive = false)
  709. {
  710. var parentKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default);
  711. string name;
  712. if (path.Contains("Users\\Default\\")) name = classHive ? "AME_UserHive_Default_Classes" : "AME_UserHive_Default";
  713. else name = classHive ? "AME_UserHive_" + (HivesLoaded + 1) + "_Classes" : "AME_UserHive_" + (HivesLoaded + 1);
  714. IntPtr parentHandle = parentKey.Handle.DangerousGetHandle();
  715. RegLoadKey(parentHandle, name, path);
  716. HivesLoaded++;
  717. }
  718. private static void AcquirePrivileges()
  719. {
  720. ulong luid = 0;
  721. bool throwaway;
  722. LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid);
  723. RtlAdjustPrivilege((int)luid, true, false, out throwaway);
  724. LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid);
  725. RtlAdjustPrivilege((int)luid, true, false, out throwaway);
  726. }
  727. private static void ReturnPrivileges()
  728. {
  729. ulong luid = 0;
  730. bool throwaway;
  731. LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid);
  732. RtlAdjustPrivilege((int)luid, false, false, out throwaway);
  733. LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid);
  734. RtlAdjustPrivilege((int)luid, false, false, out throwaway);
  735. }
  736. private static bool HivesHooked;
  737. private static int HivesLoaded;
  738. public static async void HookUserHives()
  739. {
  740. try
  741. {
  742. if (HivesHooked || WinUtil.IsTrustedInstaller() || RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default).GetSubKeyNames().Any(x => x.StartsWith("AME_UserHive_"))) return;
  743. HivesHooked = true;
  744. var usersDir = Environment.GetEnvironmentVariable("SYSTEMDRIVE") + "\\Users";
  745. var ignoreList = new List<string>() { "Default User", "Public", "All Users" };
  746. var userDirs = Directory.GetDirectories(usersDir).Where(x => !ignoreList.Contains(x.Split('\\').Last())).ToList();
  747. var userKeys = Registry.Users.GetSubKeyNames().Where(x => x.StartsWith("S-"));
  748. foreach (var userKey in userKeys)
  749. {
  750. try
  751. {
  752. var userEnv = Registry.Users.OpenSubKey(userKey).OpenSubKey("Volatile Environment");
  753. userDirs.Remove((string)userEnv.GetValue("USERPROFILE"));
  754. }
  755. catch (Exception) { }
  756. }
  757. if (userDirs.Any()) AcquirePrivileges();
  758. foreach (var userDir in userDirs)
  759. {
  760. if (!File.Exists($"{userDir}\\NTUSER.DAT"))
  761. {
  762. ErrorLogger.WriteToErrorLog($"NTUSER.DAT file not found in user folder '{userDir}'.",
  763. Environment.StackTrace, $"Error attempting to load user registry hive.");
  764. continue;
  765. }
  766. LoadFromFile($"{userDir}\\NTUSER.DAT");
  767. if (userDir.EndsWith("\\Default"))
  768. {
  769. try
  770. {
  771. if (!Directory.Exists($@"{userDir}\AppData\Local\Microsoft\Windows")) Directory.CreateDirectory($@"{userDir}\AppData\Local\Microsoft\Windows");
  772. var fs = File.Create($@"{userDir}\AppData\Local\Microsoft\Windows" + @"\UsrClass.dat");
  773. var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("TrustedUninstaller.Shared.Properties.UsrClass.dat");
  774. resource.CopyTo(fs);
  775. fs.Close();
  776. }
  777. catch (Exception e)
  778. {
  779. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace,
  780. $"Failed to create default user class hive.", userDir);
  781. }
  782. }
  783. if (!File.Exists($@"{userDir}\AppData\Local\Microsoft\Windows\UsrClass.dat"))
  784. {
  785. ErrorLogger.WriteToErrorLog($@"UsrClass.dat file not found in user appdata folder '{userDir}\AppData\Local\Microsoft\Windows'.",
  786. Environment.StackTrace, $"Error attempting to load user classes registry hive.");
  787. continue;
  788. }
  789. LoadFromFile($@"{userDir}\AppData\Local\Microsoft\Windows\UsrClass.dat", true);
  790. }
  791. if (userDirs.Any()) ReturnPrivileges();
  792. }
  793. catch (Exception e)
  794. {
  795. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace,
  796. $"Critical error while attempting to mount user hives.");
  797. Console.WriteLine(":AME-ERROR: Failure while mounting user registry hives.");
  798. }
  799. }
  800. public static async void UnhookUserHives()
  801. {
  802. try
  803. {
  804. var usersKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default);
  805. var userHives = usersKey.GetSubKeyNames().Where(x => x.StartsWith("AME_UserHive_")).ToList();
  806. if (userHives.Any()) AcquirePrivileges();
  807. foreach (var userHive in userHives)
  808. {
  809. RegUnLoadKey(usersKey.Handle.DangerousGetHandle(), userHive);
  810. }
  811. if (userHives.Any()) ReturnPrivileges();
  812. usersKey.Close();
  813. }
  814. catch (Exception e)
  815. {
  816. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace,
  817. $"Critical error while attempting to unmount user hives.");
  818. Console.WriteLine(":AME-ERROR: Failure while unmounting user registry hives.");
  819. }
  820. }
  821. }
  822. }
  823. }