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.

393 lines
14 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. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Globalization;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Management;
  8. using System.Net;
  9. using System.Reflection;
  10. using System.Runtime.InteropServices;
  11. using System.Threading.Tasks;
  12. using System.Windows;
  13. using System.Xml.Serialization;
  14. using Microsoft.Win32;
  15. using TrustedUninstaller.Shared;
  16. using TrustedUninstaller.Shared.Actions;
  17. namespace TrustedUninstaller.Shared
  18. {
  19. public static class Requirements
  20. {
  21. [Serializable]
  22. public enum Requirement
  23. {
  24. [XmlEnum("Internet")]
  25. Internet = 0,
  26. [XmlEnum("NoInternet")]
  27. NoInternet = 1,
  28. [XmlEnum("DefenderDisabled")]
  29. DefenderDisabled = 2,
  30. [XmlEnum("DefenderToggled")]
  31. DefenderToggled = 3,
  32. [XmlEnum("NoPendingUpdates")]
  33. NoPendingUpdates = 4,
  34. [XmlEnum("Activation")]
  35. Activation = 5,
  36. [XmlEnum("NoAntivirus")]
  37. NoAntivirus = 6,
  38. [XmlEnum("PasswordSet")]
  39. PasswordSet = 7,
  40. [XmlEnum("AdministratorPasswordSet")]
  41. AdministratorPasswordSet = 8,
  42. [XmlEnum("PluggedIn")]
  43. PluggedIn = 9,
  44. }
  45. public static async Task<Requirement[]> MetRequirements(this Requirement[] requirements)
  46. {
  47. var requirementEnum = (Requirement[])Enum.GetValues(typeof(Requirement));
  48. if (requirements == null)
  49. {
  50. return requirementEnum;
  51. }
  52. // Add all requirements that are not included
  53. var metRequirements = requirementEnum.Except(requirements).ToList();
  54. if (requirements.Contains(Requirement.Internet))
  55. if (await new Internet().IsMet()) metRequirements.Add(Requirement.Internet);
  56. else metRequirements.Add(Requirement.NoInternet);
  57. if (requirements.Contains(Requirement.NoAntivirus))
  58. if (await new NoAntivirus().IsMet()) metRequirements.Add(Requirement.NoAntivirus);
  59. if (requirements.Contains(Requirement.NoPendingUpdates))
  60. if (await new NoPendingUpdates().IsMet()) metRequirements.Add(Requirement.NoPendingUpdates);
  61. if (requirements.Contains(Requirement.Activation))
  62. if (await new Activation().IsMet()) metRequirements.Add(Requirement.Activation);
  63. if (requirements.Contains(Requirement.DefenderDisabled))
  64. if (await new DefenderDisabled().IsMet()) metRequirements.Add(Requirement.DefenderDisabled);
  65. if (requirements.Contains(Requirement.DefenderToggled))
  66. if (await new DefenderDisabled().IsMet()) metRequirements.Add(Requirement.DefenderToggled);
  67. if (requirements.Contains(Requirement.PasswordSet))
  68. metRequirements.Add(Requirement.PasswordSet);
  69. if (requirements.Contains(Requirement.AdministratorPasswordSet))
  70. metRequirements.Add(Requirement.AdministratorPasswordSet);
  71. if (requirements.Contains(Requirement.PluggedIn))
  72. if (await new Battery().IsMet()) metRequirements.Add(Requirement.PluggedIn);
  73. return metRequirements.ToArray();
  74. }
  75. public interface IRequirements
  76. {
  77. Task<bool> IsMet();
  78. Task<bool> Meet();
  79. }
  80. public class RequirementBase
  81. {
  82. public class ProgressEventArgs : EventArgs
  83. {
  84. public int PercentAdded;
  85. public ProgressEventArgs(int percent)
  86. {
  87. PercentAdded = percent;
  88. }
  89. }
  90. public event EventHandler<ProgressEventArgs> ProgressChanged;
  91. protected void OnProgressAdded(int percent)
  92. {
  93. ProgressChanged?.Invoke(this, new ProgressEventArgs(percent));
  94. }
  95. }
  96. public class Battery : RequirementBase, IRequirements
  97. {
  98. [StructLayout(LayoutKind.Sequential)]
  99. public class PowerState
  100. {
  101. public ACLineStatus ACLineStatus;
  102. public BatteryFlag BatteryFlag;
  103. public Byte BatteryLifePercent;
  104. public Byte Reserved1;
  105. public Int32 BatteryLifeTime;
  106. public Int32 BatteryFullLifeTime;
  107. // direct instantation not intended, use GetPowerState.
  108. private PowerState() {}
  109. public static PowerState GetPowerState()
  110. {
  111. PowerState state = new PowerState();
  112. if (GetSystemPowerStatusRef(state))
  113. return state;
  114. throw new ApplicationException("Unable to get power state");
  115. }
  116. [DllImport("Kernel32", EntryPoint = "GetSystemPowerStatus")]
  117. private static extern bool GetSystemPowerStatusRef(PowerState sps);
  118. }
  119. // Note: Underlying type of byte to match Win32 header
  120. public enum ACLineStatus : byte
  121. {
  122. Offline = 0, Online = 1, Unknown = 255
  123. }
  124. public enum BatteryFlag : byte
  125. {
  126. High = 1, Low = 2, Critical = 4, Charging = 8,
  127. NoSystemBattery = 128, Unknown = 255
  128. }
  129. public async Task<bool> IsMet()
  130. {
  131. try
  132. {
  133. PowerState state = PowerState.GetPowerState();
  134. if ((state.BatteryFlag == BatteryFlag.NoSystemBattery || state.BatteryFlag == BatteryFlag.Charging)
  135. || state.ACLineStatus == ACLineStatus.Online || (state.ACLineStatus == ACLineStatus.Unknown && state.BatteryFlag == BatteryFlag.Unknown))
  136. return true;
  137. else
  138. return false;
  139. }
  140. catch { }
  141. return true;
  142. }
  143. public Task<bool> Meet() => throw new NotImplementedException();
  144. }
  145. public class Internet : RequirementBase, IRequirements
  146. {
  147. [DllImport("wininet.dll", SetLastError = true)]
  148. private static extern bool InternetCheckConnection(string lpszUrl, int dwFlags, int dwReserved);
  149. [DllImport("wininet.dll", SetLastError=true)]
  150. extern static bool InternetGetConnectedState(out int lpdwFlags, int dwReserved);
  151. public async Task<bool> IsMet()
  152. {
  153. try
  154. {
  155. try
  156. {
  157. if (!InternetCheckConnection("http://archlinux.org", 1, 0))
  158. {
  159. if (!InternetCheckConnection("http://google.com", 1, 0))
  160. return false;
  161. }
  162. return true;
  163. }
  164. catch
  165. {
  166. var request = (HttpWebRequest)WebRequest.Create("http://google.com");
  167. request.KeepAlive = false;
  168. request.Timeout = 5000;
  169. using (var response = (HttpWebResponse)request.GetResponse())
  170. return true;
  171. }
  172. }
  173. catch
  174. {
  175. return false;
  176. }
  177. }
  178. public Task<bool> Meet() => throw new NotImplementedException();
  179. }
  180. public class DefenderDisabled : RequirementBase, IRequirements
  181. {
  182. public async Task<bool> IsMet()
  183. {
  184. if (Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Services\\WinDefend") != null)
  185. return false;
  186. return Process.GetProcessesByName("MsMpEng").Length == 0;
  187. }
  188. public async Task<bool> Meet()
  189. {
  190. OnProgressAdded(30);
  191. try
  192. {
  193. //Scheduled task to run the program on logon, and remove defender notifications
  194. var runOnLogOn = new CmdAction()
  195. {
  196. Command = $"schtasks /create /tn \"AME Wizard\" /tr \"{Assembly.GetExecutingAssembly().Location}\" /sc onlogon /RL HIGHEST /f",
  197. Wait = false
  198. };
  199. await runOnLogOn.RunTask();
  200. OnProgressAdded(10);
  201. var disableNotifs = new CmdAction()
  202. {
  203. Command = $"reg add \"HKLM\\SOFTWARE\\Policies\\Microsoft\\Windows Defender Security Center\\Notifications\" /v DisableNotifications /t REG_DWORD /d 1 /f"
  204. };
  205. await disableNotifs.RunTask();
  206. OnProgressAdded(10);
  207. var defenderService = new RunAction()
  208. {
  209. Exe = $"NSudoLC.exe",
  210. Arguments = "-U:T -P:E -M:S -Priority:RealTime -UseCurrentConsole -Wait reg delete \"HKLM\\SYSTEM\\CurrentControlSet\\Services\\WinDefend\" /f",
  211. BaseDir = true,
  212. CreateWindow = false
  213. };
  214. await defenderService.RunTask();
  215. OnProgressAdded(20);
  216. // MpOAV.dll normally in use by a lot of processes. This prevents that.
  217. var MpOAVCLSID = new RunAction()
  218. {
  219. Exe = $"NSudoLC.exe",
  220. Arguments = @"-U:T -P:E -M:S -Priority:RealTime -Wait reg delete ""HKCR\CLSID\{2781761E-28E0-4109-99FE-B9D127C57AFE}\InprocServer32"" /f",
  221. BaseDir = true,
  222. CreateWindow = false
  223. };
  224. await MpOAVCLSID.RunTask();
  225. OnProgressAdded(20);
  226. if (Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Services\\WinDefend") != null)
  227. {
  228. throw new Exception("Could not remove WinDefend service.");
  229. }
  230. OnProgressAdded(10);
  231. return true;
  232. }
  233. catch (Exception exception)
  234. {
  235. ErrorLogger.WriteToErrorLog(exception.Message, exception.StackTrace,
  236. $"Could not remove Windows Defender.");
  237. return false;
  238. // TODO: Move this to requirements page view if any Meet calls return false
  239. try
  240. {
  241. var saveLogDir = System.Windows.Forms.Application.StartupPath + "\\AME Logs";
  242. if (Directory.Exists(saveLogDir)) Directory.Delete(saveLogDir, true);
  243. Directory.Move(Directory.GetCurrentDirectory() + "\\Logs", saveLogDir);
  244. }
  245. catch (Exception) { }
  246. //MessageBox.Show("Could not remove Windows Defender. Check the error logs and contact the team " +
  247. // "for more information and assistance.", "Could not remove Windows Defender.", MessageBoxButton.OK, MessageBoxImage.Error);
  248. }
  249. }
  250. }
  251. public class DefenderToggled : RequirementBase, IRequirements
  252. {
  253. public async Task<bool> IsMet()
  254. {
  255. var defenderKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows Defender");
  256. RegistryKey realtimeKey = null;
  257. try
  258. {
  259. realtimeKey = defenderKey.OpenSubKey("Real-Time Protection");
  260. }
  261. catch
  262. {
  263. }
  264. if (realtimeKey != null)
  265. {
  266. try
  267. {
  268. if (!((int)realtimeKey.GetValue("DisableRealtimeMonitoring") != 1))
  269. return false;
  270. }
  271. catch (Exception exception)
  272. {
  273. return false;
  274. }
  275. }
  276. try
  277. {
  278. if (!((int)defenderKey.OpenSubKey("SpyNet").GetValue("SpyNetReporting") != 0))
  279. return false;
  280. }
  281. catch
  282. {
  283. }
  284. try
  285. {
  286. if (!((int)defenderKey.OpenSubKey("SpyNet").GetValue("SubmitSamplesConsent") != 0))
  287. return false;
  288. }
  289. catch
  290. {
  291. }
  292. try
  293. {
  294. if (!((int)defenderKey.OpenSubKey("Features").GetValue("TamperProtection") != 4))
  295. return false;
  296. }
  297. catch
  298. {
  299. }
  300. return true;
  301. }
  302. public async Task<bool> Meet()
  303. {
  304. throw new NotImplementedException();
  305. }
  306. }
  307. public class NoPendingUpdates : RequirementBase, IRequirements
  308. {
  309. public async Task<bool> IsMet()
  310. {
  311. //TODO: This
  312. return true;
  313. }
  314. public Task<bool> Meet() => throw new NotImplementedException();
  315. }
  316. public class NoAntivirus : RequirementBase, IRequirements
  317. {
  318. public async Task<bool> IsMet()
  319. {
  320. return !WinUtil.GetEnabledAvList(false).Any();
  321. }
  322. public Task<bool> Meet() => throw new NotImplementedException();
  323. }
  324. public class Activation : RequirementBase, IRequirements
  325. {
  326. public async Task<bool> IsMet()
  327. {
  328. return WinUtil.IsGenuineWindows();
  329. }
  330. public Task<bool> Meet() => throw new NotImplementedException();
  331. }
  332. public class WindowsBuild
  333. {
  334. public bool IsMet(string[] builds)
  335. {
  336. return builds.Any(x => x.Equals(Globals.WinVer.ToString()));
  337. }
  338. public Task<bool> Meet() => throw new NotImplementedException();
  339. }
  340. }
  341. }