@ -5,6 +5,7 @@ using System.IO;
using System.Linq ;
using System.Reflection ;
using System.Text ;
using System.Threading ;
using System.Threading.Tasks ;
using System.Windows ;
using Microsoft.Win32 ;
@ -22,6 +23,11 @@ namespace TrustedUninstaller.CLI
//After the auto start up.
Directory . SetCurrentDirectory ( AppDomain . CurrentDomain . BaseDirectory ) ;
if ( args . Length = = 1 & & args [ 0 ] = = "-DisableDefender" )
{
return DisableDefender ( ) ;
}
DualOut . Init ( ) ;
if ( ! WinUtil . IsAdministrator ( ) )
@ -44,19 +50,19 @@ namespace TrustedUninstaller.CLI
Console . WriteLine ( "No Playbook selected." ) ;
return - 1 ;
}
AmeliorationUtil . Playbook = await AmeliorationUtil . DeserializePlaybook ( args [ 0 ] ) ;
if ( ! Directory . Exists ( $"{AmeliorationUtil.Playbook.Path}\\Configuration" ) | | Directory . GetFiles ( $"{AmeliorationUtil.Playbook.Path}\\Configuration" ) . Length = = 0 )
{
Console . WriteLine ( "Configuration folder is empty, put YAML files in it and restart the application." ) ;
Console . WriteLine ( $"Current directory: {Directory.GetCurrentDirectory()}" ) ;
return - 1 ;
}
ExtractResourceFolder ( "resources" , Directory . GetCurrentDirectory ( ) ) ;
if ( ! WinUtil . IsTrustedInstaller ( ) )
{
Console . WriteLine ( "Checking requirements...\r\n" ) ;
@ -64,7 +70,7 @@ namespace TrustedUninstaller.CLI
{
Console . WriteLine ( "Internet must be connected to run this Playbook." ) ;
}
if ( AmeliorationUtil . Playbook . Requirements . Contains ( Requirements . Requirement . DefenderDisabled ) & & Process . GetProcessesByName ( "MsMpEng" ) . Any ( ) )
{
bool first = true ;
@ -74,9 +80,9 @@ namespace TrustedUninstaller.CLI
Console . WriteLine ( "All 4 windows security toggles must be set to off.\r\nNavigate to Windows Security > Virus & threat detection > manage settings.\r\nPress any key to continue..." ) ;
Console . ReadKey ( ) ;
}
bool remnantsOnly = Requirements . DefenderDisabled . RemnantsOnly ( ) ;
Console . WriteLine ( remnantsOnly ? "The system must be prepared before continuing.\r\nPress any key to continue..." : "The system must be prepared before continuing. Your system will restart after preparation\r\nPress any key to continue..." ) ;
Console . ReadKey ( ) ;
try
@ -103,8 +109,8 @@ namespace TrustedUninstaller.CLI
Console . WriteLine ( "Error preparing system: " + e . Message ) ;
Environment . Exit ( - 1 ) ;
}
}
if ( AmeliorationUtil . Playbook . Requirements . Contains ( Requirements . Requirement . Internet ) & & ! await ( new Requirements . Internet ( ) ) . IsMet ( ) )
{
Console . WriteLine ( "Internet must be connected to run this Playbook." ) ;
@ -136,6 +142,30 @@ namespace TrustedUninstaller.CLI
AmeliorationUtil . Playbook . Options = defaultOptions ;
}
if ( ! AmeliorationUtil . Playbook . UseKernelDriver . HasValue )
{
if ( new RegistryValueAction ( )
{
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity" ,
Value = "Enabled" ,
Data = 1 ,
} . GetStatus ( )
! = UninstallTaskStatus . Completed
& &
new RegistryValueAction ( )
{
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\CI\Config" ,
Value = "VulnerableDriverBlocklistEnable" ,
Data = 0 ,
} . GetStatus ( )
= = UninstallTaskStatus . Completed & & ( await GetDefenderToggles ( ) ) . All ( toggleOn = > ! toggleOn ) )
{
AmeliorationUtil . UseKernelDriver = true ;
}
}
else
AmeliorationUtil . UseKernelDriver = AmeliorationUtil . Playbook . UseKernelDriver . Value ;
try
{
if ( ! Directory . Exists ( Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "ame-assassin" ) ) )
@ -144,31 +174,34 @@ namespace TrustedUninstaller.CLI
ExtractResourceFolder ( "resources" , Directory . GetCurrentDirectory ( ) ) ;
ExtractArchive ( Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "CLI-Resources.7z" ) , AppDomain . CurrentDomain . BaseDirectory ) ;
if ( AmeliorationUtil . UseKernelDriver ) ExtractArchive ( Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "ProcessInformer.7z" ) , AppDomain . CurrentDomain . BaseDirectory ) ;
try
{
File . Delete ( Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "CLI-Resources.7z" ) ) ;
File . Delete ( Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "ProcessInformer.7z" ) ) ;
} catch ( Exception e )
{
}
catch ( Exception e ) { }
}
}
catch ( Exception e )
} catch ( Exception e )
{
ErrorLogger . WriteToErrorLog ( e . Message ,
e . StackTrace , "Error extracting resources." ) ;
Console . WriteLine ( $":AME-Fatal Error: Error extracting resources." ) ;
return - 1 ;
}
await AmeliorationUtil . StartAmelioration ( ) ;
return 0 ;
}
public static void ExtractArchive ( string file , string targetDir )
{
RunCommand ( $"x \" { file } \ " -o\"{targetDir}\" -p\"wizard\" -y -aos" ) ;
}
private static void RunCommand ( string command )
{
var proc = new Process ( ) ;
@ -181,15 +214,15 @@ namespace TrustedUninstaller.CLI
FileName = Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "7za.exe" ) ,
RedirectStandardError = true ,
} ;
proc . StartInfo = startInfo ;
proc . Start ( ) ;
StringBuilder errorOutput = new StringBuilder ( "" ) ;
proc . ErrorDataReceived + = ( sender , args ) = > { errorOutput . Append ( "\r\n" + args . Data ) ; } ;
proc . BeginErrorReadLine ( ) ;
proc . WaitForExit ( ) ;
proc . CancelErrorRead ( ) ;
@ -199,7 +232,8 @@ namespace TrustedUninstaller.CLI
if ( proc . ExitCode > 1 )
throw new ArgumentOutOfRangeException ( "Error running 7zip: " + errorOutput . ToString ( ) ) ;
}
public static void ExtractResourceFolder ( string resource , string dir , bool overwrite = false )
public static void ExtractResourceFolder ( string resource , string dir , bool overwrite = false )
{
if ( ! Directory . Exists ( dir ) ) Directory . CreateDirectory ( dir ) ;
@ -216,7 +250,7 @@ namespace TrustedUninstaller.CLI
var file = dir + $"\\{obj.Substring($" TrustedUninstaller . CLI . Properties . { resource } . ".Length).Replace(" - - - ", " \ \ ")}" ;
if ( file . EndsWith ( ".gitkeep" ) ) continue ;
var fileDir = Path . GetDirectoryName ( file ) ;
if ( fileDir ! = null & & ! Directory . Exists ( fileDir ) ) Directory . CreateDirectory ( fileDir ) ;
@ -226,8 +260,7 @@ namespace TrustedUninstaller.CLI
try
{
File . Delete ( file ) ;
}
catch ( Exception e )
} catch ( Exception e )
{
if ( ! Directory . Exists ( Directory . GetCurrentDirectory ( ) + "\\Logs" ) )
Directory . CreateDirectory ( Directory . GetCurrentDirectory ( ) + "\\Logs" ) ;
@ -237,6 +270,7 @@ namespace TrustedUninstaller.CLI
writer . WriteLine ( "\r\nDate/Time: " + DateTime . Now ) ;
writer . WriteLine ( "============================================" ) ;
}
continue ;
}
}
@ -264,7 +298,7 @@ namespace TrustedUninstaller.CLI
}
}
}
public static async Task < List < bool > > GetDefenderToggles ( )
{
var result = new List < bool > ( ) ;
@ -281,32 +315,31 @@ namespace TrustedUninstaller.CLI
try
{
realtimePolicy = policiesKey . OpenSubKey ( "Real-Time Protection" ) ;
} catch ( Exception e )
{
}
catch ( Exception e ) { }
if ( realtimePolicy ! = null )
realtimeKey = realtimePolicy ;
else
realtimeKey = defenderKey . OpenSubKey ( "Real-Time Protection" ) ;
}
catch
} catch
{
result . Add ( false ) ;
}
if ( realtimeKey ! = null )
{
try
{
result . Add ( ( int ) realtimeKey . GetValue ( "DisableRealtimeMonitoring" ) ! = 1 ) ;
}
catch ( Exception exception )
} catch ( Exception exception )
{
try
{
realtimeKey = defenderKey . OpenSubKey ( "Real-Time Protection" ) ;
result . Add ( ( int ) realtimeKey . GetValue ( "DisableRealtimeMonitoring" ) ! = 1 ) ;
}
catch ( Exception e )
} catch ( Exception e )
{
result . Add ( true ) ;
}
@ -317,12 +350,13 @@ namespace TrustedUninstaller.CLI
{
RegistryKey spynetPolicy = null ;
RegistryKey spynetKey = null ;
try
{
spynetPolicy = policiesKey . OpenSubKey ( "SpyNet" ) ;
} catch ( Exception e )
{
}
catch ( Exception e ) { }
if ( spynetPolicy ! = null )
spynetKey = spynetPolicy ;
@ -334,19 +368,18 @@ namespace TrustedUninstaller.CLI
try
{
reporting = ( int ) spynetKey . GetValue ( "SpyNetReporting" ) ;
}
catch ( Exception e )
} catch ( Exception e )
{
if ( spynetPolicy ! = null )
{
reporting = ( int ) defenderKey . OpenSubKey ( "SpyNet" ) . GetValue ( "SpyNetReporting" ) ;
}
}
try
{
consent = ( int ) spynetKey . GetValue ( "SubmitSamplesConsent" ) ;
}
catch ( Exception e )
} catch ( Exception e )
{
if ( spynetPolicy ! = null )
{
@ -356,131 +389,125 @@ namespace TrustedUninstaller.CLI
result . Add ( reporting ! = 0 ) ;
result . Add ( consent ! = 0 & & consent ! = 2 & & consent ! = 4 ) ;
}
catch
} catch
{
result . Add ( false ) ;
result . Add ( false ) ;
}
try
{
int tamper = ( int ) defenderKey . OpenSubKey ( "Features" ) . GetValue ( "TamperProtection" ) ;
result . Add ( tamper ! = 4 & & tamper ! = 0 ) ;
}
catch
} catch
{
result . Add ( false ) ;
}
} ) ;
return result ;
}
public static void PrepareSystemCLI ( )
private static int DisableDefender ( )
{
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 = 7 5 0 0 ,
} ;
defenderStop . RunTask ( ) . Wait ( ) ;
} catch ( Exception e )
{
Defender . Disable ( ) ;
}
var defenderValues = new RunAction ( )
catch ( Exception ex )
{
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 ( ) ;
ErrorLogger . WriteToErrorLog ( ex . GetType ( ) + ": " + ex . Message , ex . StackTrace ,
$"First Defender disable failed from second process." ) ;
Defender . Kill ( ) ;
try
{
Defender . Disable ( ) ;
}
catch ( Exception e )
{
ErrorLogger . WriteToErrorLog ( e . GetType ( ) + ": " + e . Message , e . StackTrace ,
$"Could not disable Windows Defender from second process." ) ;
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." ) ;
return 1 ;
}
}
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 )
return 0 ;
}
public static void PrepareSystemCLI ( )
{
try
{
var disableDefender = new RunAction ( )
if ( ! Defender . Kill ( ) )
{
RawPath = Path . GetDirectoryName ( Assembly . GetExecutingAssembly ( ) . Location ) ,
Exe = $"NSudoLC.exe" ,
Arguments = "-U:T -P:E -M:S -ShowWindowMode:Hide -Priority:RealTime -Wait reg add \"HKLM\\SYSTEM\\CurrentControlSet\\Services\\WinDefend\" /v \"Start\" /t REG_DWORD /d 4 /f" ,
CreateWindow = false
} ;
disableDefender . RunTask ( ) . Wait ( ) ;
if ( new RegistryValueAction ( ) { KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\WinDefend" , Value = "Start" , Data = 4 , Type = RegistryValueType . REG_DWORD } . GetStatus ( ) ! = UninstallTaskStatus . Completed )
throw new Exception ( "Could not disable WinDefend service." ) ;
}
ErrorLogger . WriteToErrorLog ( "Unknown reason" , null , "Could not kill Defender" ) ;
// 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 ( ) ;
try
{
var process = Defender . StartElevatedProcess ( Assembly . GetExecutingAssembly ( ) . Location , $@"-DisableDefender" ) ;
var exitCode = Defender . WaitForProcessExit ( process , 1 0 0 0 0 ) ;
if ( exitCode ! = 0 )
throw new Exception ( "Exit code was nonzero." ) ;
} catch ( Exception e )
{
ErrorLogger . WriteToErrorLog ( e . GetType ( ) + ": " + e . Message , e . StackTrace , "First Defender disable failed" ) ;
if ( Registry . ClassesRoot . OpenSubKey ( @"CLSID\{2781761E-28E0-4109-99FE-B9D127C57AFE}\InprocServer32" ) ! = null )
{
throw new Exception ( "Could not remove MpOAV mapping." ) ;
}
Thread . Sleep ( 1 0 0 0 ) ;
if ( ! Defender . Kill ( ) )
{
Thread . Sleep ( 3 0 0 0 ) ;
Defender . Kill ( ) ;
}
// 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 ( )
try
{
var process = Defender . StartElevatedProcess ( Assembly . GetExecutingAssembly ( ) . Location , $@"-DisableDefender" ) ;
var exitCode = Defender . WaitForProcessExit ( process , 1 0 0 0 0 ) ;
if ( exitCode ! = 0 )
throw new Exception ( "Exit code was nonzero." ) ;
} catch ( Exception exception )
{
ErrorLogger . WriteToErrorLog ( e . GetType ( ) + ": " + e . Message , e . StackTrace , "Second Defender disable failed" ) ;
Defender . Disable ( ) ;
}
}
}
else
{
try
{
var process = Defender . StartElevatedProcess ( Assembly . GetExecutingAssembly ( ) . Location , $@"-DisableDefender" ) ;
var exitCode = Defender . WaitForProcessExit ( process , 1 5 0 0 0 ) ;
if ( exitCode ! = 0 )
throw new Exception ( "Exit code was nonzero." ) ;
} catch ( Exception e )
{
ErrorLogger . WriteToErrorLog ( e . GetType ( ) + ": " + e . Message , e . StackTrace , "First Defender disable failed" ) ;
Defender . Disable ( ) ;
}
}
} catch
{
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 ;
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 ;
}
}
}
}
}
}