From 8e3b009195559733aee8a2217319b7ca4e8590d1 Mon Sep 17 00:00:00 2001 From: he3als Date: Tue, 12 Mar 2024 23:22:14 +0000 Subject: [PATCH] feat: deameliorate function --- src/Actions/Deameliorate.cs | 192 +++++++++++++++++++++++++++++++++ src/Misc/SelectWindowsImage.cs | 33 +++--- src/Program.cs | 25 +---- src/amecs.csproj | 1 + 4 files changed, 213 insertions(+), 38 deletions(-) create mode 100644 src/Actions/Deameliorate.cs diff --git a/src/Actions/Deameliorate.cs b/src/Actions/Deameliorate.cs new file mode 100644 index 0000000..9050412 --- /dev/null +++ b/src/Actions/Deameliorate.cs @@ -0,0 +1,192 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Security.Principal; +using System.Threading; +using amecs.Misc; +using Ameliorated.ConsoleUtils; +using Microsoft.Win32; + +namespace amecs.Actions +{ + public class Deameliorate + { + private static string _mountedPath; + private static string _winVer; + + public static bool DeAme() + { + if (new ChoicePrompt() + { + Text = @" +This will de-ameliorate by reinstalling Windows. + +Although user data should be kept, we strongly recommend +making backups of any important user data. + +Continue? (Y/N): " + }.Start().Value == 2) return true; + + Program.Frame.Clear(); + (_mountedPath, _, _winVer, _, _) = SelectWindowsImage.GetMediaPath(); + if (_mountedPath == null) return false; + + if (new ChoicePrompt {Text = $"\r\nYour Windows image is {_winVer}. Continue? (Y/N): "}.Start().Value == 2) + return true; + + var fc = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Yellow; + + string userSid = null; + try + { + NSudo.GetSystemPrivilege(); + NSudo.RunAsUser(() => + { + userSid = WindowsIdentity.GetCurrent().User.ToString(); + }); + } + catch + { + // do nothing + } + + try + { + ConsoleTUI.OpenFrame.WriteCentered("\r\nUninstalling AME-installed UI software..."); + + string openShellId = null; + + var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"); + foreach (var item in key.GetSubKeyNames()) + { + try + { + if (((string)key.OpenSubKey(item).GetValue("DisplayName")).Equals("Open-Shell")) + { + openShellId = item; + } + } + catch + { + // do nothing + } + } + + if (openShellId != null) + { + ConsoleTUI.OpenFrame.WriteCentered("\r\nUninstalling Open-Shell..."); + + var proc = Process.Start("MsiExec.exe", $"/X{openShellId} /quiet"); + proc.WaitForExit(); + + if (userSid != null) + { + var appData = (string)Registry.Users.OpenSubKey(userSid + @"\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders").GetValue("AppData"); + + if (Directory.Exists(Path.Combine(appData, "OpenShell"))) + Directory.Delete(Path.Combine(appData, "OpenShell"), true); + } + } + + var epSetupPath = $@"{Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)}\ExplorerPatcher\ep_setup.exe"; + if (File.Exists(epSetupPath)) + { + ConsoleTUI.OpenFrame.WriteCentered("\r\nUninstalling ExplorerPatcher, you'll need to click the prompts..."); + + var proc = Process.Start(epSetupPath, $"/uninstall"); + proc.WaitForExit(); + } + + Program.Frame.Clear(); + } catch (Exception e) + { + ConsoleTUI.OpenFrame.Close( + "Error when uninstalling software: " + e.Message, + ConsoleColor.Red, Console.BackgroundColor, + new ChoicePrompt { AnyKey = true, Text = "Press any key to continue anyways: " }); + + Program.Frame.Clear(); + ConsoleTUI.OpenFrame.WriteCentered("\r\nContinuing without uninstalling software...\r\n"); + } + + // ExplorerPatcher re-opens Explorer as SYSTEM after uninstalling, so it has to be restarted + // no silent uninstall is available, so user has to manually click 'Yes' to uninstall + // https://github.com/valinet/ExplorerPatcher/discussions/2007 + Thread.Sleep(500); + var winlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true); + winlogon.SetValue("AutoRestartShell", 0); + foreach (var exp in Process.GetProcessesByName("explorer")) + { + exp.Kill(); + } + winlogon.SetValue("AutoRestartShell", 1); + NSudo.RunProcessAsUser(NSudo.GetUserToken(), "explorer.exe", "", 0); + + // all policies are cleared as a user that's de-ameliorating is unlikely + // to have their own policies in the first place + ConsoleTUI.OpenFrame.WriteCentered("\r\nClearing policies..."); + foreach (var keyPath in new[] { + $@"HKU\{userSid}\Software\Microsoft\Windows\CurrentVersion\Policies", + $@"HKU\{userSid}\Software\Policies", + @"HKLM\Software\Microsoft\Windows\CurrentVersion\Policies", + @"HKLM\Software\Policies", + @"HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Policies" + }) + { + var hive = RegistryHive.LocalMachine; + if (keyPath.StartsWith("HKU")) + hive = RegistryHive.Users; + + var baseKey = RegistryKey.OpenBaseKey(hive, RegistryView.Default); + var subKeyPath = keyPath.Substring(keyPath.IndexOf('\\') + 1); + var key = baseKey.OpenSubKey(subKeyPath, true); + if (key == null) continue; + + try + { + baseKey.DeleteSubKeyTree(subKeyPath); + } + catch + { + // do nothing - some values might fail, but almost all are deleted + } + + key.Close(); + } + + Console.ReadKey(); + Program.Frame.Clear(); + ConsoleTUI.OpenFrame.WriteCentered("\r\nCompleted initial setup!", ConsoleColor.Green); + ConsoleTUI.OpenFrame.WriteCentered("\r\nWindows Setup will display as 'Windows Server,' but it's not actually installing Windows Server and is only set as such to bypass hardware requirements."); + + Console.WriteLine(); + ConsoleTUI.OpenFrame.WriteCentered("\r\nWaiting 10 seconds and starting..."); + + Console.ForegroundColor = fc; + Thread.Sleep(10000); + + Console.WriteLine(); + try + { + Process.Start(Path.Combine(_mountedPath, "setup.exe"), "/Auto Upgrade /DynamicUpdate Disable /Product Server"); + } catch (Exception e) + { + ConsoleTUI.OpenFrame.Close( + $"There was an error when trying to run the Windows Setup: {e}\r\nTry running the Windows Setup manually from File Explorer.", + ConsoleColor.Red, Console.BackgroundColor, + new ChoicePrompt { AnyKey = true, Text = $"Press any key to exit: " }); + + return false; + } + + ConsoleTUI.OpenFrame.Close( + "Completed, Windows Setup should have started.", + ConsoleColor.Cyan, Console.BackgroundColor, + new ChoicePrompt { AnyKey = true, Text = $"Press any key to go back: " }); + + return true; + } + } +} \ No newline at end of file diff --git a/src/Misc/SelectWindowsImage.cs b/src/Misc/SelectWindowsImage.cs index 4e27fef..a12c339 100644 --- a/src/Misc/SelectWindowsImage.cs +++ b/src/Misc/SelectWindowsImage.cs @@ -24,7 +24,7 @@ namespace amecs.Misc catch (SecurityException e) { Console.WriteLine(); - ConsoleTUI.OpenFrame.Close("Security exception: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); + ConsoleTUI.OpenFrame.Close("Security exception: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " }); return true; } @@ -80,7 +80,7 @@ namespace amecs.Misc { var error = ((string)null, "none", (string)null, (int?)null, (bool?)null); var choice = - new ChoicePrompt() { Text = "To continue, Windows installation media is needed.\r\nDo you have a Windows USB instead of an ISO file? (Y/N): " }.Start(); + new ChoicePrompt { Text = "To continue, Windows installation media is needed.\r\nDo you have a Windows USB instead of an ISO file? (Y/N): " }.Start(); if (!choice.HasValue) return error; // Folder/drive chosen @@ -103,7 +103,7 @@ namespace amecs.Misc { Console.WriteLine(); ConsoleTUI.OpenFrame.Close("\r\nYou must select a folder or drive containing Windows installation media.", - new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); + new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " }); return error; } } @@ -128,7 +128,7 @@ namespace amecs.Misc { Console.WriteLine(); ConsoleTUI.OpenFrame.Close("\r\nYou must select an ISO.", - new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); + new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " }); return error; } @@ -182,18 +182,18 @@ namespace amecs.Misc { case true when isoBuildMustBeReturned: ConsoleTUI.OpenFrame.Close( - $"Multiple Windows versions were found in the Windows image, can't determine which Windows build it is. Please use an unmodified Windows ISO.", + "Multiple Windows versions were found in the Windows image, can't determine which Windows build it is. Please use an unmodified Windows ISO.", ConsoleColor.Red, Console.BackgroundColor, - new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); + new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " }); return error; case true when winVersionsMustMatch: ConsoleTUI.OpenFrame.Close( - $"Multiple Windows versions were found in the Windows image, can't determine which Windows build it is. If your Windows version doesn't match the ISO, there will be problems.", + "Multiple Windows versions were found in the Windows image, can't determine which Windows build it is. If your Windows version doesn't match the ISO, there will be problems.", ConsoleColor.Red, Console.BackgroundColor, - new ChoicePrompt() { AnyKey = true, Text = "Press any key to continue anyways: " }); + new ChoicePrompt { AnyKey = true, Text = "Press any key to continue anyways: " }); Program.Frame.Clear(); - ConsoleTUI.OpenFrame.WriteCentered("\r\nContinuing without version check\r\n"); + ConsoleTUI.OpenFrame.WriteCentered("\r\nContinuing without version check...\r\n"); break; } @@ -207,7 +207,7 @@ namespace amecs.Misc ConsoleTUI.OpenFrame.Close( "Error checking ISO version: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, - new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); + new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " }); return error; } finally @@ -226,18 +226,19 @@ namespace amecs.Misc var hostVersion = Environment.OSVersion.Version; var hostWinver = GetWindowsVersion(float.Parse($"{hostVersion.Major}.{hostVersion.Minor}"), hostVersion.Build); - // If it all matches - if (hostWinver == _isoWinVer && winVersionsMustMatch) return (_mountedPath, _isoPath, _isoWinVer, _isoBuild, true); - // If ISO version doesn't match host version, and winVersionsMustMatch is true + // If it all matches & winVersionsMustMatch + if (hostWinver == _isoWinVer) return (_mountedPath, _isoPath, _isoWinVer, _isoBuild, true); + // If ISO version doesn't match host version & winVersionsMustMatch if (hostWinver != _isoWinVer && winVersionsMustMatch) { if (!string.IsNullOrEmpty(_isoPath)) DismountIso(_isoPath); ConsoleTUI.OpenFrame.Close( $"You're on {hostWinver}, but the selected image is {_isoWinVer}. You can only use an ISO that matches your Windows version.", ConsoleColor.Red, Console.BackgroundColor, - new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); + new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " }); return error; } + // If ISO version doesn't match host version, and winVersionsMustMatch is true if (hostWinver != _isoWinVer) return (_mountedPath, _isoPath, _isoWinVer, _isoBuild, false); } @@ -247,9 +248,9 @@ namespace amecs.Misc : "Press any key to continue anyways"; ConsoleTUI.OpenFrame.Close( - $"No Windows installation image was found inside the selected Windows media. No version check can be done, things might break.", + "No Windows installation image was found inside the selected Windows media. No version check can be done, things might break.", ConsoleColor.Red, Console.BackgroundColor, - new ChoicePrompt() { AnyKey = true, Text = $"{noWimText}: " }); + new ChoicePrompt { AnyKey = true, Text = $"{noWimText}: " }); Program.Frame.Clear(); ConsoleTUI.OpenFrame.WriteCentered("\r\nContinuing without version check\r\n"); diff --git a/src/Program.cs b/src/Program.cs index db070db..2bede50 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -1,9 +1,7 @@ using System; using System.DirectoryServices.AccountManagement; using System.Linq; -using System.Runtime.InteropServices; using System.Security.Principal; -using System.Threading.Tasks; using Ameliorated.ConsoleUtils; using Microsoft.Win32; using amecs.Actions; @@ -13,23 +11,6 @@ namespace amecs { internal class Program { - private static void RunAsUser(Action action) - { - var token = NSudo.GetUserToken(); - Task.Run((Action)Delegate.Combine((Action)(() => { NSudo.GetUserPrivilege(token); }), - action)).Wait(); - Marshal.FreeHGlobal(token); - } - - private static async Task RunAsUserAsync(Action action) - { - var token = NSudo.GetUserToken(); - await Task.Run((Action)Delegate.Combine((Action)(() => { NSudo.GetUserPrivilege(token); }), - action)); - Marshal.FreeHGlobal(token); - } - - private const string Ver = "2.1"; public static ConsoleTUI.Frame Frame; [STAThread] @@ -43,7 +24,7 @@ namespace amecs NSudo.GetSystemPrivilege(); if (!WindowsIdentity.GetCurrent().IsSystem) throw new Exception("Identity did not change."); - RunAsUser(() => + NSudo.RunAsUser(() => { Globals.Username = WindowsIdentity.GetCurrent().Name.Split('\\').Last(); Globals.UserDomain = WindowsIdentity.GetCurrent().Name.Split('\\').FirstOrDefault(); @@ -74,9 +55,8 @@ namespace amecs } Frame = new ConsoleTUI.Frame($"| Central AME Script v{Ver} |", false); - Frame.Open(); - + while (true) { Globals.UserElevated = Globals.User.IsMemberOf(Globals.Administrators); @@ -129,6 +109,7 @@ namespace amecs new Menu.MenuItem("Install .NET 3.5", new Func(_NET.Install)) : new Menu.MenuItem("Install .NET 3.5", new Func(_NET.Install)) {SecondaryText = "[Installed]", SecondaryTextForeground = ConsoleColor.Yellow, PrimaryTextForeground = ConsoleColor.DarkGray}, Menu.MenuItem.Blank, + new Menu.MenuItem("Uninstall AME", new Func(Deameliorate.DeAme)), new Menu.MenuItem("Extra", new Func(Extra.Extra.ShowMenu)), new Menu.MenuItem("Exit", new Func(Globals.Exit)) }, diff --git a/src/amecs.csproj b/src/amecs.csproj index 1cfcbd5..28a4d5f 100644 --- a/src/amecs.csproj +++ b/src/amecs.csproj @@ -188,6 +188,7 @@ +