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.

170 lines
7.1 KiB

1 year ago
1 year ago
1 year ago
1 year ago
  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Windows;
  7. using TrustedUninstaller.Shared;
  8. using TrustedUninstaller.Shared.Actions;
  9. namespace TrustedUninstaller.CLI
  10. {
  11. public class CLI
  12. {
  13. private static async System.Threading.Tasks.Task<int> Main(string[] args)
  14. {
  15. //Needed after defender removal's reboot, the "current directory" will be set to System32
  16. //After the auto start up.
  17. Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
  18. DualOut.Init();
  19. if (!WinUtil.IsAdministrator())
  20. {
  21. System.Console.Error.WriteLine("This program must be launched as an Administrator!");
  22. return -1;
  23. }
  24. #if !DEBUG
  25. /*
  26. if (!WinUtil.IsGenuineWindows())
  27. {
  28. System.Console.Error.WriteLine("This program only works on genuine Windows copies!");
  29. return -1;
  30. }
  31. */
  32. #endif
  33. if (args.Length < 1 || !Directory.Exists(args[0]))
  34. {
  35. Console.WriteLine("No Playbook selected: Use the GUI to select a playbook to run.");
  36. return -1;
  37. }
  38. AmeliorationUtil.Playbook = await AmeliorationUtil.DeserializePlaybook(args[0]);
  39. if (!Directory.Exists($"{AmeliorationUtil.Playbook.Path}\\Configuration"))
  40. {
  41. Console.WriteLine("Creating Configuration folder...");
  42. Directory.CreateDirectory($"{AmeliorationUtil.Playbook.Path}\\Configuration");
  43. }
  44. if (Directory.GetFiles($"{AmeliorationUtil.Playbook.Path}\\Configuration").Length == 0)
  45. {
  46. Console.WriteLine("Configuration folder is empty, put YAML files in it and restart the application.");
  47. Console.WriteLine($"Current directory: {Directory.GetCurrentDirectory()}");
  48. return -1;
  49. }
  50. ExtractResourceFolder("resources", Directory.GetCurrentDirectory());
  51. if (!WinUtil.IsTrustedInstaller())
  52. {
  53. Console.WriteLine("Checking requirements...\r\n");
  54. if (AmeliorationUtil.Playbook.Requirements.Contains(Requirements.Requirement.Internet) && !await (new Requirements.Internet()).IsMet())
  55. {
  56. Console.WriteLine("Internet must be connected to run this Playbook.");
  57. }
  58. if (AmeliorationUtil.Playbook.Requirements.Contains(Requirements.Requirement.DefenderDisabled) && Process.GetProcessesByName("MsMpEng").Any())
  59. {
  60. Console.WriteLine("The system must be prepared before continuing. Make sure all 4 windows security toggles are set to off.\r\nYour system will restart after preparation\r\nPress any key to continue...");
  61. Console.ReadKey();
  62. try
  63. {
  64. WinUtil.PrepareSystemCLI();
  65. CmdAction reboot = new CmdAction()
  66. {
  67. Command = "timeout /t 1 & shutdown /r /t 0",
  68. Wait = false
  69. };
  70. AmeliorationUtil.SafeRunAction(reboot).Wait();
  71. Environment.Exit(0);
  72. } catch (Exception e)
  73. {
  74. Console.WriteLine("Error preparing system: " + e.Message);
  75. Environment.Exit(-1);
  76. }
  77. }
  78. if (AmeliorationUtil.Playbook.Requirements.Contains(Requirements.Requirement.Internet) && !await (new Requirements.Internet()).IsMet())
  79. {
  80. Console.WriteLine("Internet must be connected to run this Playbook.");
  81. }
  82. }
  83. await AmeliorationUtil.StartAmelioration();
  84. return 0;
  85. }
  86. public static void ExtractResourceFolder(string resource, string dir, bool overwrite = false)
  87. {
  88. if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
  89. Assembly assembly = Assembly.GetExecutingAssembly();
  90. var resources = assembly.GetManifestResourceNames().Where(res => res.StartsWith($"TrustedUninstaller.CLI.Properties"));
  91. foreach (var obj in resources)
  92. {
  93. using (UnmanagedMemoryStream stream = (UnmanagedMemoryStream)assembly.GetManifestResourceStream(obj))
  94. {
  95. int MB = 1024 * 1024;
  96. int offset = -MB;
  97. var file = dir + $"\\{obj.Substring($"TrustedUninstaller.CLI.Properties.{resource}.".Length).Replace("---", "\\")}";
  98. if (file.EndsWith(".gitkeep")) continue;
  99. var fileDir = Path.GetDirectoryName(file);
  100. if (fileDir != null && !Directory.Exists(fileDir)) Directory.CreateDirectory(fileDir);
  101. if (File.Exists(file) && !overwrite) continue;
  102. if (File.Exists(file) && overwrite)
  103. {
  104. try
  105. {
  106. File.Delete(file);
  107. }
  108. catch (Exception e)
  109. {
  110. if (!Directory.Exists(Directory.GetCurrentDirectory() + "\\Logs"))
  111. Directory.CreateDirectory(Directory.GetCurrentDirectory() + "\\Logs");
  112. using (var writer = new StreamWriter(Path.Combine(Directory.GetCurrentDirectory(), "Logs\\ErrorLog.txt"), true))
  113. {
  114. writer.WriteLine($"Title: Could not delete existing resource file {file}.\r\nMessage: {e.Message}\r\n\r\nStackTrace: {e.StackTrace}");
  115. writer.WriteLine("\r\nDate/Time: " + DateTime.Now);
  116. writer.WriteLine("============================================");
  117. }
  118. continue;
  119. }
  120. }
  121. using (FileStream fsDlst = new FileStream(file, FileMode.CreateNew, FileAccess.Write))
  122. {
  123. while (offset + MB < stream.Length)
  124. {
  125. var buffer = new byte[MB];
  126. offset += MB;
  127. if (offset + MB > stream.Length)
  128. {
  129. var bytesLeft = stream.Length - offset;
  130. buffer = new byte[bytesLeft];
  131. }
  132. stream.Seek(offset, SeekOrigin.Begin);
  133. stream.Read(buffer, 0, buffer.Length);
  134. fsDlst.Seek(offset, SeekOrigin.Begin);
  135. fsDlst.Write(buffer, 0, buffer.Length);
  136. }
  137. }
  138. }
  139. }
  140. }
  141. }
  142. }