Tool for checking the integrity of an AME installation
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.

629 lines
24 KiB

1 year ago
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Threading;
  7. using System.Runtime.InteropServices;
  8. using System.ServiceProcess;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. using Microsoft.Win32;
  12. namespace ame_integrity_check
  13. {
  14. public enum Type
  15. {
  16. File = 1,
  17. Directory = 2,
  18. Process = 3,
  19. Service = 4
  20. }
  21. internal class Scanner : IDisposable
  22. {
  23. private int result = 1;
  24. private bool allFound = true;
  25. private bool found = false;
  26. private bool errorOverride = false;
  27. public Task<bool> displayTask;
  28. public void Dispose() => GC.SuppressFinalize(this);
  29. public async Task<bool> DisplayQuery(string text, int time = 150)
  30. {
  31. Out.WriteCustomString(text, 3, 11);
  32. string maxSpaces = " ";
  33. for (int i = 1; i < 6; i++) {
  34. Console.SetCursorPosition(59, Console.CursorTop);
  35. var spaces = maxSpaces.Remove(0, i);
  36. Console.Write($"[ {spaces.PadLeft(spaces.Length + i, '*')} ]");
  37. Thread.Sleep(time);
  38. }
  39. return true;
  40. }
  41. private static void SetQueryStatus(string status, ConsoleColor color)
  42. {
  43. Console.SetCursorPosition(64 - status.Length, Console.CursorTop);
  44. Console.Write(" [ ");
  45. Out.WriteCustomString(status, 3, 0, foregroundColor: color);
  46. Console.WriteLine(" ]");
  47. }
  48. public async void Query(Type type, string item, bool finalize = false, bool modifyResult = true)
  49. {
  50. item = Environment.ExpandEnvironmentVariables(item);
  51. bool foundItem = false;
  52. try {
  53. switch (type) {
  54. case Type.File:
  55. if (item.Contains("*"))
  56. {
  57. var lastToken = item.LastIndexOf("\\");
  58. var parentPath = item.Remove(lastToken).TrimEnd('\\');
  59. if (parentPath.Contains("*")) throw new ArgumentException("Parent directories to a given file filter cannot contain wildcards.");
  60. var filter = item.Substring(lastToken + 1);
  61. foundItem = Directory.GetFiles(parentPath, filter).Any();
  62. break;
  63. }
  64. foundItem = File.Exists(item);
  65. break;
  66. case Type.Directory:
  67. if (item.Contains("*"))
  68. {
  69. var lastToken = item.LastIndexOf("\\");
  70. var parentPath = item.Remove(lastToken).TrimEnd('\\');
  71. if (parentPath.Contains("*")) throw new ArgumentException("Parent directories to a given file filter cannot contain wildcards.");
  72. var filter = item.Substring(lastToken + 1);
  73. foundItem = Directory.GetDirectories(parentPath, filter).Any();
  74. break;
  75. }
  76. foundItem = Directory.Exists(item);
  77. break;
  78. case Type.Process:
  79. foundItem = Process.GetProcessesByName(item).Any();
  80. break;
  81. case Type.Service:
  82. foundItem = ServiceController.GetServices().Any(x => x.ServiceName.Equals("wuauserv", StringComparison.CurrentCultureIgnoreCase));
  83. break;
  84. default:
  85. foundItem = false;
  86. break;
  87. }
  88. } catch (Exception e) {
  89. errorOverride = true;
  90. }
  91. if (foundItem) found = true;
  92. if (!finalize) return;
  93. await displayTask;
  94. if (errorOverride) {
  95. errorOverride = false;
  96. SetQueryStatus("ERROR", ConsoleColor.DarkRed);
  97. found = false;
  98. return;
  99. }
  100. if (!found) {
  101. if (modifyResult) allFound = false;
  102. SetQueryStatus("Absent", ConsoleColor.Green);
  103. } else {
  104. result = 2;
  105. if (allFound) result = 3;
  106. SetQueryStatus("Present", ConsoleColor.DarkRed);
  107. }
  108. found = false;
  109. }
  110. public void DisplayResult()
  111. {
  112. switch (result) {
  113. case 1:
  114. Out.WriteCustomString("\n\nAME Integrity validated", 1, foregroundColor: ConsoleColor.Green);
  115. break;
  116. case 2:
  117. Out.WriteCustomString("\n\nAME integrity compromised, contact the team for help.", 1, foregroundColor: ConsoleColor.Red);
  118. break;
  119. case 3:
  120. Out.WriteCustomString("\n\nYour system is not ameliorated.", 1, foregroundColor: ConsoleColor.Red);
  121. break;
  122. }
  123. }
  124. }
  125. internal static class Program
  126. {
  127. public static string PreviousTitle;
  128. public static int PreviousBufferHeight;
  129. public static int PreviousBufferWidth;
  130. public static int PreviousSizeHeight;
  131. public static int PreviousSizeWidth;
  132. public const double Ver = 0.9;
  133. public static void Main(string[] args)
  134. {
  135. PreviousSizeHeight = Console.WindowHeight;
  136. PreviousSizeWidth = Console.WindowWidth;
  137. PreviousBufferHeight = Console.BufferHeight;
  138. PreviousBufferWidth = Console.BufferWidth;
  139. Console.SetWindowSize(80, 26);
  140. Console.SetBufferSize(80, 26);
  141. Console.SetWindowSize(80, 26);
  142. Console.Clear();
  143. Console.CursorVisible = false;
  144. PreviousTitle = Console.Title;
  145. Console.Title = "AME Integrity Check";
  146. try { Out.DisableResize(); } catch (Exception) { }
  147. try { Out.DisableQuickEdit(); } catch (Exception) { }
  148. Console.CancelKeyPress += Exit;
  149. Out.WriteCustomString("\n__________________________________________________________" +
  150. $"\n\n| AME Integrity Check v{Ver} |\n\n", 1);
  151. displayStart:
  152. Menu mainMenu = new Menu() {
  153. Choices = {"Check AME Integrity", "Get Support", "", "Exit"},
  154. EndString = "\n__________________________________________________________\n",
  155. Statement = "Use the arrows keys to navigate"
  156. };
  157. var choice = mainMenu.Load();
  158. switch (choice) {
  159. case 0:
  160. RunCheck();
  161. Out.ResetPane();
  162. goto displayStart;
  163. case 1:
  164. Process.Start("https://t.me/joinchat/CR-xFBGQKVt7HPZKgZfbxg");
  165. Out.ResetPane();
  166. goto displayStart;
  167. case 2:
  168. PrepProcessExit();
  169. Environment.Exit(0);
  170. break;
  171. default:
  172. PrepProcessExit();
  173. Environment.Exit(1);
  174. break;
  175. }
  176. }
  177. private static bool detected = false;
  178. private static int result = 1;
  179. private static void RunCheck()
  180. {
  181. Out.ResetPane();
  182. bool legacy = false;
  183. var registryKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
  184. int winVer = 1;
  185. if (registryKey != null) winVer = Int32.Parse(registryKey.GetValue("CurrentBuildNumber").ToString());
  186. if (winVer < 19044) legacy = true;
  187. using (var scanner = new Scanner())
  188. {
  189. scanner.displayTask = scanner.DisplayQuery("Checking for Windows Defender activity...", 250);
  190. scanner.Query(Type.Process, "MsMpEng", true);
  191. scanner.displayTask = scanner.DisplayQuery("Checking Windows Defender files...", 200);
  192. if (!legacy) {
  193. scanner.Query(Type.Directory, "%ProgramFiles%\\Windows Defender");
  194. scanner.Query(Type.Directory, "%ProgramData%\\Microsoft\\Windows Defender", true);
  195. }
  196. else scanner.Query(Type.Directory, "%ProgramFiles%\\Windows Defender", true);
  197. if (!legacy) {
  198. scanner.displayTask = scanner.DisplayQuery("Checking Windows Update service...", 350);
  199. scanner.Query(Type.Service, "wuauserv", true);
  200. }
  201. scanner.displayTask = scanner.DisplayQuery("Checking Windows Update files...", 220);
  202. scanner.Query(Type.File, "%WINDIR%\\System32\\wuaueng.dll");
  203. scanner.Query(Type.File, "%WINDIR%\\System32\\wuapi.dll", true);
  204. scanner.displayTask = scanner.DisplayQuery("Checking Microsoft Edge...", 200);
  205. scanner.Query(Type.Directory, "%ProgramFiles(x86)%\\Microsoft\\EdgeCore");
  206. scanner.Query(Type.Directory, "%WINDIR%\\SystemApps\\*MicrosoftEdge*", true);
  207. scanner.displayTask = scanner.DisplayQuery("Checking for Microsoft Store activity...", 200);
  208. scanner.Query(Type.Process, "WinStore.App", true, false);
  209. scanner.displayTask = scanner.DisplayQuery("Checking Windows SmartScreen...");
  210. scanner.Query(Type.Process, "smartscreen");
  211. scanner.Query(Type.File, "%WINDIR%\\System32\\smartscreen.exe", true);
  212. scanner.displayTask = scanner.DisplayQuery("Checking SIH Client...");
  213. scanner.Query(Type.File, "%WINDIR%\\System32\\SIHClient.exe", true);
  214. scanner.displayTask = scanner.DisplayQuery("Checking Storage Sense...", 300);
  215. scanner.Query(Type.File, "%WINDIR%\\System32\\StorSvc.dll", true);
  216. scanner.DisplayResult();
  217. }
  218. Out.WriteCustomString("__________________________________________________________\n\n\nPress any key to return to the Menu: ", 3, 11);
  219. ClearBuffer();
  220. Console.CursorVisible = true;
  221. Console.ReadKey(false);
  222. Console.CursorVisible = false;
  223. }
  224. private static bool anyNotPresent;
  225. private static void ClearBuffer()
  226. {
  227. var posCacheTop = Console.CursorTop;
  228. var posCacheLeft = Console.CursorLeft;
  229. while (Console.KeyAvailable) {
  230. Console.ReadKey(false);
  231. }
  232. Console.SetCursorPosition(posCacheLeft, posCacheTop);
  233. Console.Write("".PadLeft(Console.WindowHeight, ' '));
  234. Console.SetCursorPosition(posCacheLeft, posCacheTop);
  235. }
  236. private static void Exit(object sender, ConsoleCancelEventArgs args)
  237. {
  238. PrepProcessExit();
  239. Environment.Exit(0);
  240. }
  241. private static void PrepProcessExit()
  242. {
  243. var parent = ParentProcess.ProcessName;
  244. if (parent.Equals("Explorer", StringComparison.CurrentCultureIgnoreCase)) return;
  245. try { Out.EnableResize(); } catch (Exception) { }
  246. try { Out.EnableQuickEdit(); } catch (Exception) { }
  247. Console.CursorVisible = true;
  248. Console.Clear();
  249. Console.Title = PreviousTitle;
  250. Console.SetWindowSize(PreviousSizeWidth, PreviousSizeHeight);
  251. Console.SetBufferSize(PreviousBufferWidth, PreviousBufferHeight);
  252. }
  253. }
  254. internal static class Out
  255. {
  256. public static void ResetPane(int fromTop = 6)
  257. {
  258. Console.SetCursorPosition(Console.CursorLeft, fromTop - 1);
  259. var length = Console.WindowHeight - fromTop - 1;
  260. for (int i = 0; i < length; i++) {
  261. Console.Write("".PadRight(Console.WindowWidth, ' '));
  262. }
  263. Console.SetCursorPosition(0, fromTop);
  264. }
  265. public static void WriteCustomString(string text, int type, int offset = 11, ConsoleColor foregroundColor = ConsoleColor.DarkYellow, ConsoleColor backgroundColor = ConsoleColor.DarkYellow)
  266. {
  267. bool resetColor = false;
  268. ConsoleColor foregroundCache = Console.ForegroundColor;
  269. ConsoleColor backgroundCache = Console.BackgroundColor;
  270. if (foregroundColor == ConsoleColor.DarkYellow) {
  271. foregroundColor = Console.ForegroundColor;
  272. }
  273. if (backgroundColor == ConsoleColor.DarkYellow) {
  274. backgroundColor = Console.BackgroundColor;
  275. }
  276. if (Console.ForegroundColor != foregroundColor) {
  277. resetColor = true;
  278. Console.ForegroundColor = foregroundColor;
  279. }
  280. if (Console.BackgroundColor != backgroundColor) {
  281. resetColor = true;
  282. Console.BackgroundColor = backgroundColor;
  283. }
  284. switch (type) {
  285. case 1:
  286. // Indented and centered
  287. Console.WriteLine(CenterString(text, offset));
  288. break;
  289. case 2:
  290. Console.WriteLine(text.Insert(0, new string(' ', offset)));
  291. break;
  292. case 3:
  293. var loopOnce = false;
  294. foreach (string line in text.Split('\n')) {
  295. if (line == "") {
  296. Console.WriteLine();
  297. continue;
  298. }
  299. Console.Write(line.Insert(0, new string(' ', offset)));
  300. }
  301. break;
  302. default:
  303. break;
  304. }
  305. if (resetColor) {
  306. Console.ForegroundColor = foregroundCache;
  307. Console.BackgroundColor = backgroundCache;
  308. }
  309. }
  310. private static string CenterString(string text, int offset = 11, int width = 58)
  311. {
  312. StringBuilder subLines = new StringBuilder();
  313. string newLine = "";
  314. foreach (string line in text.Split('\n')) {
  315. if (!subLines.ToString().Equals("")) newLine = "\n";
  316. if (line == "" && !subLines.ToString().Equals("")) {
  317. subLines.Append("\n");
  318. continue;
  319. }
  320. var space = "";
  321. if (!(line.Length % 2).Equals(0) && line.Length != width) {
  322. space = " ";
  323. }
  324. if (line.Length > width) {
  325. for (int index = 0; index < line.Length; index += (width - 10)) {
  326. if (!subLines.ToString().Equals("")) newLine = "\n";
  327. var subLine = line.Substring(index, Math.Min(width - 10, line.Length - index));
  328. subLine = subLine.Trim(' ');
  329. var subCentered = CenterString(subLine, offset, width);
  330. subLines.Append(newLine + subCentered);
  331. }
  332. continue;
  333. }
  334. var leadingLength = (width - line.Length) / 2;
  335. subLines.Append(newLine + space + line.PadLeft(line.Length + leadingLength, ' ').Insert(0, new string(' ', offset)));
  336. }
  337. return subLines.ToString();
  338. }
  339. private const int MF_BYCOMMAND = 0x00000000;
  340. public const int SC_CLOSE = 0xF060;
  341. public const int SC_MINIMIZE = 0xF020;
  342. public const int SC_MAXIMIZE = 0xF030;
  343. public const int SC_SIZE = 0xF000;//resize
  344. [DllImport("user32.dll")]
  345. public static extern int DeleteMenu(IntPtr hMenu, int nPosition, int wFlags);
  346. [DllImport("user32.dll")]
  347. private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
  348. [DllImport("kernel32.dll", ExactSpelling = true)]
  349. private static extern IntPtr GetConsoleWindow();
  350. public static void DisableResize()
  351. {
  352. IntPtr handle = GetConsoleWindow();
  353. IntPtr sysMenu = GetSystemMenu(handle, false);
  354. if (handle != IntPtr.Zero)
  355. {
  356. //DeleteMenu(sysMenu, SC_CLOSE, MF_BYCOMMAND);
  357. //DeleteMenu(sysMenu, SC_MINIMIZE, MF_BYCOMMAND);
  358. DeleteMenu(sysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
  359. DeleteMenu(sysMenu, SC_SIZE, MF_BYCOMMAND);//resize
  360. }
  361. }
  362. public static void EnableResize()
  363. {
  364. IntPtr handle = GetConsoleWindow();
  365. GetSystemMenu(handle, true);
  366. }
  367. const uint CHECK_QUICK_EDIT = 0x0040;
  368. const int ENABLE_QUICK_EDIT = 0x40 | 0x80;
  369. // STD_INPUT_HANDLE (DWORD): -10 is the standard input device.
  370. const int STD_INPUT_HANDLE = -10;
  371. [DllImport("kernel32.dll", SetLastError = true)]
  372. static extern IntPtr GetStdHandle(int nStdHandle);
  373. [DllImport("kernel32.dll")]
  374. static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
  375. [DllImport("kernel32.dll")]
  376. static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
  377. internal static void DisableQuickEdit() {
  378. IntPtr consoleHandle = GetStdHandle(STD_INPUT_HANDLE);
  379. // get current console mode
  380. uint consoleMode;
  381. GetConsoleMode(consoleHandle, out consoleMode);
  382. // set the new mode
  383. SetConsoleMode(consoleHandle, consoleMode &= ~CHECK_QUICK_EDIT);
  384. }
  385. internal static void EnableQuickEdit() {
  386. IntPtr consoleHandle = GetStdHandle(STD_INPUT_HANDLE);
  387. // get current console mode
  388. uint consoleMode;
  389. GetConsoleMode(consoleHandle, out consoleMode);
  390. // set the new mode
  391. SetConsoleMode(consoleHandle, consoleMode|(ENABLE_QUICK_EDIT));
  392. }
  393. }
  394. internal class Menu
  395. {
  396. public List<string> Choices;
  397. public string EndString;
  398. public string Statement;
  399. public int Offset;
  400. public Menu(int offset = 16, string endString = null)
  401. {
  402. Choices = new List<string>();
  403. EndString = endString;
  404. Offset = offset;
  405. }
  406. public int Load()
  407. {
  408. int max = -1;
  409. var posCache = Console.CursorTop;
  410. bool loopedOnce = false;
  411. foreach (string choice in Choices) {
  412. Console.SetCursorPosition(Offset - 2, Console.CursorTop);
  413. if (!loopedOnce) {
  414. Out.WriteCustomString("> " + choice, 2, 0, foregroundColor: ConsoleColor.Green);
  415. loopedOnce = true;
  416. } else {
  417. Out.WriteCustomString(choice, 2, 2);
  418. }
  419. max += 1;
  420. }
  421. if (EndString != null) Out.WriteCustomString(EndString, 1);
  422. if (Statement != null) Out.WriteCustomString(Statement, 2);
  423. int index = 0;
  424. ConsoleKey keyPressed;
  425. Console.SetCursorPosition(Offset, posCache);
  426. while ((keyPressed = Console.ReadKey(true).Key) != ConsoleKey.Enter) {
  427. if (keyPressed == ConsoleKey.DownArrow) {
  428. if (index >= max) continue;
  429. Console.SetCursorPosition(Offset - 2, Console.CursorTop);
  430. Out.WriteCustomString(Choices[index], 3, 2);
  431. if (!String.IsNullOrEmpty(Choices[index + 1])) {
  432. index += 1;
  433. Console.SetCursorPosition(Offset - 2, Console.CursorTop + 1);
  434. Out.WriteCustomString("> " + Choices[index], 3, 0, foregroundColor: ConsoleColor.Green);
  435. } else {
  436. index += 2;
  437. Console.SetCursorPosition(Offset - 2, Console.CursorTop + 2);
  438. Out.WriteCustomString("> " + Choices[index], 3, 0, foregroundColor: ConsoleColor.Green);
  439. }
  440. }
  441. if (keyPressed == ConsoleKey.UpArrow) {
  442. if (!(index > 0)) continue;
  443. Console.SetCursorPosition(Offset - 2, Console.CursorTop);
  444. Out.WriteCustomString(Choices[index], 3, 2);
  445. if (!String.IsNullOrEmpty(Choices[index - 1])) {
  446. index -= 1;
  447. Console.SetCursorPosition(Offset - 2, Console.CursorTop - 1);
  448. Out.WriteCustomString("> " + Choices[index], 3, 0, foregroundColor: ConsoleColor.Green);
  449. } else {
  450. index -= 2;
  451. Console.SetCursorPosition(Offset - 2, Console.CursorTop - 2);
  452. Out.WriteCustomString("> " + Choices[index], 3, 0, foregroundColor: ConsoleColor.Green);
  453. }
  454. }
  455. }
  456. return index;
  457. }
  458. }
  459. public static class ParentProcess
  460. {
  461. public static string ProcessName
  462. {
  463. get { return GetParentProcess().ProcessName; }
  464. }
  465. private static Process GetParentProcess()
  466. {
  467. int iParentPid = 0;
  468. int iCurrentPid = Process.GetCurrentProcess().Id;
  469. IntPtr oHnd = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  470. if (oHnd == IntPtr.Zero)
  471. return null;
  472. PROCESSENTRY32 oProcInfo = new PROCESSENTRY32();
  473. oProcInfo.dwSize =
  474. (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(PROCESSENTRY32));
  475. if (Process32First(oHnd, ref oProcInfo) == false)
  476. return null;
  477. do
  478. {
  479. if (iCurrentPid == oProcInfo.th32ProcessID)
  480. iParentPid = (int)oProcInfo.th32ParentProcessID;
  481. }
  482. while (iParentPid == 0 && Process32Next(oHnd, ref oProcInfo));
  483. if (iParentPid > 0)
  484. return Process.GetProcessById(iParentPid);
  485. else
  486. return null;
  487. }
  488. static uint TH32CS_SNAPPROCESS = 2;
  489. [StructLayout(LayoutKind.Sequential)]
  490. public struct PROCESSENTRY32
  491. {
  492. public uint dwSize;
  493. public uint cntUsage;
  494. public uint th32ProcessID;
  495. public IntPtr th32DefaultHeapID;
  496. public uint th32ModuleID;
  497. public uint cntThreads;
  498. public uint th32ParentProcessID;
  499. public int pcPriClassBase;
  500. public uint dwFlags;
  501. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
  502. public string szExeFile;
  503. };
  504. [DllImport("kernel32.dll", SetLastError = true)]
  505. static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID);
  506. [DllImport("kernel32.dll")]
  507. static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
  508. [DllImport("kernel32.dll")]
  509. static extern bool Process32Next(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
  510. }
  511. }