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.

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