using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Management; using System.Management.Automation; using System.Net.Http; using System.Reflection; using System.Runtime.InteropServices; using System.Security.Principal; using System.ServiceProcess; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Interop; using Microsoft.Win32; using TrustedUninstaller.Shared.Actions; namespace TrustedUninstaller.Shared { using SLID = Guid; //SLID id declared as typedef GUID SLID; in slpublic.h public static class WinUtil { public enum SHSTOCKICONID : uint { SIID_DOCNOASSOC = 0, SIID_DOCASSOC = 1, SIID_APPLICATION = 2, SIID_FOLDER = 3, SIID_FOLDEROPEN = 4, SIID_DRIVE525 = 5, SIID_DRIVE35 = 6, SIID_DRIVEREMOVE = 7, SIID_DRIVEFIXED = 8, SIID_DRIVENET = 9, SIID_DRIVENETDISABLED = 10, SIID_DRIVECD = 11, SIID_DRIVERAM = 12, SIID_WORLD = 13, SIID_SERVER = 15, SIID_PRINTER = 16, SIID_MYNETWORK = 17, SIID_FIND = 22, SIID_HELP = 23, SIID_SHARE = 28, SIID_LINK = 29, SIID_SLOWFILE = 30, SIID_RECYCLER = 31, SIID_RECYCLERFULL = 32, SIID_MEDIACDAUDIO = 40, SIID_LOCK = 47, SIID_AUTOLIST = 49, SIID_PRINTERNET = 50, SIID_SERVERSHARE = 51, SIID_PRINTERFAX = 52, SIID_PRINTERFAXNET = 53, SIID_PRINTERFILE = 54, SIID_STACK = 55, SIID_MEDIASVCD = 56, SIID_STUFFEDFOLDER = 57, SIID_DRIVEUNKNOWN = 58, SIID_DRIVEDVD = 59, SIID_MEDIADVD = 60, SIID_MEDIADVDRAM = 61, SIID_MEDIADVDRW = 62, SIID_MEDIADVDR = 63, SIID_MEDIADVDROM = 64, SIID_MEDIACDAUDIOPLUS = 65, SIID_MEDIACDRW = 66, SIID_MEDIACDR = 67, SIID_MEDIACDBURN = 68, SIID_MEDIABLANKCD = 69, SIID_MEDIACDROM = 70, SIID_AUDIOFILES = 71, SIID_IMAGEFILES = 72, SIID_VIDEOFILES = 73, SIID_MIXEDFILES = 74, SIID_FOLDERBACK = 75, SIID_FOLDERFRONT = 76, SIID_SHIELD = 77, SIID_WARNING = 78, SIID_INFO = 79, SIID_ERROR = 80, SIID_KEY = 81, SIID_SOFTWARE = 82, SIID_RENAME = 83, SIID_DELETE = 84, SIID_MEDIAAUDIODVD = 85, SIID_MEDIAMOVIEDVD = 86, SIID_MEDIAENHANCEDCD = 87, SIID_MEDIAENHANCEDDVD = 88, SIID_MEDIAHDDVD = 89, SIID_MEDIABLURAY = 90, SIID_MEDIAVCD = 91, SIID_MEDIADVDPLUSR = 92, SIID_MEDIADVDPLUSRW = 93, SIID_DESKTOPPC = 94, SIID_MOBILEPC = 95, SIID_USERS = 96, SIID_MEDIASMARTMEDIA = 97, SIID_MEDIACOMPACTFLASH = 98, SIID_DEVICECELLPHONE = 99, SIID_DEVICECAMERA = 100, SIID_DEVICEVIDEOCAMERA = 101, SIID_DEVICEAUDIOPLAYER = 102, SIID_NETWORKCONNECT = 103, SIID_INTERNET = 104, SIID_ZIPFILE = 105, SIID_SETTINGS = 106, SIID_DRIVEHDDVD = 132, SIID_DRIVEBD = 133, SIID_MEDIAHDDVDROM = 134, SIID_MEDIAHDDVDR = 135, SIID_MEDIAHDDVDRAM = 136, SIID_MEDIABDROM = 137, SIID_MEDIABDR = 138, SIID_MEDIABDRE = 139, SIID_CLUSTEREDDRIVE = 140, SIID_MAX_ICONS = 175 } [Flags] public enum SHGSI : uint { SHGSI_ICONLOCATION = 0, SHGSI_ICON = 0x000000100, SHGSI_SYSICONINDEX = 0x000004000, SHGSI_LINKOVERLAY = 0x000008000, SHGSI_SELECTED = 0x000010000, SHGSI_LARGEICON = 0x000000000, SHGSI_SMALLICON = 0x000000001, SHGSI_SHELLICONSIZE = 0x000000004 } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct SHSTOCKICONINFO { public UInt32 cbSize; public IntPtr hIcon; public Int32 iSysIconIndex; public Int32 iIcon; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260 /*MAX_PATH*/)] public string szPath; } [DllImport("Shell32.dll", SetLastError = false)] public static extern Int32 SHGetStockIconInfo(SHSTOCKICONID siid, SHGSI uFlags, ref SHSTOCKICONINFO psii); [DllImport("user32.dll", SetLastError = true)] public static extern bool DestroyIcon(IntPtr hIcon); public static bool IsAdministrator() { using var identity = WindowsIdentity.GetCurrent(); var principal = new WindowsPrincipal(identity); return principal.IsInRole(WindowsBuiltInRole.Administrator); } public static string GetUserName() { var wi = WindowsIdentity.GetCurrent(); var groups = from g in wi.Groups select new SecurityIdentifier(g.Value) .Translate(typeof(NTAccount)).Value; var msAccount = (from g in groups where g.StartsWith(@"MicrosoftAccount\") select g).FirstOrDefault(); return msAccount == null ? Environment.UserName : msAccount.Substring(@"MicrosoftAccount\".Length); } public static bool IsLocalAccount() { var wi = WindowsIdentity.GetCurrent(); var groups = from g in wi.Groups select new SecurityIdentifier(g.Value) .Translate(typeof(NTAccount)).Value; var msAccount = (from g in groups where g.StartsWith(@"MicrosoftAccount\") select g).FirstOrDefault(); return msAccount == null; } public enum SL_GENUINE_STATE { SL_GEN_STATE_IS_GENUINE = 0, // SL_GEN_STATE_INVALID_LICENSE = 1, // SL_GEN_STATE_TAMPERED = 2, SL_GEN_STATE_LAST = 3 } [DllImport("Slwga.dll", EntryPoint = "SLIsGenuineLocal", CharSet = CharSet.None, ExactSpelling = false, SetLastError = false, PreserveSig = true, CallingConvention = CallingConvention.Winapi, BestFitMapping = false, ThrowOnUnmappableChar = false)] [PreserveSigAttribute()] internal static extern uint SLIsGenuineLocal(ref SLID slid, [In, Out] ref SL_GENUINE_STATE genuineState, IntPtr val3); public static bool IsGenuineWindows() { // Microsoft-Windows-Security-SPP GUID // http://technet.microsoft.com/en-us/library/dd772270.aspx var windowsSlid = new SLID("55c92734-d682-4d71-983e-d6ec3f16059f"); var genuineState = SL_GENUINE_STATE.SL_GEN_STATE_LAST; var resultInt = SLIsGenuineLocal(ref windowsSlid, ref genuineState, IntPtr.Zero); #if DEBUG return true; #else return resultInt == 0 && genuineState == SL_GENUINE_STATE.SL_GEN_STATE_IS_GENUINE; #endif } private static IEnumerable GetWindowsGroups(WindowsIdentity id) { var irc = id.Groups ?? new IdentityReferenceCollection(); return irc.Select(ir => (NTAccount)ir.Translate(typeof(NTAccount))).Select(acc => acc.Value).ToList(); } public static bool HasWindowsGroup(string groupName) { var appDomain = Thread.GetDomain(); appDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal); var currentPrincipal = (WindowsPrincipal)Thread.CurrentPrincipal; var groups = GetWindowsGroups((WindowsIdentity)currentPrincipal.Identity); return groups.Any(group => group == groupName); } public static bool IsTrustedInstaller() { return HasWindowsGroup(@"NT SERVICE\TrustedInstaller"); } public static bool RelaunchAsTrustedInstaller() { var controller = new ServiceController("TrustedInstaller"); if (controller.Status != ServiceControllerStatus.Running) { controller.Start(); controller.WaitForStatus(ServiceControllerStatus.Running); } var targetProcess = Process.GetProcessesByName("TrustedInstaller").FirstOrDefault(); if (targetProcess == null) { return false; } var currentProcess = Process.GetCurrentProcess(); var currentModule = currentProcess.MainModule; if (currentModule == null) { return false; } var currentExecutable = currentModule.FileName; return NativeProcess.StartProcess(currentExecutable, targetProcess.Id, AmeliorationUtil.Playbook.Path); } [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern Boolean ChangeServiceConfig( IntPtr hService, UInt32 nServiceType, UInt32 nStartType, UInt32 nErrorControl, String lpBinaryPathName, String lpLoadOrderGroup, IntPtr lpdwTagId, [In] char[] lpDependencies, String lpServiceStartName, String lpPassword, String lpDisplayName); [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] static extern IntPtr OpenService( IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] public static extern IntPtr OpenSCManager( string machineName, string databaseName, uint dwAccess); [DllImport("advapi32.dll", EntryPoint = "CloseServiceHandle")] public static extern int CloseServiceHandle(IntPtr hSCObject); private const uint SERVICE_NO_CHANGE = 0xFFFFFFFF; private const uint SERVICE_QUERY_CONFIG = 0x00000001; private const uint SERVICE_CHANGE_CONFIG = 0x00000002; private const uint SC_MANAGER_ALL_ACCESS = 0x000F003F; public static void ChangeStartMode(ServiceController svc, ServiceStartMode mode) { var scManagerHandle = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS); if (scManagerHandle == IntPtr.Zero) { throw new ExternalException("Open Service Manager Error"); } var serviceHandle = OpenService( scManagerHandle, svc.ServiceName, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG); if (serviceHandle == IntPtr.Zero) { throw new ExternalException("Open Service Error"); } var result = ChangeServiceConfig( serviceHandle, SERVICE_NO_CHANGE, (uint)mode, SERVICE_NO_CHANGE, null, null, IntPtr.Zero, null, null, null, null); if (result == false) { var nError = Marshal.GetLastWin32Error(); var win32Exception = new Win32Exception(nError); throw new ExternalException("Could not change service start type: " + win32Exception.Message); } CloseServiceHandle(serviceHandle); CloseServiceHandle(scManagerHandle); } [StructLayout(LayoutKind.Sequential)] struct RM_UNIQUE_PROCESS { public int dwProcessId; public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime; } const int RmRebootReasonNone = 0; const int CCH_RM_MAX_APP_NAME = 255; const int CCH_RM_MAX_SVC_NAME = 63; enum RM_APP_TYPE { RmUnknownApp = 0, RmMainWindow = 1, RmOtherWindow = 2, RmService = 3, RmExplorer = 4, RmConsole = 5, RmCritical = 1000 } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct RM_PROCESS_INFO { public RM_UNIQUE_PROCESS Process; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_APP_NAME + 1)] public string strAppName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)] public string strServiceShortName; public RM_APP_TYPE ApplicationType; public uint AppStatus; public uint TSSessionId; [MarshalAs(UnmanagedType.Bool)] public bool bRestartable; } [DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)] static extern int RmRegisterResources(uint pSessionHandle, UInt32 nFiles, string[] rgsFilenames, UInt32 nApplications, [In] RM_UNIQUE_PROCESS[] rgApplications, UInt32 nServices, string[] rgsServiceNames); [DllImport("rstrtmgr.dll", CharSet = CharSet.Auto)] static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, string strSessionKey); [DllImport("rstrtmgr.dll")] static extern int RmEndSession(uint pSessionHandle); [DllImport("rstrtmgr.dll")] static extern int RmGetList(uint dwSessionHandle, out uint pnProcInfoNeeded, ref uint pnProcInfo, [In, Out] RM_PROCESS_INFO[] rgAffectedApps, ref uint lpdwRebootReasons); /// /// Find out what process(es) have a lock on the specified file. /// /// Path of the file. /// Processes locking the file /// See also: /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa373661(v=vs.85).aspx /// http://wyupdate.googlecode.com/svn-history/r401/trunk/frmFilesInUse.cs (no copyright in code at time of viewing) /// /// public static List WhoIsLocking(string path) { string key = Guid.NewGuid().ToString(); List processes = new List(); int res = RmStartSession(out uint handle, 0, key); if (res != 0) { ErrorLogger.WriteToErrorLog("Could not begin restart session. Unable to determine file locker.", Environment.StackTrace, $"Error while attempting to get locking processes of file {path}"); throw new Exception("Could not begin restart session. Unable to determine file locker."); } try { const int ERROR_MORE_DATA = 234; uint pnProcInfoNeeded = 0, pnProcInfo = 0, lpdwRebootReasons = RmRebootReasonNone; string[] resources = new string[] { path }; // Just checking on one resource. res = RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null); if (res != 0) throw new Exception("Could not register resource."); //Note: there's a race condition here -- the first call to RmGetList() returns // the total number of process. However, when we call RmGetList() again to get // the actual processes this number may have increased. res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons); if (res == ERROR_MORE_DATA) { // Create an array to store the process results RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded]; pnProcInfo = pnProcInfoNeeded; // Get the list res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons); if (res == 0) { processes = new List((int)pnProcInfo); // Enumerate all of the results and add them to the // list to be returned for (int i = 0; i < pnProcInfo; i++) { try { processes.Add(Process.GetProcessById(processInfo[i].Process.dwProcessId)); } // catch the error -- in case the process is no longer running catch (ArgumentException) { } } } else throw new Exception("Could not list processes locking resource."); } else if (res != 0) throw new Exception("Could not list processes locking resource. Could not get size of result." + $" Result value: {res}"); } finally { RmEndSession(handle); } return processes; } /// /// Finds active anti-viruses in the system. /// /// a list of ProviderStatus. /// See also: /// https://jdhitsolutions.com/blog/powershell/5187/get-antivirus-product-status-with-powershell/ /// https://docs.microsoft.com/en-us/windows/win32/api/iwscapi/ne-iwscapi-wsc_security_product_state?redirectedfrom=MSDN /// https://mspscripts.com/get-installed-antivirus-information-2/ /// https://social.msdn.microsoft.com/Forums/pt-BR/6501b87e-dda4-4838-93c3-244daa355d7c/wmisecuritycenter2-productstate?forum=vblanguage /// https://stackoverflow.com/questions/4700897/wmi-security-center-productstate-clarification/4711211 /// https://blogs.msdn.microsoft.com/alejacma/2008/05/12/how-to-get-antivirus-information-with-wmi-vbscript/#comment-442 /// https://www.magnumdb.com/search?q=parent:WSC_SECURITY_PRODUCT_STATE /// https://web.archive.org/web/20190121133247/http://neophob.com/2010/03/wmi-query-windows-securitycenter2/ /// public static List GetEnabledAvList(bool ensureWMI = true) { if (ensureWMI) { var svc = new ServiceController("Winmgmt"); ChangeStartMode(svc, ServiceStartMode.Automatic); } List avList = new List(); string computer = Environment.MachineName; string wmipath = @"\\" + computer + @"\root\SecurityCenter2"; string query = @"SELECT * FROM AntivirusProduct WHERE displayName != ""Windows Defender"""; try { using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmipath, query)) { ManagementObjectCollection results = searcher.Get(); foreach (var o in results) { // You can find if an AV is active or not by accessing the hex code of the productState // (from the right) 19th bit == Anti Virus is on // (from the right) 13th bit == On Access Scanning // 00000000 00000[1]10 000[1]0000 000[0]0000 // 19th bit (yes) = Av on // 13th bit (yes) = On Access Scanning // The third byte defines if the .dat file is up-to-date var result = (ManagementObject)o; var productState = result["productState"]; string hex = Hex(Convert.ToInt32(productState)); string bin = Binary(Convert.ToInt32(productState)); string reversed = Reverse(bin); var enabled = GetBit(reversed, 18); var scanning = GetBit(reversed, 12); var outdated = GetBit(reversed, 4); static string Binary(int value) { return Convert.ToString(value, 2).PadLeft(24, '0'); } static string Hex(int value) { return Convert.ToString(value, 16).PadLeft(6, '0'); } static bool GetBit(string value, int index) { return value.Substring(index, 1).Equals("1"); } static string Reverse(string value) { return new string(value.Reverse().ToArray()); } if (!enabled) continue; var av = new ProviderStatus() { DisplayName = result["displayName"].ToString(), AVStatus = enabled ? AVStatusFlags.Enabled : AVStatusFlags.Unknown, SecurityProvider = ProviderFlags.ANTIVIRUS, SignatureStatus = outdated ? SignatureStatusFlags.OutOfDate : SignatureStatusFlags.UpToDate }; avList.Add(av); } } } catch (Exception e) { ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "Error while retrieving the AV list."); } return avList; } //Checks if Visual C++ redistributable is installed. public static bool IsVCInstalled() { string dependenciesPath = @"SOFTWARE\Classes\Installer\Dependencies"; using (RegistryKey dependencies = Registry.LocalMachine.OpenSubKey(dependenciesPath)) { if (dependencies == null) return false; foreach (string subKeyName in dependencies.GetSubKeyNames().Where(n => !n.ToLower().Contains("dotnet") && !n.ToLower().Contains("microsoft"))) { using (RegistryKey subDir = Registry.LocalMachine.OpenSubKey(dependenciesPath + "\\" + subKeyName)) { var value = subDir.GetValue("DisplayName")?.ToString() ?? null; if (string.IsNullOrEmpty(value)) { continue; } if (Environment.Is64BitOperatingSystem) { if (Regex.IsMatch(value, @"C\+\+ 2015.*\((x64|x86)\)")) { return true; } } else { if (Regex.IsMatch(value, @"C\+\+ 2015.*\(x86\)")) { return true; } } } } } return false; } public static async Task RemoveProtectionAsync() { var cmdAction = new CmdAction(); if (!IsVCInstalled()) { Console.WriteLine(Environment.NewLine + "Installing VC 15..."); try { //Install Visual C++ 2015 redistributable package silently cmdAction.Command = "vc_redist.x64.exe /q /norestart"; await cmdAction.RunTask(); } catch (Exception e) { ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "Error while installing VC 15."); throw; } } try { Console.WriteLine(Environment.NewLine + "Installing driver..."); cmdAction.Command = Environment.Is64BitOperatingSystem ? $"ProcessHacker\\x64\\ProcessHacker.exe -s -installkph" : $"ProcessHacker\\x86\\ProcessHacker.exe -s -installkph"; var res = await cmdAction.RunTask(); } catch (Exception e) { ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "ProcessHacker ran into an error while installing its driver."); throw; } } private const int GWL_STYLE = -16; private const int WS_SYSMENU = 0x80000; [DllImport("user32.dll", SetLastError = true)] private static extern int GetWindowLong(IntPtr hWnd, int nIndex); [DllImport("user32.dll")] private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); //public static void RemoveCloseButton(Window window) //{ //var hwnd = new WindowInteropHelper(window).Handle; //SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU); //} public static bool IsVM() { try { using (var searcher = new System.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem")) { using (var items = searcher.Get()) { foreach (var item in items) { string manufacturer = item["Manufacturer"].ToString().ToLower(); if ((manufacturer == "microsoft corporation" && item["Model"].ToString().ToUpperInvariant().Contains("VIRTUAL")) || manufacturer.Contains("vmware") || item["Model"].ToString() == "VirtualBox") { return true; } } } } return false; } catch (Exception e) { ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "Error while checking if running system is a VM."); return false; } } public static void PrepareSystemCLI() { try { var defenderStop = new RunAction() { RawPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), Exe = $"NSudoLC.exe", Arguments = "-U:T -P:E -M:S -ShowWindowMode:Hide -Priority:RealTime -Wait cmd /c \"" + "sc sdset \"WinDefend\" \"D:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)(A;;CCLCSWRPLOCRRC;;;BA)(A;;CCLCSWRPLOCRRC;;;BU)(A;;CCLCSWRPLOCRRC;;;IU)(A;;CCLCSWRPLOCRRC;;;SU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-80-1913148863-3492339771-4165695881-2087618961-4109116736)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)\"&" + "sc config WinDefend start=disabled&" + "net stop WinDefend\"", CreateWindow = false, Timeout = 7500, }; defenderStop.RunTask().Wait(); } catch (Exception e) { } var defenderValues = new RunAction() { RawPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), Exe = $"NSudoLC.exe", Arguments = "-U:T -P:E -M:S -ShowWindowMode:Hide -Priority:RealTime -Wait cmd /c \"reg delete \"HKLM\\SOFTWARE\\Microsoft\\Windows Defender\" /v \"ProductAppDataPath\" /f &" + " reg delete \"HKLM\\SOFTWARE\\Microsoft\\Windows Defender\" /v \"InstallLocation\" /f\"", CreateWindow = false }; defenderValues.RunTask().Wait(); var defenderKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows Defender"); if (defenderKey != null && defenderKey.GetValueNames().Contains("InstallLocation")) { throw new Exception("Could not remove defender install values."); } var defenderService = new RunAction() { RawPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), Exe = $"NSudoLC.exe", Arguments = "-U:T -P:E -M:S -ShowWindowMode:Hide -Priority:RealTime -Wait reg delete \"HKLM\\SYSTEM\\CurrentControlSet\\Services\\WinDefend\" /f", CreateWindow = false }; defenderService.RunTask().Wait(); if (Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Services\\WinDefend") != null) { throw new Exception("Could not remove WinDefend service."); } // MpOAV.dll normally in use by a lot of processes. This prevents that. var MpOAVCLSID = new RunAction() { RawPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), Exe = $"NSudoLC.exe", Arguments = @"-U:T -P:E -M:S -Priority:RealTime -ShowWindowMode:Hide -Wait reg delete ""HKCR\CLSID\{2781761E-28E0-4109-99FE-B9D127C57AFE}\InprocServer32"" /f", CreateWindow = false }; MpOAVCLSID.RunTask().Wait(); if (Registry.ClassesRoot.OpenSubKey(@"CLSID\{2781761E-28E0-4109-99FE-B9D127C57AFE}\InprocServer32") != null) { throw new Exception("Could not remove MpOAV mapping."); } // Can cause ProcessHacker driver warnings without this AmeliorationUtil.SafeRunAction(new RegistryValueAction() { KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity", Value = "Enabled", Data = 0, }).Wait(); AmeliorationUtil.SafeRunAction(new RegistryValueAction() { KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\CI\Config", Value = "VulnerableDriverBlocklistEnable", Data = 0, }).Wait(); } public static async Task UninstallDriver() { CmdAction cmdAction = new CmdAction(); try { Console.WriteLine("Removing driver..."); cmdAction.Command = Environment.Is64BitOperatingSystem ? $"ProcessHacker\\x64\\ProcessHacker.exe -s -uninstallkph" : $"ProcessHacker\\x86\\ProcessHacker.exe -s -uninstallkph"; await cmdAction.RunTask(); } catch (Exception e) { ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "ProcessHacker ran into an Error while uninstalling the driver."); throw; } } public class RegistryManager { [DllImport("advapi32.dll", SetLastError = true)] static extern int RegLoadKey(IntPtr hKey, string lpSubKey, string lpFile); [DllImport("advapi32.dll", SetLastError = true)] static extern int RegSaveKey(IntPtr hKey, string lpFile, uint securityAttrPtr = 0); [DllImport("advapi32.dll", SetLastError = true)] static extern int RegUnLoadKey(IntPtr hKey, string lpSubKey); [DllImport("ntdll.dll", SetLastError = true)] static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege, out bool PreviousValue); [DllImport("advapi32.dll")] static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref UInt64 lpLuid); [DllImport("advapi32.dll")] static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpName, ref UInt64 lpLuid); public static void LoadFromFile(string path, bool classHive = false) { var parentKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default); string name; if (path.Contains("Users\\Default\\")) name = classHive ? "AME_UserHive_Default_Classes" : "AME_UserHive_Default"; else name = classHive ? "AME_UserHive_" + (HivesLoaded + 1) + "_Classes" : "AME_UserHive_" + (HivesLoaded + 1); IntPtr parentHandle = parentKey.Handle.DangerousGetHandle(); RegLoadKey(parentHandle, name, path); HivesLoaded++; } private static void AcquirePrivileges() { ulong luid = 0; bool throwaway; LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid); RtlAdjustPrivilege((int)luid, true, false, out throwaway); LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid); RtlAdjustPrivilege((int)luid, true, false, out throwaway); } private static void ReturnPrivileges() { ulong luid = 0; bool throwaway; LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid); RtlAdjustPrivilege((int)luid, false, false, out throwaway); LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid); RtlAdjustPrivilege((int)luid, false, false, out throwaway); } private static bool HivesHooked; private static int HivesLoaded; public static async void HookUserHives() { try { if (HivesHooked || WinUtil.IsTrustedInstaller() || RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default).GetSubKeyNames().Any(x => x.StartsWith("AME_UserHive_"))) return; HivesHooked = true; var usersDir = Environment.GetEnvironmentVariable("SYSTEMDRIVE") + "\\Users"; var ignoreList = new List() { "Default User", "Public", "All Users" }; var userDirs = Directory.GetDirectories(usersDir).Where(x => !ignoreList.Contains(x.Split('\\').Last())).ToList(); var userKeys = Registry.Users.GetSubKeyNames().Where(x => x.StartsWith("S-")); foreach (var userKey in userKeys) { try { var userEnv = Registry.Users.OpenSubKey(userKey).OpenSubKey("Volatile Environment"); userDirs.Remove((string)userEnv.GetValue("USERPROFILE")); } catch (Exception) { } } if (userDirs.Any()) AcquirePrivileges(); foreach (var userDir in userDirs) { if (!File.Exists($"{userDir}\\NTUSER.DAT")) { ErrorLogger.WriteToErrorLog($"NTUSER.DAT file not found in user folder '{userDir}'.", Environment.StackTrace, $"Error attempting to load user registry hive."); continue; } LoadFromFile($"{userDir}\\NTUSER.DAT"); if (userDir.EndsWith("\\Default")) { try { if (!Directory.Exists($@"{userDir}\AppData\Local\Microsoft\Windows")) Directory.CreateDirectory($@"{userDir}\AppData\Local\Microsoft\Windows"); var fs = File.Create($@"{userDir}\AppData\Local\Microsoft\Windows" + @"\UsrClass.dat"); var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("TrustedUninstaller.Shared.Properties.UsrClass.dat"); resource.CopyTo(fs); fs.Close(); } catch (Exception e) { ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, $"Failed to create default user class hive.", userDir); } } if (!File.Exists($@"{userDir}\AppData\Local\Microsoft\Windows\UsrClass.dat")) { ErrorLogger.WriteToErrorLog($@"UsrClass.dat file not found in user appdata folder '{userDir}\AppData\Local\Microsoft\Windows'.", Environment.StackTrace, $"Error attempting to load user classes registry hive."); continue; } LoadFromFile($@"{userDir}\AppData\Local\Microsoft\Windows\UsrClass.dat", true); } if (userDirs.Any()) ReturnPrivileges(); } catch (Exception e) { ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, $"Critical error while attempting to mount user hives."); Console.WriteLine(":AME-ERROR: Failure while mounting user registry hives."); } } public static async void UnhookUserHives() { try { var usersKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default); var userHives = usersKey.GetSubKeyNames().Where(x => x.StartsWith("AME_UserHive_")).ToList(); if (userHives.Any()) AcquirePrivileges(); foreach (var userHive in userHives) { RegUnLoadKey(usersKey.Handle.DangerousGetHandle(), userHive); } if (userHives.Any()) ReturnPrivileges(); usersKey.Close(); } catch (Exception e) { ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, $"Critical error while attempting to unmount user hives."); Console.WriteLine(":AME-ERROR: Failure while unmounting user registry hives."); } } } } }