Browse Source

Update to v0.7.3

master 0.7.3
Styris 6 months ago
parent
commit
ddfdcccc04
34 changed files with 6797 additions and 379 deletions
  1. +26
    -0
      TrustedUninstaller.CLI/CLI.cs
  2. BIN
      TrustedUninstaller.CLI/Properties/resources/CLI-Resources.7z
  3. BIN
      TrustedUninstaller.CLI/Properties/resources/ProcessInformer.7z
  4. +16
    -27
      TrustedUninstaller.CLI/TrustedUninstaller.CLI.csproj
  5. +13
    -4
      TrustedUninstaller.Shared/Actions/AppxAction.cs
  6. +157
    -14
      TrustedUninstaller.Shared/Actions/CmdAction.cs
  7. +92
    -35
      TrustedUninstaller.Shared/Actions/FileAction.cs
  8. +3
    -1
      TrustedUninstaller.Shared/Actions/LanguageAction.cs
  9. +1
    -0
      TrustedUninstaller.Shared/Actions/LineInFileAction.cs
  10. +174
    -12
      TrustedUninstaller.Shared/Actions/PowershellAction.cs
  11. +1
    -0
      TrustedUninstaller.Shared/Actions/RegistryKeyAction.cs
  12. +1
    -0
      TrustedUninstaller.Shared/Actions/RegistryValueAction.cs
  13. +187
    -28
      TrustedUninstaller.Shared/Actions/RunAction.cs
  14. +1
    -0
      TrustedUninstaller.Shared/Actions/ScheduledTaskAction.cs
  15. +80
    -56
      TrustedUninstaller.Shared/Actions/ServiceAction.cs
  16. +1
    -0
      TrustedUninstaller.Shared/Actions/ShortcutAction.cs
  17. +4
    -1
      TrustedUninstaller.Shared/Actions/SystemPackageAction.cs
  18. +178
    -116
      TrustedUninstaller.Shared/Actions/TaskKillAction.cs
  19. +1
    -0
      TrustedUninstaller.Shared/Actions/UpdateAction.cs
  20. +1
    -0
      TrustedUninstaller.Shared/Actions/UserAction.cs
  21. +1
    -0
      TrustedUninstaller.Shared/Actions/WriteStatusAction.cs
  22. +143
    -26
      TrustedUninstaller.Shared/AmeliorationUtil.cs
  23. +3340
    -0
      TrustedUninstaller.Shared/AugmentedProcess.cs
  24. +22
    -0
      TrustedUninstaller.Shared/Debug.cs
  25. +34
    -14
      TrustedUninstaller.Shared/Defender.cs
  26. +21
    -6
      TrustedUninstaller.Shared/Globals.cs
  27. +2
    -1
      TrustedUninstaller.Shared/Playbook.cs
  28. +507
    -0
      TrustedUninstaller.Shared/ProcessPrivilege.cs
  29. +1
    -0
      TrustedUninstaller.Shared/Tasks/ITaskAction.cs
  30. +8
    -0
      TrustedUninstaller.Shared/Tasks/TaskAction.cs
  31. +9
    -0
      TrustedUninstaller.Shared/Tasks/UninstallTask.cs
  32. +21
    -13
      TrustedUninstaller.Shared/TrustedUninstaller.Shared.csproj
  33. +1699
    -0
      TrustedUninstaller.Shared/Win32.cs
  34. +52
    -25
      TrustedUninstaller.Shared/WinUtil.cs

+ 26
- 0
TrustedUninstaller.CLI/CLI.cs View File

@ -142,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")))
@ -150,9 +174,11 @@ 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)
{
}


BIN
TrustedUninstaller.CLI/Properties/resources/CLI-Resources.7z View File


BIN
TrustedUninstaller.CLI/Properties/resources/ProcessInformer.7z View File


+ 16
- 27
TrustedUninstaller.CLI/TrustedUninstaller.CLI.csproj View File

@ -70,6 +70,13 @@
<DebugType>embedded</DebugType>
<DefineConstants>SINGLE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug Single File|x64' ">
<OutputPath>bin\x64\Release\</OutputPath>
<PlatformTarget>x64</PlatformTarget>
<Optimize>true</Optimize>
<DebugType>embedded</DebugType>
<DefineConstants>SINGLE;DEBUG</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<ManifestCertificateThumbprint>B8F0A67800B779C5CEF49BEAB6E5247E373F9452</ManifestCertificateThumbprint>
</PropertyGroup>
@ -91,21 +98,19 @@
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Single File|x64' ">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Single File|x64' Or '$(Configuration)|$(Platform)' == 'Debug Single File|x64' ">
<PostBuildEvent>for /f "usebackq delims=" %%A in (`DIR /B /S /A:d "$(SolutionDir)" ^| FINDSTR /R /c:".*\\bin\\.*\\de$" /c:".*\\bin\\.*\\en$" /c:".*\\bin\\.*\\es$" /c:".*\\bin\\.*\\fr$" /c:".*\\bin\\.*\\it$" /c:".*\\bin\\.*\\ja$" /c:".*\\bin\\.*\\ko$" /c:".*\\bin\\.*\\ru$" /c:".*\\bin\\.*\\zh-Hans$" /c:".*\\bin\\.*\\zh-Hant$" /c:".*\\bin\\.*\\pl$" /c:".*\\bin\\.*\\zh-CN$"`) do (RMDIR /Q /S "%%A" &amp; cmd /c "exit /b 0")
cmd /c "echo Compiled&gt; "$(SolutionDir)\TrustedUninstaller.GUI\gui-builder\Compiled.txt""</PostBuildEvent>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Single File|x64' ">
<PreBuildEvent>PowerShell -NoP -C "Get-Process 'ame-builder' -EA SilentlyContinue | Wait-Process -EA SilentlyContinue; EXIT 0"
PowerShell -NoP -C "Start-Process '$(SolutionDir)\TrustedUninstaller.GUI\gui-builder\ame-builder.exe' -ArgumentList 'CLI' -WindowStyle Hidden"
</PreBuildEvent>
PowerShell -NoP -C "Start-Process '$(SolutionDir)\TrustedUninstaller.GUI\gui-builder\ame-builder.exe' -ArgumentList 'CLI','""""x64\$(Configuration)""""' -NoNewWindow -Wait"
</PostBuildEvent>
<AllowedReferenceRelatedFileExtensions>
<!-- Prevent default XML files copied to output.-->
.allowedextension
</AllowedReferenceRelatedFileExtensions>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' != 'Single File|x64' ">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' != 'Single File|x64' And '$(Configuration)|$(Platform)' != 'Debug Single File|x64' ">
<PostBuildEvent>for /f "usebackq delims=" %%A in (`DIR /B /S /A:d "$(SolutionDir)" ^| FINDSTR /R /c:".*\\bin\\.*\\de$" /c:".*\\bin\\.*\\en$" /c:".*\\bin\\.*\\es$" /c:".*\\bin\\.*\\fr$" /c:".*\\bin\\.*\\it$" /c:".*\\bin\\.*\\ja$" /c:".*\\bin\\.*\\ko$" /c:".*\\bin\\.*\\ru$" /c:".*\\bin\\.*\\zh-Hans$" /c:".*\\bin\\.*\\zh-Hant$" /c:".*\\bin\\.*\\pl$" /c:".*\\bin\\.*\\zh-CN$"`) do (RMDIR /Q /S "%%A" &amp; cmd /c "exit /b 0")</PostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Build" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
@ -113,16 +118,6 @@
<SpecificVersion>False</SpecificVersion>
<Private>False</Private>
</Reference>
<Reference Include="System.Management" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Numerics" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CLI.cs" />
@ -150,18 +145,12 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="6.0.0" />
<PackageReference Include="Microsoft.PowerShell.5.ReferenceAssemblies" Version="1.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
<PackageReference Include="SQLitePCLRaw.core" Version="2.0.7" />
<PackageReference Include="System.Buffers" Version="4.5.1" />
<PackageReference Include="System.CodeDom" Version="6.0.0" />
<PackageReference Include="System.IO.Compression" Version="4.0.0" />
<PackageReference Include="System.Management" Version="6.0.0" />
<PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
<PackageReference Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" />
<PackageReference Include="System.Security.Principal.Windows" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
@ -171,7 +160,7 @@
<EmbeddedResource Include="Properties\resources\CLI-Resources.7z" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\resources\NSudoLC.exe" />
<EmbeddedResource Include="Properties\resources\ProcessInformer.7z" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

+ 13
- 4
TrustedUninstaller.Shared/Actions/AppxAction.cs View File

@ -16,6 +16,8 @@ namespace TrustedUninstaller.Shared.Actions
// Integrate ame-assassin later
internal class AppxAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
public enum AppxOperation
{
Remove = 0,
@ -39,6 +41,9 @@ namespace TrustedUninstaller.Shared.Actions
[YamlMember(typeof(bool), Alias = "verboseOutput")]
public bool Verbose { get; set; } = false;
[YamlMember(typeof(bool), Alias = "unregister")]
public bool Unregister { get; set; } = false;
[YamlMember(typeof(string), Alias = "weight")]
public int ProgressWeight { get; set; } = 30;
public int GetProgressWeight() => ProgressWeight;
@ -69,14 +74,18 @@ namespace TrustedUninstaller.Shared.Actions
InProgress = true;
Console.WriteLine($"Removing APPX {Type.ToString().ToLower()} '{Name}'...");
WinUtil.CheckKph();
string verboseArg = Verbose ? " -Verbose" : "";
string unregisterArg = Unregister ? " -Verbose" : "";
string kernelDriverArg = AmeliorationUtil.UseKernelDriver ? " -UseKernelDriver" : "";
var psi = new ProcessStartInfo()
{
UseShellExecute = false,
CreateNoWindow = true,
Arguments = $@"-{Type.ToString()} ""{Name}""" + verboseArg,
Arguments = $@"-{Type.ToString()} ""{Name}""" + verboseArg + unregisterArg + kernelDriverArg,
FileName = Directory.GetCurrentDirectory() + "\\ame-assassin\\ame-assassin.exe",
RedirectStandardOutput = true,
RedirectStandardError = true
@ -98,7 +107,7 @@ namespace TrustedUninstaller.Shared.Actions
bool exited = proc.WaitForExit(30000);
// WaitForExit alone seems to not be entirely reliable
while (!exited && ExeRunning(proc))
while (!exited && ExeRunning("ame-assassin", proc.Id))
{
exited = proc.WaitForExit(30000);
}
@ -121,11 +130,11 @@ namespace TrustedUninstaller.Shared.Actions
if (!write.Equals("Complete!")) Console.WriteLine(write);
}
private static bool ExeRunning(Process process)
private static bool ExeRunning(string name, int id)
{
try
{
return Process.GetProcessesByName(process.ProcessName).Any(x => x.Id == process.Id);
return Process.GetProcessesByName(name).Any(x => x.Id == id);
}
catch (Exception)
{


+ 157
- 14
TrustedUninstaller.Shared/Actions/CmdAction.cs View File

@ -1,7 +1,9 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using TrustedUninstaller.Shared.Exceptions;
using TrustedUninstaller.Shared.Tasks;
@ -11,6 +13,25 @@ namespace TrustedUninstaller.Shared.Actions
{
public class CmdAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread()
{
if (InProgress) throw new TaskInProgressException("Another Cmd action was called while one was in progress.");
InProgress = true;
Console.WriteLine($"Running cmd command '{Command}'...");
ExitCode = null;
if (RunAs == Privilege.TrustedInstaller)
RunAsProcess();
else
RunAsPrivilegedProcess();
InProgress = false;
}
[YamlMember(typeof(Privilege), Alias = "runas")]
public Privilege RunAs { get; set; } = Privilege.TrustedInstaller;
[YamlMember(typeof(string), Alias = "command")]
public string Command { get; set; }
@ -48,21 +69,20 @@ namespace TrustedUninstaller.Shared.Actions
return ExitCode == null ? UninstallTaskStatus.ToDo: UninstallTaskStatus.Completed;
}
public async Task<bool> RunTask()
public Task<bool> RunTask()
{
if (InProgress) throw new TaskInProgressException("Another Cmd action was called while one was in progress.");
InProgress = true;
Console.WriteLine($"Running cmd command '{Command}'...");
ExitCode = null;
return null;
}
private void RunAsProcess()
{
var process = new Process();
var startInfo = new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Normal,
FileName = "cmd.exe",
Arguments = "/C " + $"\"{Environment.ExpandEnvironmentVariables(this.Command)}\"",
Arguments = "/C " + $"\"{this.Command}\"",
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
@ -83,7 +103,7 @@ namespace TrustedUninstaller.Shared.Actions
if (!Wait)
{
process.Dispose();
return true;
return;
}
var error = new StringBuilder();
@ -97,6 +117,114 @@ namespace TrustedUninstaller.Shared.Actions
};
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if (Timeout != null)
{
var exited = process.WaitForExit(Timeout.Value);
if (!exited)
{
process.Kill();
throw new TimeoutException($"Command '{Command}' timeout exceeded.");
}
}
else
{
bool exited = process.WaitForExit(30000);
// WaitForExit alone seems to not be entirely reliable
while (!exited && CmdRunning(process.Id))
{
exited = process.WaitForExit(30000);
}
}
int exitCode = 0;
try
{
exitCode = process.ExitCode;
}
catch (Exception ex)
{
ErrorLogger.WriteToErrorLog("Error fetching process exit code. (1)", null, "CmdAction Error", Command);
}
if (exitCode != 0)
{
StandardError = error.ToString();
Console.WriteLine($"cmd instance exited with error code: {exitCode}");
if (!String.IsNullOrEmpty(StandardError)) Console.WriteLine($"Error message: {StandardError}");
ErrorLogger.WriteToErrorLog("Cmd exited with a non-zero exit code: " + exitCode, null, "CmdAction Error", Command);
this.ExitCode = exitCode;
}
else
{
ExitCode = 0;
}
process.CancelOutputRead();
process.CancelErrorRead();
process.Dispose();
}
private static bool CmdRunning(int id)
{
try
{
return Process.GetProcessesByName("cmd").Any(x => x.Id == id);
}
catch (Exception)
{
return false;
}
}
private void RunAsPrivilegedProcess()
{
var process = new AugmentedProcess.Process();
var startInfo = new AugmentedProcess.ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Normal,
FileName = "cmd.exe",
Arguments = "/C " + $"\"{Environment.ExpandEnvironmentVariables(this.Command)}\"",
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
CreateNoWindow = true
};
if (ExeDir) startInfo.WorkingDirectory = AmeliorationUtil.Playbook.Path + "\\Executables";
if (!Wait)
{
startInfo.RedirectStandardError = false;
startInfo.RedirectStandardOutput = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.UseShellExecute = true;
}
process.StartInfo = startInfo;
ProcessPrivilege.StartPrivilegedTask(process, RunAs);
if (!Wait)
{
process.Dispose();
return;
}
var error = new StringBuilder();
process.OutputDataReceived += PrivilegedProcOutputHandler;
process.ErrorDataReceived += delegate(object sender, AugmentedProcess.DataReceivedEventArgs args)
{
if (!String.IsNullOrEmpty(args.Data))
error.AppendLine(args.Data);
else
error.AppendLine();
};
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if (Timeout != null)
{
@ -127,14 +255,29 @@ namespace TrustedUninstaller.Shared.Actions
}
process.CancelOutputRead();
process.CancelErrorRead();
process.Dispose();
InProgress = false;
return true;
}
private void PrivilegedProcOutputHandler(object sendingProcess, AugmentedProcess.DataReceivedEventArgs outLine)
{
var outputString = outLine.Data;
private static void ProcOutputHandler(object sendingProcess,
DataReceivedEventArgs outLine)
// Collect the sort command output.
if (!String.IsNullOrEmpty(outLine.Data))
{
if (outputString.Contains("\\AME"))
{
outputString = outputString.Substring(outputString.IndexOf('>') + 1);
}
Console.WriteLine(outputString);
}
else
{
Console.WriteLine();
}
}
private void ProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
var outputString = outLine.Data;


+ 92
- 35
TrustedUninstaller.Shared/Actions/FileAction.cs View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Configuration.Install;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -9,6 +10,7 @@ using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.ServiceProcess;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using TrustedUninstaller.Shared.Exceptions;
@ -19,6 +21,7 @@ namespace TrustedUninstaller.Shared.Actions
{
public class FileAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(typeof(string), Alias = "path")]
public string RawPath { get; set; }
@ -81,13 +84,14 @@ namespace TrustedUninstaller.Shared.Actions
{
if (!TrustedInstaller)
{
try {await Task.Run(() => File.Delete(file));} catch {}
try { File.Delete(file);} catch (Exception e) { }
if (File.Exists(file))
{
try
{
EzUnlockFileW(file);
var result = EzUnlockFileW(file);
Testing.WriteLine($"ExUnlock on ({file}) result: " + result);
}
catch (Exception e)
{
@ -95,20 +99,21 @@ namespace TrustedUninstaller.Shared.Actions
$"FileAction Error", file);
}
try {await Task.Run(() => File.Delete(file));} catch {}
try {await Task.Run(() => File.Delete(file));} catch (Exception e) {Testing.WriteLine(e, "DeleteFile > File.Delete(File)");}
CmdAction delAction = new CmdAction()
{
Command = $"del /q /f \"{file}\""
};
await delAction.RunTask();
delAction.RunTaskOnMainThread();
}
}
else if (File.Exists("NSudoLC.exe"))
{
try
{
EzUnlockFileW(file);
var result = EzUnlockFileW(file);
Testing.WriteLine($"ExUnlock on ({file}) result: " + result);
}
catch (Exception e)
{
@ -123,7 +128,7 @@ namespace TrustedUninstaller.Shared.Actions
CreateWindow = false
};
await tiDelAction.RunTask();
tiDelAction.RunTaskOnMainThread();
if (tiDelAction.Output != null)
{
if (log) ErrorLogger.WriteToErrorLog(tiDelAction.Output, Environment.StackTrace,
@ -149,7 +154,7 @@ namespace TrustedUninstaller.Shared.Actions
{
Command = $"rmdir /Q /S \"{dir}\""
};
await deleteDirCmd.RunTask();
deleteDirCmd.RunTaskOnMainThread();
if (deleteDirCmd.StandardError != null)
{
@ -171,7 +176,7 @@ namespace TrustedUninstaller.Shared.Actions
CreateWindow = false
};
await tiDelAction.RunTask();
tiDelAction.RunTaskOnMainThread();
if (tiDelAction.Output != null)
{
@ -216,15 +221,28 @@ namespace TrustedUninstaller.Shared.Actions
var cmdAction = new CmdAction();
Console.WriteLine($"Removing driver service {driverService}...");
// TODO: Replace with win32
try
{
ServiceInstaller ServiceInstallerObj = new ServiceInstaller();
ServiceInstallerObj.Context = new InstallContext();
ServiceInstallerObj.ServiceName = driverService;
ServiceInstallerObj.Uninstall(null);
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Service uninstall failed: " + e.Message, e.StackTrace, "FileAction Warning", RawPath);
}
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction stop" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction stop";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction delete" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction delete";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
}
catch (Exception servException)
{
@ -270,16 +288,19 @@ namespace TrustedUninstaller.Shared.Actions
{
try
{
using var search = new ManagementObjectSearcher($"select * from Win32_Service where ProcessId = '{svchost.Id}'");
foreach (ManagementObject queryObj in search.Get())
foreach (var serviceName in Win32.ServiceEx.GetServicesFromProcessId(svchost.Id))
{
var serviceName = (string)queryObj["Name"]; // Access service name
var serv = ServiceController.GetServices().FirstOrDefault(x => x.ServiceName.Equals(serviceName));
if (serv == null) svcCount++;
else svcCount += serv.DependentServices.Length + 1;
svcCount++;
try
{
var serviceController = ServiceController.GetServices().FirstOrDefault(x => x.ServiceName.Equals(serviceName));
if (serviceController != null)
svcCount += serviceController.DependentServices.Length;
}
catch (Exception e)
{
Console.WriteLine($"\r\nError: Could not get amount of dependent services for {serviceName}.\r\nException: " + e.Message);
}
}
} catch (Exception e)
{
@ -328,7 +349,15 @@ namespace TrustedUninstaller.Shared.Actions
continue;
}
await taskKillAction.RunTask();
try
{
await taskKillAction.RunTask();
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace,
$"FileAction Error: Could not kill process {taskKillAction.ProcessName}.");
}
}
// This gives any obstinant processes some time to unlock the file on their own.
@ -352,6 +381,11 @@ namespace TrustedUninstaller.Shared.Actions
if (delay >= 800)
ErrorLogger.WriteToErrorLog($"Could not kill locking processes for file '{file}'. Process termination loop exceeded max cycles (8).",
Environment.StackTrace, "FileAction Error");
if (Path.GetExtension(file).Equals(".exe", StringComparison.OrdinalIgnoreCase))
{
await new TaskKillAction() { ProcessName = Path.GetFileNameWithoutExtension(file) }.RunTask();
}
await DeleteFile(file, true);
@ -419,7 +453,7 @@ namespace TrustedUninstaller.Shared.Actions
};
try
{
await permAction.RunTask();
permAction.RunTaskOnMainThread();
}
catch (Exception e)
{
@ -466,7 +500,7 @@ namespace TrustedUninstaller.Shared.Actions
}
}
}
else if (isFile)
if (isFile)
{
try
{
@ -486,7 +520,7 @@ namespace TrustedUninstaller.Shared.Actions
};
try
{
await permAction.RunTask();
permAction.RunTaskOnMainThread();
}
catch (Exception e)
{
@ -504,15 +538,30 @@ namespace TrustedUninstaller.Shared.Actions
var cmdAction = new CmdAction();
Console.WriteLine($"Removing driver service {driverService}...");
// TODO: Replace with win32
try
{
ServiceInstaller ServiceInstallerObj = new ServiceInstaller();
ServiceInstallerObj.Context = new InstallContext();
ServiceInstallerObj.ServiceName = driverService;
ServiceInstallerObj.Uninstall(null);
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Service uninstall failed: " + e.Message, e.StackTrace, "FileAction Warning", RawPath);
}
WinUtil.CheckKph();
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction stop" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction stop";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction delete" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {driverService} -caction delete";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
}
catch (Exception servException)
{
@ -558,16 +607,19 @@ namespace TrustedUninstaller.Shared.Actions
{
try
{
using var search = new ManagementObjectSearcher($"select * from Win32_Service where ProcessId = '{svchost.Id}'");
foreach (ManagementObject queryObj in search.Get())
foreach (var serviceName in Win32.ServiceEx.GetServicesFromProcessId(svchost.Id))
{
var serviceName = (string)queryObj["Name"]; // Access service name
var serv = ServiceController.GetServices().FirstOrDefault(x => x.ServiceName.Equals(serviceName));
if (serv == null) svcCount++;
else svcCount += serv.DependentServices.Length + 1;
svcCount++;
try
{
var serviceController = ServiceController.GetServices().FirstOrDefault(x => x.ServiceName.Equals(serviceName));
if (serviceController != null)
svcCount += serviceController.DependentServices.Length;
}
catch (Exception e)
{
Console.WriteLine($"\r\nError: Could not get amount of dependent services for {serviceName}.\r\nException: " + e.Message);
}
}
} catch (Exception e)
{
@ -645,6 +697,11 @@ namespace TrustedUninstaller.Shared.Actions
ErrorLogger.WriteToErrorLog($"Could not kill locking processes for file '{realPath}'. Process termination loop exceeded max cycles (8).",
Environment.StackTrace, "FileAction Error");
if (Path.GetExtension(realPath).Equals(".exe", StringComparison.OrdinalIgnoreCase))
{
await new TaskKillAction() { ProcessName = Path.GetFileNameWithoutExtension(realPath) }.RunTask();
}
await DeleteFile(realPath, true);
}
}


+ 3
- 1
TrustedUninstaller.Shared/Actions/LanguageAction.cs View File

@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;
@ -8,6 +9,7 @@ namespace TrustedUninstaller.Shared.Actions
{
class LanguageAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
public int ProgressWeight { get; set; } = 1;
public int GetProgressWeight() => ProgressWeight;


+ 1
- 0
TrustedUninstaller.Shared/Actions/LineInFileAction.cs View File

@ -16,6 +16,7 @@ namespace TrustedUninstaller.Shared.Actions
}
internal class LineInFileAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(Alias = "path")]
public string RawPath { get; set; }


+ 174
- 12
TrustedUninstaller.Shared/Actions/PowershellAction.cs View File

@ -14,6 +14,26 @@ namespace TrustedUninstaller.Shared.Actions
{
public class PowerShellAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread()
{
if (InProgress) throw new TaskInProgressException("Another Powershell action was called while one was in progress.");
InProgress = true;
Console.WriteLine($"Running PowerShell command '{Command}'...");
WinUtil.CheckKph();
if (RunAs == Privilege.TrustedInstaller)
RunAsProcess();
else
RunAsPrivilegedProcess();
InProgress = false;
return;
}
[YamlMember(typeof(Privilege), Alias = "runas")]
public Privilege RunAs { get; set; } = Privilege.TrustedInstaller;
[YamlMember(typeof(string), Alias = "command")]
public string Command { get; set; }
@ -50,13 +70,13 @@ namespace TrustedUninstaller.Shared.Actions
return ExitCode == null ? UninstallTaskStatus.ToDo: UninstallTaskStatus.Completed;
}
public async Task<bool> RunTask()
public Task<bool> RunTask()
{
if (InProgress) throw new TaskInProgressException("Another Powershell action was called while one was in progress.");
InProgress = true;
Console.WriteLine($"Running PowerShell command '{Command}'...");
return null;
}
private void RunAsProcess()
{
var process = new Process();
var startInfo = new ProcessStartInfo
{
@ -83,7 +103,7 @@ namespace TrustedUninstaller.Shared.Actions
if (!Wait)
{
process.Dispose();
return true;
return;
}
var error = new StringBuilder();
@ -98,6 +118,114 @@ namespace TrustedUninstaller.Shared.Actions
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if (Timeout != null)
{
var exited = process.WaitForExit(Timeout.Value);
if (!exited)
{
process.Kill();
throw new TimeoutException($"Command '{Command}' timeout exceeded.");
}
}
else
{
bool exited = process.WaitForExit(30000);
// WaitForExit alone seems to not be entirely reliable
while (!exited && PowerShellRunning(process.Id))
{
exited = process.WaitForExit(30000);
}
}
StandardError = error.ToString();
int exitCode = 0;
try
{
exitCode = process.ExitCode;
}
catch (Exception ex)
{
ErrorLogger.WriteToErrorLog("Error fetching process exit code. (1)", null, "PowerShellAction Error", Command);
}
if (exitCode != 0)
{
Console.WriteLine($"PowerShell instance exited with error code: {exitCode}");
if (!String.IsNullOrEmpty(StandardError)) Console.WriteLine($"Error message: {StandardError}");
ErrorLogger.WriteToErrorLog("PowerShell exited with a non-zero exit code: " + exitCode, null, "PowerShellAction Error", Command);
this.ExitCode = exitCode;
}
else
{
if (!String.IsNullOrEmpty(StandardError)) Console.WriteLine($"Error output: {StandardError}");
ExitCode = 0;
}
process.CancelOutputRead();
process.CancelErrorRead();
process.Dispose();
}
private static bool PowerShellRunning(int id)
{
try
{
return Process.GetProcessesByName("powershell").Any(x => x.Id == id);
}
catch (Exception)
{
return false;
}
}
private void RunAsPrivilegedProcess()
{
var process = new AugmentedProcess.Process();
var startInfo = new AugmentedProcess.ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Normal,
FileName = "PowerShell.exe",
Arguments = $@"-NoP -ExecutionPolicy Bypass -NonInteractive -C ""{Command}""",
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
CreateNoWindow = true
};
if (ExeDir) startInfo.WorkingDirectory = AmeliorationUtil.Playbook.Path + "\\Executables";
if (!Wait)
{
startInfo.RedirectStandardError = false;
startInfo.RedirectStandardOutput = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.UseShellExecute = true;
}
process.StartInfo = startInfo;
ProcessPrivilege.StartPrivilegedTask(process, RunAs);
if (!Wait)
{
process.Dispose();
return;
}
var error = new StringBuilder();
process.OutputDataReceived += PrivilegedProcOutputHandler;
process.ErrorDataReceived += delegate(object sender, AugmentedProcess.DataReceivedEventArgs args)
{
if (!String.IsNullOrEmpty(args.Data))
error.AppendLine(args.Data);
else
error.AppendLine();
};
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if (Timeout != null)
{
var exited = process.WaitForExit(Timeout.Value);
@ -129,16 +257,50 @@ namespace TrustedUninstaller.Shared.Actions
process.CancelOutputRead();
process.CancelErrorRead();
process.Dispose();
InProgress = false;
return true;
}
private static bool ExeRunning(string exe, int id)
{
try
{
return Process.GetProcessesByName(Path.GetFileNameWithoutExtension(exe)).Any(x => x.Id == id);
}
catch (Exception)
{
return false;
}
}
private static void ProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
private void PrivilegedProcOutputHandler(object sendingProcess, AugmentedProcess.DataReceivedEventArgs outLine)
{
var outputString = outLine.Data;
// Collect the sort command output.
if (!String.IsNullOrEmpty(outLine.Data))
{
Console.WriteLine(outLine.Data);
if (outputString.Contains("\\AME"))
{
outputString = outputString.Substring(outputString.IndexOf('>') + 1);
}
Console.WriteLine(outputString);
}
else
{
Console.WriteLine();
}
}
private void ProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
var outputString = outLine.Data;
// Collect the sort command output.
if (!String.IsNullOrEmpty(outLine.Data))
{
if (outputString.Contains("\\AME"))
{
outputString = outputString.Substring(outputString.IndexOf('>') + 1);
}
Console.WriteLine(outputString);
}
else
{


+ 1
- 0
TrustedUninstaller.Shared/Actions/RegistryKeyAction.cs View File

@ -23,6 +23,7 @@ namespace TrustedUninstaller.Shared.Actions
}
public class RegistryKeyAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(typeof(string), Alias = "path")]
public string KeyName { get; set; }


+ 1
- 0
TrustedUninstaller.Shared/Actions/RegistryValueAction.cs View File

@ -38,6 +38,7 @@ namespace TrustedUninstaller.Shared.Actions
public class RegistryValueAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(typeof(string), Alias = "path")]
public string KeyName { get; set; }


+ 187
- 28
TrustedUninstaller.Shared/Actions/RunAction.cs View File

@ -2,14 +2,59 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Documents;
using TrustedUninstaller.Shared.Tasks;
using YamlDotNet.Serialization;
namespace TrustedUninstaller.Shared.Actions
{
public enum Privilege
{
TrustedInstaller,
System,
CurrentUserElevated,
CurrentUser,
}
public class RunAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread()
{
if (RawPath != null) RawPath = Environment.ExpandEnvironmentVariables(RawPath);
InProgress = true;
if (Arguments == null) Console.WriteLine($"Running '{Exe}'...");
else Console.WriteLine($"Running '{Exe}' with arguments '{Arguments}'...");
WinUtil.CheckKph();
var currentDir = Directory.GetCurrentDirectory();
if (ExeDir) RawPath = AmeliorationUtil.Playbook.Path + "\\Executables";
if (BaseDir) RawPath = currentDir;
string file = null;
if (RawPath != null && File.Exists(Path.Combine(Environment.ExpandEnvironmentVariables(RawPath), Exe)))
file = Path.Combine(Environment.ExpandEnvironmentVariables(RawPath), Exe);
else if (ExistsInPath(Exe) || File.Exists(Environment.ExpandEnvironmentVariables(Exe)))
file = Environment.ExpandEnvironmentVariables(Exe);
if (file == null)
throw new FileNotFoundException($"Executable not found.");
if (RunAs == Privilege.TrustedInstaller)
RunAsProcess(file);
else
RunAsPrivilegedProcess(file);
InProgress = false;
return;
}
[YamlMember(typeof(Privilege), Alias = "runas")]
public Privilege RunAs { get; set; } = Privilege.TrustedInstaller;
[YamlMember(typeof(string), Alias = "path")]
public string RawPath { get; set; } = null;
@ -80,28 +125,13 @@ namespace TrustedUninstaller.Shared.Actions
return HasExited || !Wait ? UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo;
}
public async Task<bool> RunTask()
public Task<bool> RunTask()
{
if (RawPath != null) RawPath = Environment.ExpandEnvironmentVariables(RawPath);
InProgress = true;
if (Arguments == null) Console.WriteLine($"Running '{Exe}'...");
else Console.WriteLine($"Running '{Exe}' with arguments '{Arguments}'...");
var currentDir = Directory.GetCurrentDirectory();
if (ExeDir) RawPath = AmeliorationUtil.Playbook.Path + "\\Executables";
if (BaseDir) RawPath = currentDir;
string file = null;
if (RawPath != null && File.Exists(Path.Combine(RawPath, Exe)))
file = Path.Combine(RawPath, Exe);
else if (ExistsInPath(Exe) || File.Exists(Environment.ExpandEnvironmentVariables(Exe)))
file = Exe;
if (file == null)
throw new FileNotFoundException($"Executable not found.");
return null;
}
private void RunAsProcess(string file)
{
var startInfo = new ProcessStartInfo
{
CreateNoWindow = !this.CreateWindow,
@ -138,7 +168,7 @@ namespace TrustedUninstaller.Shared.Actions
if (!Wait)
{
exeProcess.Dispose();
return true;
return;
}
if (ShowOutput)
@ -165,15 +195,24 @@ namespace TrustedUninstaller.Shared.Actions
bool exited = exeProcess.WaitForExit(30000);
// WaitForExit alone seems to not be entirely reliable
while (!exited && ExeRunning(exeProcess))
while (!exited && ExeRunning(exeProcess.ProcessName, exeProcess.Id))
{
exited = exeProcess.WaitForExit(30000);
}
}
if (exeProcess.ExitCode != 0)
int exitCode = 0;
try
{
exitCode = exeProcess.ExitCode;
}
catch (Exception ex)
{
ErrorLogger.WriteToErrorLog("Process exited with a non-zero exit code: " + exeProcess.ExitCode, null, "RunAction Error", Exe + " " + Arguments);
ErrorLogger.WriteToErrorLog("Error fetching process exit code. (1)", null, "RunAction Error", Exe + " " + Arguments);
}
if (exitCode != 0)
{
ErrorLogger.WriteToErrorLog("Process exited with a non-zero exit code: " + exitCode, null, "RunAction Error", Exe + " " + Arguments);
}
HasExited = true;
@ -182,15 +221,116 @@ namespace TrustedUninstaller.Shared.Actions
exeProcess.CancelOutputRead();
if (ShowError)
exeProcess.CancelErrorRead();
}
private void RunAsPrivilegedProcess(string file)
{
var startInfo = new AugmentedProcess.ProcessStartInfo
{
CreateNoWindow = !this.CreateWindow,
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Normal,
RedirectStandardError = true,
RedirectStandardOutput = true,
FileName = file,
};
if (Arguments != null) startInfo.Arguments = Arguments;
InProgress = false;
return true;
if (ExeDir) startInfo.WorkingDirectory = AmeliorationUtil.Playbook.Path + "\\Executables";
if (!Wait)
{
startInfo.RedirectStandardError = false;
startInfo.RedirectStandardOutput = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.UseShellExecute = true;
}
if (!ShowOutput)
startInfo.RedirectStandardOutput = false;
if (!ShowError)
startInfo.RedirectStandardError = false;
var exeProcess = new AugmentedProcess.Process
{
StartInfo = startInfo,
EnableRaisingEvents = true
};
ProcessPrivilege.StartPrivilegedTask(exeProcess, RunAs);
if (!Wait)
{
exeProcess.Dispose();
return;
}
if (ShowOutput)
exeProcess.OutputDataReceived += PrivilegedProcOutputHandler;
if (ShowError)
exeProcess.ErrorDataReceived += PrivilegedProcOutputHandler;
if (ShowOutput)
exeProcess.BeginOutputReadLine();
if (ShowError)
exeProcess.BeginErrorReadLine();
if (Timeout.HasValue)
{
var exited = exeProcess.WaitForExit(Timeout.Value);
if (!exited)
{
exeProcess.Kill();
throw new TimeoutException($"Executable run timeout exceeded.");
}
}
else
{
bool exited = exeProcess.WaitForExit(30000);
// WaitForExit alone seems to not be entirely reliable
while (!exited && ExeRunning(exeProcess.ProcessName, exeProcess.Id))
{
exited = exeProcess.WaitForExit(30000);
}
}
try
{
if (exeProcess.ExitCode != 0)
{
ErrorLogger.WriteToErrorLog("Process exited with a non-zero exit code: " + exeProcess.ExitCode, null, "RunAction Error", Exe + " " + Arguments);
}
}
catch (Exception ex)
{
ErrorLogger.WriteToErrorLog("Error fetching process exit code. (1)", null, "RunAction Error", Exe + " " + Arguments);
Thread.Sleep(500);
try
{
if (exeProcess.ExitCode != 0)
{
ErrorLogger.WriteToErrorLog("Process exited with a non-zero exit code: " + exeProcess.ExitCode, null, "RunAction Error", Exe + " " + Arguments);
}
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Error fetching process exit code. (2)", null, "RunAction Error", Exe + " " + Arguments);
}
}
HasExited = true;
if (ShowOutput)
exeProcess.CancelOutputRead();
if (ShowError)
exeProcess.CancelErrorRead();
}
private static bool ExeRunning(Process process)
private static bool ExeRunning(string name, int id)
{
try
{
return Process.GetProcessesByName(process.ProcessName).Any(x => x.Id == process.Id);
return Process.GetProcessesByName(name).Any(x => x.Id == id);
}
catch (Exception)
{
@ -198,6 +338,25 @@ namespace TrustedUninstaller.Shared.Actions
}
}
private void PrivilegedProcOutputHandler(object sendingProcess, AugmentedProcess.DataReceivedEventArgs outLine)
{
// Collect the sort command output.
if (!String.IsNullOrEmpty(outLine.Data))
{
var outputString = outLine.Data;
if (outputString.Contains("\\AME"))
{
outputString = outputString.Substring(outputString.IndexOf('>') + 1);
}
Console.WriteLine(outputString);
Output += outputString + Environment.NewLine;
}
else
{
Console.WriteLine();
}
}
private void ProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
// Collect the sort command output.


+ 1
- 0
TrustedUninstaller.Shared/Actions/ScheduledTaskAction.cs View File

@ -21,6 +21,7 @@ namespace TrustedUninstaller.Shared.Actions
internal class ScheduledTaskAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(typeof(ScheduledTaskOperation), Alias = "operation")]
public ScheduledTaskOperation Operation { get; set; } = ScheduledTaskOperation.Delete;
[YamlMember(Alias = "data")]


+ 80
- 56
TrustedUninstaller.Shared/Actions/ServiceAction.cs View File

@ -1,5 +1,7 @@
#nullable enable
using System;
using System.Collections.Specialized;
using System.Configuration.Install;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -7,6 +9,7 @@ using System.Management;
using System.ServiceProcess;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.Win32;
using TrustedUninstaller.Shared.Exceptions;
using TrustedUninstaller.Shared.Tasks;
@ -25,6 +28,7 @@ namespace TrustedUninstaller.Shared.Actions
}
internal class ServiceAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(typeof(ServiceOperation), Alias = "operation")]
public ServiceOperation Operation { get; set; } = ServiceOperation.Delete;
@ -94,7 +98,7 @@ namespace TrustedUninstaller.Shared.Actions
return (int)value == Startup.Value ? UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo;
}
ServiceController serviceController;
ServiceController? serviceController;
if (Device) serviceController = GetDevice();
else serviceController = GetService();
@ -129,12 +133,10 @@ namespace TrustedUninstaller.Shared.Actions
|| serviceController?.Status == ServiceControllerStatus.PausePending ?
UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo,
ServiceOperation.Delete =>
serviceController == null ?
serviceController == null || Win32.ServiceEx.IsPendingDeleteOrDeleted(serviceController.ServiceName) ?
UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo,
_ => throw new ArgumentOutOfRangeException("Argument out of Range", new ArgumentOutOfRangeException())
};
}
private readonly string[] RegexNoKill = { "DcomLaunch" };
@ -191,44 +193,46 @@ namespace TrustedUninstaller.Shared.Actions
foreach (ServiceController dependentService in service.DependentServices)
{
Console.WriteLine($"Killing dependent service {dependentService.ServiceName}...");
try
{
dependentService.Stop();
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Service stop failed: " + e.Message, e.StackTrace, "ServiceAction Warning", ServiceName);
}
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {dependentService.ServiceName} -caction stop" :
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {dependentService.ServiceName} -caction stop" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {dependentService.ServiceName} -caction stop";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
Console.WriteLine("Waiting for the service to stop...");
int delay = 100;
while (service.Status != ServiceControllerStatus.Stopped && delay <= 1000)
while (dependentService.Status != ServiceControllerStatus.Stopped && delay <= 1000)
{
service.Refresh();
dependentService.Refresh();
//Wait for the service to stop
Task.Delay(delay).Wait();
delay += 100;
}
if (delay >= 1000)
{
Console.WriteLine("\r\nService stop timeout exceeded. Trying second method...");
try
{
using var search = new ManagementObjectSearcher($"SELECT * FROM Win32_Service WHERE Name='{service.ServiceName}'");
foreach (ManagementObject queryObj in search.Get())
{
var serviceId = (UInt32)queryObj["ProcessId"]; // Access service name
var killServ = new TaskKillAction()
{
ProcessID = (int)serviceId
};
await killServ.RunTask();
}
}
catch (Exception e)
Console.WriteLine("\r\nService stop timeout exceeded.");
}
try
{
var killServ = new TaskKillAction()
{
ErrorLogger.WriteToErrorLog($"Could not kill dependent service {dependentService.ServiceName}.",
e.StackTrace, "ServiceAction Error");
}
ProcessID = Win32.ServiceEx.GetServiceProcessId(dependentService.ServiceName)
};
await killServ.RunTask();
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog($"Could not kill dependent service {dependentService.ServiceName}.",
e.StackTrace, "ServiceAction Error");
}
}
@ -243,11 +247,19 @@ namespace TrustedUninstaller.Shared.Actions
if (DeleteStop && service.Status != ServiceControllerStatus.StopPending && service.Status != ServiceControllerStatus.Stopped)
{
try
{
service.Stop();
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Service stop failed: " + e.Message, e.StackTrace, "ServiceAction Warning", ServiceName);
}
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction stop" :
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction stop" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction stop";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
}
Console.WriteLine("Waiting for the service to stop...");
@ -259,30 +271,21 @@ namespace TrustedUninstaller.Shared.Actions
await Task.Delay(delay);
delay += 100;
}
if (delay >= 1500)
if (delay >= 1000)
{
Console.WriteLine("\r\nService stop timeout exceeded. Trying second method...");
try
{
using var search = new ManagementObjectSearcher($"SELECT * FROM Win32_Service WHERE Name='{service.ServiceName}'");
foreach (ManagementObject queryObj in search.Get())
{
var serviceId = (UInt32)queryObj["ProcessId"]; // Access service name
var killServ = new TaskKillAction()
{
ProcessID = (int)serviceId
};
await killServ.RunTask();
}
}
catch (Exception e)
Console.WriteLine("\r\nService stop timeout exceeded.");
}
try
{
var killServ = new TaskKillAction()
{
ErrorLogger.WriteToErrorLog($"Could not kill service {service.ServiceName}.",
e.StackTrace, "ServiceAction Error");
}
ProcessID = Win32.ServiceEx.GetServiceProcessId(service.ServiceName)
};
await killServ.RunTask();
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog($"Could not kill service {service.ServiceName}.", e.StackTrace, "ServiceAction Error");
}
if (RegistryDelete)
@ -296,18 +299,39 @@ namespace TrustedUninstaller.Shared.Actions
}
else
{
try
{
ServiceInstaller ServiceInstallerObj = new ServiceInstaller();
ServiceInstallerObj.Context = new InstallContext();
ServiceInstallerObj.ServiceName = service.ServiceName;
ServiceInstallerObj.Uninstall(null);
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Service uninstall failed: " + e.Message, e.StackTrace, "ServiceAction Warning", ServiceName);
}
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction delete" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction delete";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
}
}
else
{
try
{
service.Stop();
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Service stop failed: " + e.Message, e.StackTrace, "ServiceAction Warning", ServiceName);
}
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction {Operation.ToString().ToLower()}" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype service -cobject {service.ServiceName} -caction {Operation.ToString().ToLower()}";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
}
service?.Dispose();


+ 1
- 0
TrustedUninstaller.Shared/Actions/ShortcutAction.cs View File

@ -10,6 +10,7 @@ namespace TrustedUninstaller.Shared.Actions
{
class ShortcutAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(typeof(string), Alias = "path")]
public string RawPath { get; set; }


+ 4
- 1
TrustedUninstaller.Shared/Actions/SystemPackageAction.cs View File

@ -14,6 +14,7 @@ namespace TrustedUninstaller.Shared.Actions
// Integrate ame-assassin later
internal class SystemPackageAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
public enum Architecture
{
amd64 = 0,
@ -77,11 +78,13 @@ namespace TrustedUninstaller.Shared.Actions
}
}
string kernelDriverArg = AmeliorationUtil.UseKernelDriver ? " -UseKernelDriver" : "";
var psi = new ProcessStartInfo()
{
UseShellExecute = false,
CreateNoWindow = true,
Arguments = $@"-SystemPackage ""{Name}"" -Arch {Arch.ToString()} -Language ""{Language}""" + excludeArgs + excludeDependsArgs,
Arguments = $@"-SystemPackage ""{Name}"" -Arch {Arch.ToString()} -Language ""{Language}""" + excludeArgs + excludeDependsArgs + kernelDriverArg,
FileName = Directory.GetCurrentDirectory() + "\\ame-assassin\\ame-assassin.exe",
RedirectStandardOutput = true,
RedirectStandardError = true


+ 178
- 116
TrustedUninstaller.Shared/Actions/TaskKillAction.cs View File

@ -13,9 +13,22 @@ namespace TrustedUninstaller.Shared.Actions
{
class TaskKillAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess,
bool bInheritHandle, int dwProcessId);
public enum ProcessAccessFlags : uint
{
QueryLimitedInformation = 0x1000
}
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);
[YamlMember(typeof(string), Alias = "name")]
public string? ProcessName { get; set; }
@ -73,18 +86,38 @@ namespace TrustedUninstaller.Shared.Actions
return processToTerminate.Any() ? UninstallTaskStatus.ToDo : UninstallTaskStatus.Completed;
}
private IEnumerable<Process> GetProcess()
private List<Process> GetProcess()
{
if (ProcessName == null) return new List<Process>();
if (ProcessID.HasValue)
{
var list = new List<Process>();
try
{
var process = Process.GetProcessById(ProcessID.Value);
if (ProcessName == null || process.ProcessName.Equals(ProcessName, StringComparison.OrdinalIgnoreCase))
list.Add(process);
else
return list;
}
catch (Exception e)
{
return list;
}
}
if (ProcessName.EndsWith("*") && ProcessName.StartsWith("*")) return Process.GetProcesses()
.Where(process => process.ProcessName.IndexOf(ProcessName.Trim('*'), StringComparison.CurrentCultureIgnoreCase) >= 0);
if (ProcessName == null)
{
return new List<Process>();
}
if (ProcessName.EndsWith("*") && ProcessName.StartsWith("*")) return Process.GetProcesses().ToList()
.Where(process => process.ProcessName.IndexOf(ProcessName.Trim('*'), StringComparison.CurrentCultureIgnoreCase) >= 0).ToList();
if (ProcessName.EndsWith("*")) return Process.GetProcesses()
.Where(process => process.ProcessName.StartsWith(ProcessName.TrimEnd('*'), StringComparison.CurrentCultureIgnoreCase));
.Where(process => process.ProcessName.StartsWith(ProcessName.TrimEnd('*'), StringComparison.CurrentCultureIgnoreCase)).ToList();
if (ProcessName.StartsWith("*")) return Process.GetProcesses()
.Where(process => process.ProcessName.EndsWith(ProcessName.TrimStart('*'), StringComparison.CurrentCultureIgnoreCase));
.Where(process => process.ProcessName.EndsWith(ProcessName.TrimStart('*'), StringComparison.CurrentCultureIgnoreCase)).ToList();
return Process.GetProcessesByName(ProcessName);
return Process.GetProcessesByName(ProcessName).ToList();
}
[DllImport("kernel32.dll", SetLastError=true)]
static extern bool IsProcessCritical(IntPtr hProcess, ref bool Critical);
@ -116,85 +149,76 @@ namespace TrustedUninstaller.Shared.Actions
if (ProcessName != null)
{
//If the service is svchost, we stop the service instead of killing it.
if (ProcessName.Contains("svchost"))
if (ProcessName.Equals("svchost", StringComparison.OrdinalIgnoreCase))
{
// bool serviceFound = false;
try
{
using var search = new ManagementObjectSearcher($"select * from Win32_Service where ProcessId = '{ProcessID}'");
foreach (ManagementObject queryObj in search.Get())
if (ProcessID.HasValue)
{
foreach (var serviceName in Win32.ServiceEx.GetServicesFromProcessId(ProcessID.Value))
{
try
{
var stopServ = new ServiceAction()
{
ServiceName = serviceName,
Operation = ServiceOperation.Stop
};
await stopServ.RunTask();
}
catch (Exception e)
{
Console.WriteLine($"Could not kill service " + serviceName + ": " + e.Message);
ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "Could not kill service " + serviceName + ": " + e.Message);
}
}
}
else
{
var serviceName = (string)queryObj["Name"]; // Access service name
var stopServ = new ServiceAction()
foreach (var process in GetProcess())
{
ServiceName = serviceName,
Operation = ServiceOperation.Stop
foreach (var serviceName in Win32.ServiceEx.GetServicesFromProcessId(process.Id))
{
try
{
var stopServ = new ServiceAction()
{
ServiceName = serviceName,
Operation = ServiceOperation.Stop
};
await stopServ.RunTask();
};
await stopServ.RunTask();
}
catch (Exception e)
{
Console.WriteLine($"Could not kill service " + serviceName + ": " + e.Message);
ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "Could not kill service " + serviceName + ": " + e.Message);
}
}
}
}
}
catch (NullReferenceException e)
{
Console.WriteLine($"A service with PID: {ProcessID} could not be found.");
ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, $"Could not find service with PID {ProcessID}.");
Console.WriteLine($"A service with PID: {ProcessID.Value} could not be found.");
ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, $"Could not find service with PID {ProcessID.Value}.");
}
/* foreach (var serv in servicesToDelete)
int i;
for (i = 0; i <= 6 && GetProcess().Any(); i++)
{
//The ID can only be associated with one of the services, there's no need to loop through
//them all if we already found the service.
if (serviceFound)
{
break;
}
try
{
using var search = new ManagementObjectSearcher($"select ProcessId from Win32_Service where Name = '{serv}'").Get();
var servID = (uint)search.OfType<ManagementObject>().FirstOrDefault()["ProcessID"];
if (servID == ProcessID)
{
serviceFound = true;
}
search.Dispose();
}
catch (Exception e)
{
var search = new ManagementObjectSearcher($"select Name from Win32_Service where ProcessID = '{ProcessID}'").Get();
var servName = search.OfType<ManagementObject>().FirstOrDefault()["Name"];
Console.WriteLine($"Could not find {servName} but PID {ProcessID} still exists.");
ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, $"Exception Type: {e.GetType()}");
return false;
}
}*/
//None of the services listed, we shouldn't kill svchost.
/* if (!serviceFound)
await Task.Delay(100 * i);
}
if (i < 6)
{
var search = new ManagementObjectSearcher($"select Name from Win32_Service where ProcessID = '{ProcessID}'").Get();
var servName = search.OfType<ManagementObject>().FirstOrDefault()["Name"];
Console.WriteLine($"A critical system process \"{servName}\" with PID {ProcessID} caused the Wizard to fail.");
await WinUtil.UninstallDriver();
Environment.Exit(-1);
return false;
}*/
await Task.Delay(100);
InProgress = false;
return true;
InProgress = false;
return true;
}
}
if (PathContains != null && !ProcessID.HasValue)
{
var processes = GetProcess().ToList();
var processes = GetProcess();
if (processes.Count > 0) Console.WriteLine("Processes:");
foreach (var process in processes.Where(x => x.MainModule.FileName.Contains(PathContains)))
@ -203,58 +227,74 @@ namespace TrustedUninstaller.Shared.Actions
if (!RegexNotCritical.Any(x => Regex.Match(process.ProcessName, x, RegexOptions.IgnoreCase).Success)) {
bool isCritical = false;
IsProcessCritical(process.Handle, ref isCritical);
IntPtr hprocess = OpenProcess(ProcessAccessFlags.QueryLimitedInformation, false, process.Id);
IsProcessCritical(hprocess, ref isCritical);
CloseHandle(hprocess);
if (isCritical)
{
Console.WriteLine($"{process.ProcessName} is a critical process, skipping...");
continue;
}
}
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype process -cobject {process.Id} -caction terminate" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype process -cobject {process.Id} -caction terminate";
await cmdAction.RunTask();
if (AmeliorationUtil.UseKernelDriver)
cmdAction.RunTaskOnMainThread();
else
TerminateProcess(process.Handle, 1);
int i = 0;
while (i <= 15 && GetProcess().Any(x => x.Id == process.Id && x.ProcessName == process.ProcessName))
while (i <= 5 && GetProcess().Any(x => x.Id == process.Id && x.ProcessName == process.ProcessName))
{
await Task.Delay(300);
if (AmeliorationUtil.UseKernelDriver)
cmdAction.RunTaskOnMainThread();
else
TerminateProcess(process.Handle, 1);
i++;
}
if (i >= 15) ErrorLogger.WriteToErrorLog($"Task kill timeout exceeded.", Environment.StackTrace, "TaskKillAction Error");
try {
if (!TerminateProcess(process.Handle, 1))
ErrorLogger.WriteToErrorLog("TerminateProcess failed with error code: " + Marshal.GetLastWin32Error(), Environment.StackTrace, "TaskKill Error", ProcessName);
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Could not open process handle.", e.StackTrace, "TaskKillAction Error", process.ProcessName);
}
if (i >= 5) ErrorLogger.WriteToErrorLog($"Task kill timeout exceeded.", Environment.StackTrace, "TaskKillAction Error");
}
InProgress = false;
return true;
}
}
if (ProcessID.HasValue)
{
var process = Process.GetProcessById(ProcessID.Value);
if (ProcessName != null && ProcessName.Equals("explorer", StringComparison.OrdinalIgnoreCase))
{
try
{
var process = Process.GetProcessById(ProcessID.Value);
TerminateProcess(process.Handle, 1);
} catch (Exception)
try {
if (!TerminateProcess(process.Handle, 1))
ErrorLogger.WriteToErrorLog("TerminateProcess failed with error code: " + Marshal.GetLastWin32Error(), Environment.StackTrace, "TaskKill Error", ProcessName);
}
catch (Exception e)
{
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype process -cobject {ProcessID} -caction terminate" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype process -cobject {ProcessID} -caction terminate";
await cmdAction.RunTask();
ErrorLogger.WriteToErrorLog("Could not open process handle.", e.StackTrace, "TaskKillAction Error", process.ProcessName);
}
}
else
{
var process = Process.GetProcessById(ProcessID.Value);
if (!RegexNotCritical.Any(x => Regex.Match(process.ProcessName, x, RegexOptions.IgnoreCase).Success))
{
bool isCritical = false;
try
{
IsProcessCritical(process.Handle, ref isCritical);
IntPtr hprocess = OpenProcess(ProcessAccessFlags.QueryLimitedInformation, false, process.Id);
IsProcessCritical(hprocess, ref isCritical);
CloseHandle(hprocess);
}
catch (InvalidOperationException e)
{
@ -267,59 +307,81 @@ namespace TrustedUninstaller.Shared.Actions
return false;
}
}
try {
if (!TerminateProcess(process.Handle, 1))
ErrorLogger.WriteToErrorLog("TerminateProcess failed with error code: " + Marshal.GetLastWin32Error(), Environment.StackTrace, "TaskKill Error", ProcessName);
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Could not open process handle.", e.StackTrace, "TaskKillAction Error", process.ProcessName);
}
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype process -cobject {ProcessID} -caction terminate" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype process -cobject {ProcessID} -caction terminate";
await cmdAction.RunTask();
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype process -cobject {ProcessID.Value} -caction terminate" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype process -cobject {ProcessID.Value} -caction terminate";
if (AmeliorationUtil.UseKernelDriver) cmdAction.RunTaskOnMainThread();
}
await Task.Delay(100);
}
else
{
var processes = GetProcess().ToList();
var processes = GetProcess();
if (processes.Count > 0) Console.WriteLine("Processes:");
foreach (var process in processes)
{
Console.WriteLine(process.ProcessName + " - " + process.Id);
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype process -cobject {process.ProcessName}.exe -caction terminate" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype process -cobject {process.ProcessName}.exe -caction terminate";
if (process.ProcessName == "explorer") TerminateProcess(process.Handle, 1);
else
if (!RegexNotCritical.Any(x => Regex.Match(process.ProcessName, x, RegexOptions.IgnoreCase).Success))
{
if (!RegexNotCritical.Any(x => Regex.Match(process.ProcessName, x, RegexOptions.IgnoreCase).Success))
bool isCritical = false;
try
{
bool isCritical = false;
try
{
IsProcessCritical(process.Handle, ref isCritical);
}
catch (InvalidOperationException e)
{
ErrorLogger.WriteToErrorLog("Could not check if process is critical.", e.StackTrace, "TaskKillAction Error", process.ProcessName);
continue;
}
if (isCritical)
{
Console.WriteLine($"{process.ProcessName} is a critical process, skipping...");
continue;
}
IntPtr hprocess = OpenProcess(ProcessAccessFlags.QueryLimitedInformation, false, process.Id);
IsProcessCritical(hprocess, ref isCritical);
CloseHandle(hprocess);
}
await cmdAction.RunTask();
catch (InvalidOperationException e)
{
ErrorLogger.WriteToErrorLog("Could not check if process is critical.", e.StackTrace, "TaskKillAction Error", process.ProcessName);
continue;
}
if (isCritical)
{
Console.WriteLine($"{process.ProcessName} is a critical process, skipping...");
continue;
}
}
try
{
if (!TerminateProcess(process.Handle, 1))
ErrorLogger.WriteToErrorLog("TerminateProcess failed with error code: " + Marshal.GetLastWin32Error(), Environment.StackTrace, "TaskKill Error", ProcessName);
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog("Could not open process handle.", e.StackTrace, "TaskKillAction Error", process.ProcessName);
}
if (process.ProcessName == "explorer") continue;
cmdAction.Command = Environment.Is64BitOperatingSystem ?
$"ProcessHacker\\x64\\ProcessHacker.exe -s -elevate -c -ctype process -cobject {process.Id} -caction terminate" :
$"ProcessHacker\\x86\\ProcessHacker.exe -s -elevate -c -ctype process -cobject {process.Id} -caction terminate";
if (AmeliorationUtil.UseKernelDriver && process.ProcessName != "explorer") cmdAction.RunTaskOnMainThread();
int i = 0;
while (i <= 15 && GetProcess().Any(x => x.Id == process.Id && x.ProcessName == process.ProcessName))
while (i <= 5 && GetProcess().Any(x => x.Id == process.Id && x.ProcessName == process.ProcessName))
{
if (AmeliorationUtil.UseKernelDriver)
cmdAction.RunTaskOnMainThread();
else
TerminateProcess(process.Handle, 1);
await Task.Delay(300);
i++;
}
if (i >= 15) ErrorLogger.WriteToErrorLog($"Task kill timeout exceeded.", Environment.StackTrace, "TaskKillAction Error");
if (i >= 5) ErrorLogger.WriteToErrorLog($"Task kill timeout exceeded.", Environment.StackTrace, "TaskKillAction Error");
}
}


+ 1
- 0
TrustedUninstaller.Shared/Actions/UpdateAction.cs View File

@ -10,6 +10,7 @@ namespace TrustedUninstaller.Shared.Actions
{
internal class UpdateAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(typeof(string), Alias = "name")]
public string PackageName { get; set; }


+ 1
- 0
TrustedUninstaller.Shared/Actions/UserAction.cs View File

@ -10,6 +10,7 @@ namespace TrustedUninstaller.Shared.Actions
{
public class UserAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(typeof(string), Alias = "name")]
public string Username { get; set; } = "";
[YamlMember(typeof(bool), Alias = "admin")]


+ 1
- 0
TrustedUninstaller.Shared/Actions/WriteStatusAction.cs View File

@ -7,6 +7,7 @@ namespace TrustedUninstaller.Shared.Actions
{
public class WriteStatusAction : TaskAction, ITaskAction
{
public void RunTaskOnMainThread() { throw new NotImplementedException(); }
[YamlMember(typeof(string), Alias = "status")]
public string Status { get; set; }
private bool InProgress { get; set; }


+ 143
- 26
TrustedUninstaller.Shared/AmeliorationUtil.cs View File

@ -27,8 +27,10 @@ namespace TrustedUninstaller.Shared
private static readonly ConfigParser Parser = new ConfigParser();
private static readonly HttpClient Client = new HttpClient();
public static Playbook Playbook { set; get; }
public static Playbook Playbook { set; get; } = new Playbook();
public static bool UseKernelDriver = false;
public static readonly List<string> ErrorDisplayList = new List<string>();
@ -37,16 +39,19 @@ namespace TrustedUninstaller.Shared
return Parser.Tasks.Sum(task => task.Actions.Sum(action =>
{
var taskAction = (TaskAction)action;
if (!String.IsNullOrEmpty(taskAction.Option) &&
(taskAction.Option.StartsWith("!") && options != null && options.Contains(taskAction.Option.Substring(1), StringComparer.OrdinalIgnoreCase) ||
!taskAction.Option.StartsWith("!") && options != null && !options.Contains(taskAction.Option, StringComparer.OrdinalIgnoreCase)))
if ((!IsApplicableOption(taskAction.Option, options) || !IsApplicableArch(taskAction.Arch)) ||
(taskAction.Builds != null && (
!taskAction.Builds.Where(build => !build.StartsWith("!")).Any(build => IsApplicableWindowsVersion(build))
||
taskAction.Builds.Where(build => build.StartsWith("!")).Any(build => !IsApplicableWindowsVersion(build)))) ||
(taskAction.Options != null && (
!taskAction.Options.Where(option => !option.StartsWith("!")).Any(option => IsApplicableOption(option, Playbook.Options))
||
taskAction.Options.Where(option => option.StartsWith("!")).Any(option => !IsApplicableOption(option, Playbook.Options)))))
{
return 0;
}
if (!String.IsNullOrEmpty(taskAction.Arch) &&
(taskAction.Arch.StartsWith("!") && String.Equals(taskAction.Arch, RuntimeInformation.ProcessArchitecture.ToString(), StringComparison.OrdinalIgnoreCase) ||
!taskAction.Arch.StartsWith("!") && !String.Equals(taskAction.Arch, RuntimeInformation.ProcessArchitecture.ToString(), StringComparison.OrdinalIgnoreCase)))
return 0;
return action.GetProgressWeight();
}));
}
@ -75,6 +80,21 @@ namespace TrustedUninstaller.Shared
}
}
if ((!IsApplicableOption(currentTask.Option, Playbook.Options) || !IsApplicableArch(currentTask.Arch)) ||
(currentTask.Builds != null && (
!currentTask.Builds.Where(build => !build.StartsWith("!")).Any(build => IsApplicableWindowsVersion(build))
||
currentTask.Builds.Where(build => build.StartsWith("!")).Any(build => !IsApplicableWindowsVersion(build)))) ||
(currentTask.Options != null && (
!currentTask.Options.Where(option => !option.StartsWith("!")).Any(option => IsApplicableOption(option, Playbook.Options))
||
currentTask.Options.Where(option => option.StartsWith("!")).Any(option => !IsApplicableOption(option, Playbook.Options)))))
{
Parser.Tasks.Remove(currentTask);
return true;
}
//Get the features of the last added task (the task that was just added from the config file)
var features = currentTask.Features;
@ -203,15 +223,18 @@ namespace TrustedUninstaller.Shared
{
var taskAction = (TaskAction)action;
if (!String.IsNullOrEmpty(taskAction.Option) &&
(taskAction.Option.StartsWith("!") && Playbook.Options != null && Playbook.Options.Contains(taskAction.Option.Substring(1), StringComparer.OrdinalIgnoreCase) ||
!taskAction.Option.StartsWith("!") && Playbook.Options != null && !Playbook.Options.Contains(taskAction.Option, StringComparer.OrdinalIgnoreCase)))
continue;
if (!String.IsNullOrEmpty(taskAction.Arch) &&
(taskAction.Arch.StartsWith("!") && String.Equals(taskAction.Arch, RuntimeInformation.ProcessArchitecture.ToString(), StringComparison.OrdinalIgnoreCase) ||
!taskAction.Arch.StartsWith("!") && !String.Equals(taskAction.Arch, RuntimeInformation.ProcessArchitecture.ToString(), StringComparison.OrdinalIgnoreCase)))
if ((!IsApplicableOption(taskAction.Option, Playbook.Options) || !IsApplicableArch(taskAction.Arch)) ||
(taskAction.Builds != null && (
!taskAction.Builds.Where(build => !build.StartsWith("!")).Any(build => IsApplicableWindowsVersion(build))
||
taskAction.Builds.Where(build => build.StartsWith("!")).Any(build => !IsApplicableWindowsVersion(build)))) ||
(taskAction.Options != null && (
!taskAction.Options.Where(option => !option.StartsWith("!")).Any(option => IsApplicableOption(option, Playbook.Options))
||
taskAction.Options.Where(option => option.StartsWith("!")).Any(option => !IsApplicableOption(option, Playbook.Options)))))
{
continue;
}
int i = 0;
@ -225,7 +248,10 @@ namespace TrustedUninstaller.Shared
Console.WriteLine();
try
{
await action.RunTask();
var actionTask = action.RunTask();
if (actionTask == null)
action.RunTaskOnMainThread();
else await actionTask;
action.ResetProgress();
}
catch (Exception e)
@ -275,6 +301,8 @@ namespace TrustedUninstaller.Shared
}
Console.WriteLine("Task completed.");
ProcessPrivilege.ResetTokens();
File.AppendAllText("TasksAdded.txt", task.Title + Environment.NewLine);
}
catch (Exception e)
@ -434,20 +462,20 @@ namespace TrustedUninstaller.Shared
Console.WriteLine($"{deletedItemsCount} files were deleted successfully. " +
$"{failedDeletedItemsCount} files couldn't be deleted.");
//Check if the kernel driver is installed.
//service = ServiceController.GetDevices()
//.FirstOrDefault(s => s.DisplayName == "KProcessHacker2");
if (true)
if (UseKernelDriver)
{
//Remove Process Hacker's kernel driver.
await WinUtil.UninstallDriver();
await AmeliorationUtil.SafeRunAction(new RegistryKeyAction()
{
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\KProcessHacker2",
});
}
await AmeliorationUtil.SafeRunAction(new RegistryKeyAction()
{
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\KProcessHacker2",
});
File.Delete("TasksAdded.txt");
Console.WriteLine();
@ -625,6 +653,95 @@ namespace TrustedUninstaller.Shared
}
}
}
private static bool IsApplicableWindowsVersion(string version)
{
bool negative = false;
if (version.StartsWith("!"))
{
version = version.TrimStart('!');
negative = true;
}
bool compareUpdateBuild = version.Contains(".");
var currentBuild = decimal.Parse(compareUpdateBuild ? Globals.WinVer + "." + Globals.WinUpdateVer : Globals.WinVer.ToString());
bool result = false;
if (version.StartsWith(">="))
{
var parsed = decimal.Parse(version.Substring(2));
if (currentBuild >= parsed)
result = true;
} else if (version.StartsWith("<="))
{
var parsed = decimal.Parse(version.Substring(2));
if (currentBuild <= parsed)
result = true;
} else if (version.StartsWith(">"))
{
var parsed = decimal.Parse(version.Substring(1));
if (currentBuild > parsed)
result = true;
} else if (version.StartsWith("<"))
{
var parsed = decimal.Parse(version.Substring(1));
if (currentBuild < parsed)
result = true;
}
else
{
var parsed = decimal.Parse(version);
if (currentBuild == parsed)
result = true;
}
return negative ? !result : result;
}
private static bool IsApplicableOption(string option, List<string> options)
{
if (String.IsNullOrEmpty(option))
return true;
if (option.Contains("&"))
{
if (option.Contains("!"))
throw new ArgumentException("YAML options item must not contain both & and !", "options");
return option.Split('&').All(splitOption => IsApplicableOption(splitOption, options));
}
bool negative = false;
if (option.StartsWith("!"))
{
option = option.TrimStart('!');
negative = true;
}
if (options == null)
return negative ? true : false;
var result = options.Contains(option, StringComparer.OrdinalIgnoreCase);
return negative ? !result : result;
}
private static bool IsApplicableArch(string arch)
{
if (String.IsNullOrEmpty(arch))
return true;
bool negative = false;
if (arch.StartsWith("!"))
{
arch = arch.TrimStart('!');
negative = true;
}
var result = String.Equals(arch, RuntimeInformation.ProcessArchitecture.ToString(), StringComparison.OrdinalIgnoreCase);
return negative ? !result : result;
}
public static async Task<bool> SafeRunAction(ITaskAction action)
{


+ 3340
- 0
TrustedUninstaller.Shared/AugmentedProcess.cs
File diff suppressed because it is too large
View File


+ 22
- 0
TrustedUninstaller.Shared/Debug.cs View File

@ -0,0 +1,22 @@
using System;
using System.Diagnostics;
namespace TrustedUninstaller.Shared
{
public static class Testing
{
[Conditional("DEBUG")]
public static void WriteLine(object text)
{
Console.WriteLine(text.ToString());
}
public static void WriteLine(Exception exception, string shortTrace)
{
Console.WriteLine(exception.GetType() + " at " + shortTrace + ":" + exception.Message);
}
public static void WriteLine(Exception exception, string shortTrace, string item)
{
Console.WriteLine(exception.GetType() + " at " + shortTrace + $" ({item}):" + exception.Message);
}
}
}

+ 34
- 14
TrustedUninstaller.Shared/Defender.cs View File

@ -132,7 +132,7 @@ namespace TrustedUninstaller.Shared
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
}.RunTask().Wait();
}.RunTaskOnMainThread();
if (new RegistryValueAction() { KeyName = "HKLM\\SOFTWARE\\Microsoft\\Windows Defender", Value = "InstallLocation", Operation = RegistryValueOperation.Delete }.GetStatus() !=
UninstallTaskStatus.Completed)
@ -157,7 +157,7 @@ namespace TrustedUninstaller.Shared
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
}.RunTask().Wait();
}.RunTaskOnMainThread();
if (new RegistryKeyAction() { KeyName = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\WinDefend" }.GetStatus() !=
UninstallTaskStatus.Completed)
@ -183,7 +183,7 @@ namespace TrustedUninstaller.Shared
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
}.RunTask().Wait();
}.RunTaskOnMainThread();
if (new RegistryValueAction() { KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\WinDefend", Value = "Start", Data = 4, Type = RegistryValueType.REG_DWORD }.GetStatus() !=
UninstallTaskStatus.Completed)
@ -211,7 +211,7 @@ namespace TrustedUninstaller.Shared
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
}.RunTask().Wait();
}.RunTaskOnMainThread();
if (new RegistryKeyAction() { KeyName = @"HKCR\CLSID\{2781761E-28E0-4109-99FE-B9D127C57AFE}\InprocServer32" }.GetStatus() !=
UninstallTaskStatus.Completed)
@ -247,7 +247,7 @@ namespace TrustedUninstaller.Shared
"reg delete \"HKLM\\SOFTWARE\\Microsoft\\WindowsRuntime\\ActivatableClassId\\Windows.Internal.Security.SmartScreen.EventLogger\" /f &" +
"reg delete \"HKLM\\SOFTWARE\\Microsoft\\WindowsRuntime\\ActivatableClassId\\Windows.Internal.Security.SmartScreen.UriReputationService\" /f\"",
CreateWindow = false
}.RunTask().Wait();
}.RunTaskOnMainThread();
if (new RegistryKeyAction() { KeyName = @"HKCR\CLSID\{a463fcb9-6b1c-4e0d-a80b-a2ca7999e25d}\InprocServer32" }.GetStatus() !=
UninstallTaskStatus.Completed)
@ -275,7 +275,7 @@ namespace TrustedUninstaller.Shared
Arguments =
@"-U:T -P:E -M:S -ShowWindowMode:Hide -Priority:RealTime -Wait reg add ""HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity"" /v Enabled /d 0 /f",
CreateWindow = false
}.RunTask().Wait();
}.RunTaskOnMainThread();
if (new RegistryValueAction() { KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity", Value = "Enabled", Data = 0, }.GetStatus()
!= UninstallTaskStatus.Completed)
@ -302,19 +302,39 @@ namespace TrustedUninstaller.Shared
Arguments =
@"-U:T -P:E -M:S -ShowWindowMode:Hide -Priority:RealTime -Wait reg add ""HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity"" /v Enabled /d 0 /f",
CreateWindow = false
}.RunTask().Wait();
}.RunTaskOnMainThread();
if (new RegistryValueAction() { KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity", Value = "Enabled", Data = 0, }.GetStatus()
!= UninstallTaskStatus.Completed)
ErrorLogger.WriteToErrorLog("Could not disable memory integrity.", null, "Defender disable warning");
}
AmeliorationUtil.SafeRunAction(new RegistryValueAction()
try
{
// Can cause ProcessHacker driver warnings without this
new RegistryValueAction() { KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\CI\Config", Value = "VulnerableDriverBlocklistEnable", Data = 0, }.RunTask().Wait();
if (new RegistryValueAction() { KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\CI\Config", Value = "VulnerableDriverBlocklistEnable", Data = 0, }.GetStatus()
!= UninstallTaskStatus.Completed)
throw new Exception("Unknown error");
}
catch (Exception e)
{
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\CI\Config",
Value = "VulnerableDriverBlocklistEnable",
Data = 0,
}).Wait();
ErrorLogger.WriteToErrorLog("First blocklist disable failed: " + e.GetType() + " " + e.Message, null, "Kernel driver preparation warning");
new RunAction()
{
RawPath = Directory.GetCurrentDirectory(),
Exe = $"NSudoLC.exe",
Arguments =
@"-U:T -P:E -M:S -ShowWindowMode:Hide -Priority:RealTime -Wait reg add ""HKLM\SYSTEM\CurrentControlSet\Control\CI\Config"" /v VulnerableDriverBlocklistEnable /d 0 /f",
CreateWindow = false
}.RunTaskOnMainThread();
if (new RegistryValueAction() { KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\CI\Config", Value = "VulnerableDriverBlocklistEnable", Data = 0, }.GetStatus()
!= UninstallTaskStatus.Completed)
ErrorLogger.WriteToErrorLog("Could not disable blocklist.", null, "Kernel driver preparation error");
}
return restartRequired;
}
@ -491,7 +511,7 @@ namespace TrustedUninstaller.Shared
"net stop WinDefend\"",
CreateWindow = false,
Timeout = 7500,
}.RunTask().Wait();
}.RunTaskOnMainThread();
}
return !Process.GetProcessesByName("MsMpEng").Any();
@ -597,7 +617,7 @@ namespace TrustedUninstaller.Shared
tokenGroups.Groups[idx].Attributes &= ~(uint)PInvoke.SE_GROUP_ATTRIBUTES.SE_GROUP_OWNER;
}
}
Console.WriteLine(tokenGroups.GroupCount);
tokenGroups.Groups[tokenGroups.GroupCount].Sid = tiSid;
tokenGroups.Groups[tokenGroups.GroupCount].Attributes = (uint)PInvoke.SE_GROUP_ATTRIBUTES.SE_GROUP_ENABLED | (uint)PInvoke.SE_GROUP_ATTRIBUTES.SE_GROUP_ENABLED_BY_DEFAULT;
tokenGroups.GroupCount++;


+ 21
- 6
TrustedUninstaller.Shared/Globals.cs View File

@ -9,12 +9,27 @@ namespace TrustedUninstaller.Shared
{
public class Globals
{
public const string CurrentVersion = "0.7.2";
public const double CurrentVersionNumber = 0.72;
#if DEBUG
public static readonly int WinVer = 19045;
#else
public const string CurrentVersion = "0.7.3";
public const double CurrentVersionNumber = 0.73;
public static readonly int WinVer = Int32.Parse(Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion").GetValue("CurrentBuildNumber").ToString());
#endif
private static int _winUpdateVer = -1;
public static int WinUpdateVer
{
get
{
if (_winUpdateVer != -1)
return _winUpdateVer;
try
{
_winUpdateVer = (int)Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion").GetValue("UBR");
}
catch { _winUpdateVer = 0; }
return _winUpdateVer;
}
}
}
}

+ 2
- 1
TrustedUninstaller.Shared/Playbook.cs View File

@ -5,7 +5,6 @@ using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Management.Automation.Runspaces;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
@ -53,6 +52,8 @@ namespace TrustedUninstaller.Shared
public bool Overhaul { get; set; } = false;
public string Path { get; set; }
public bool? UseKernelDriver { get; set; } = null;
public List<string> Options { get; set; } = null;


+ 507
- 0
TrustedUninstaller.Shared/ProcessPrivilege.cs View File

@ -0,0 +1,507 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Win32.SafeHandles;
using TrustedUninstaller.Shared.Actions;
namespace TrustedUninstaller.Shared
{
public class ProcessPrivilege
{
private static Win32.TokensEx.SafeTokenHandle userToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
private static Win32.TokensEx.SafeTokenHandle elevatedUserToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
private static Win32.TokensEx.SafeTokenHandle systemToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
private static Win32.TokensEx.SafeTokenHandle impsersonatedSystemToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
private static Win32.TokensEx.SafeTokenHandle lsassToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
internal static void ResetTokens()
{
elevatedUserToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
lsassToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
systemToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
impsersonatedSystemToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
userToken = new Win32.TokensEx.SafeTokenHandle(IntPtr.Zero);
}
public static void StartPrivilegedTask(AugmentedProcess.Process process, Privilege privilege)
{
var tcs = StartThread(process, privilege);
tcs.Task.Wait();
for (int i = 0; tcs.Task.Result != null && i <= 3; i++)
{
ErrorLogger.WriteToErrorLog("Error launching privileged process: " + tcs.Task.Result.Message, tcs.Task.Result.StackTrace, "PrivilegedProcess Warning",
Path.GetFileName(process.StartInfo.FileName));
ResetTokens();
Thread.Sleep(500 * i);
tcs = StartThread(process, privilege);
tcs.Task.Wait();
}
if (tcs.Task.Result != null)
throw new SecurityException("Error launching privileged process.", tcs.Task.Result);
}
private static TaskCompletionSource<Exception> StartThread(AugmentedProcess.Process process, Privilege privilege)
{
var tcs = new TaskCompletionSource<Exception>();
var thread = new Thread(() =>
{
try
{
switch (privilege)
{
case (Privilege.System):
GetSystemToken();
process.Start(AugmentedProcess.Process.CreateType.RawToken, ref systemToken);
break;
case (Privilege.CurrentUser):
GetUserToken(true);
process.Start(AugmentedProcess.Process.CreateType.UserToken, ref userToken);
break;
case (Privilege.CurrentUserElevated):
GetElevatedUserToken();
process.Start(AugmentedProcess.Process.CreateType.RawToken, ref elevatedUserToken);
break;
default:
throw new ArgumentException("Unexpected.");
}
}
catch (Exception e)
{
tcs.SetResult(e);
return;
}
tcs.SetResult(null);
});
thread.Start();
return tcs;
}
private static uint GetUserSession()
{
var sessionId = Win32.WTS.WTSGetActiveConsoleSessionId();
if (sessionId != 0xFFFFFFFF) return sessionId;
IntPtr pSessionInfo = IntPtr.Zero;
Int32 count = 0;
if (Win32.WTS.WTSEnumerateSessions((IntPtr)null, 0, 1, ref pSessionInfo, ref count) == 0)
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error enumerating user sessions.");
Int32 dataSize = Marshal.SizeOf(typeof(Win32.WTS.WTS_SESSION_INFO));
Int64 current = (Int64)pSessionInfo;
for (int i = 0; i < count; i++)
{
Win32.WTS.WTS_SESSION_INFO si =
(Win32.WTS.WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current,
typeof(Win32.WTS.WTS_SESSION_INFO));
current += dataSize;
if (si.State == Win32.WTS.WTS_CONNECTSTATE_CLASS.WTSActive)
{
sessionId = (uint)si.SessionID;
break;
}
}
Win32.WTS.WTSFreeMemory(pSessionInfo);
return sessionId;
}
private static void GetUserToken(bool getPrivileges)
{
if (getPrivileges)
{
GetSystemToken();
var result = Win32.Tokens.ImpersonateLoggedOnUser(systemToken);
if (!result)
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error impersonating system process token.");
Win32.TokensEx.AdjustCurrentPrivilege(Win32.Tokens.SE_ASSIGNPRIMARYTOKEN_NAME);
Win32.TokensEx.AdjustCurrentPrivilege(Win32.Tokens.SE_INCREASE_QUOTA_NAME);
}
if (userToken.DangerousGetHandle() != IntPtr.Zero)
return;
var sessionId = GetUserSession();
if (Win32.WTS.WTSQueryUserToken(sessionId, out Win32.TokensEx.SafeTokenHandle wtsToken))
{
if (!Win32.Tokens.DuplicateTokenEx(wtsToken, Win32.Tokens.TokenAccessFlags.TOKEN_ALL_ACCESS,
IntPtr.Zero,
Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
Win32.Tokens.TOKEN_TYPE.TokenPrimary, out userToken))
{
throw new Win32Exception(Marshal.GetLastWin32Error(),
"Failed to duplicate process token for lsass.");
}
return;
}
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error fetching active user session token.");
}
private static void GetElevatedUserToken()
{
GetSystemToken();
var result = Win32.Tokens.ImpersonateLoggedOnUser(systemToken);
if (!result)
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error impersonating system process token.");
if (lsassToken.DangerousGetHandle() == IntPtr.Zero)
{
var processHandle = Process.GetProcessesByName("lsass").First().Handle;
if (!Win32.Tokens.OpenProcessToken(processHandle,
Win32.Tokens.TokenAccessFlags.TOKEN_DUPLICATE |
Win32.Tokens.TokenAccessFlags.TOKEN_ASSIGN_PRIMARY |
Win32.Tokens.TokenAccessFlags.TOKEN_QUERY | Win32.Tokens.TokenAccessFlags.TOKEN_IMPERSONATE,
out var tokenHandle))
{
Win32.CloseHandle(processHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to open process token for lsass.");
}
if (!Win32.Tokens.DuplicateTokenEx(tokenHandle, Win32.Tokens.TokenAccessFlags.TOKEN_ALL_ACCESS,
IntPtr.Zero,
Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
Win32.Tokens.TOKEN_TYPE.TokenImpersonation, out lsassToken))
{
Win32.CloseHandle(processHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(),
"Failed to duplicate process token for lsass.");
}
Win32.CloseHandle(processHandle);
}
result = Win32.Tokens.ImpersonateLoggedOnUser(lsassToken);
if (!result)
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error impersonating lsass process token.");
Win32.TokensEx.AdjustCurrentPrivilege(Win32.Tokens.SE_ASSIGNPRIMARYTOKEN_NAME);
Win32.TokensEx.AdjustCurrentPrivilege(Win32.Tokens.SE_INCREASE_QUOTA_NAME);
if (elevatedUserToken.DangerousGetHandle() != IntPtr.Zero)
return;
var privileges = new[]
{
Win32.Tokens.SE_INCREASE_QUOTA_NAME,
Win32.Tokens.SE_MACHINE_ACCOUNT_NAME, Win32.Tokens.SE_SECURITY_NAME,
Win32.Tokens.SE_TAKE_OWNERSHIP_NAME, Win32.Tokens.SE_LOAD_DRIVER_NAME,
Win32.Tokens.SE_SYSTEM_PROFILE_NAME, Win32.Tokens.SE_SYSTEMTIME_NAME,
Win32.Tokens.SE_PROFILE_SINGLE_PROCESS_NAME, Win32.Tokens.SE_INCREASE_BASE_PRIORITY_NAME,
Win32.Tokens.SE_CREATE_PERMANENT_NAME,
Win32.Tokens.SE_BACKUP_NAME, Win32.Tokens.SE_RESTORE_NAME, Win32.Tokens.SE_SHUTDOWN_NAME,
Win32.Tokens.SE_DEBUG_NAME, Win32.Tokens.SE_AUDIT_NAME, Win32.Tokens.SE_SYSTEM_ENVIRONMENT_NAME,
Win32.Tokens.SE_CHANGE_NOTIFY_NAME,
Win32.Tokens.SE_UNDOCK_NAME, Win32.Tokens.SE_SYNC_AGENT_NAME,
Win32.Tokens.SE_ENABLE_DELEGATION_NAME, Win32.Tokens.SE_MANAGE_VOLUME_NAME,
Win32.Tokens.SE_IMPERSONATE_NAME, Win32.Tokens.SE_CREATE_GLOBAL_NAME,
Win32.Tokens.SE_TRUSTED_CREDMAN_ACCESS_NAME, Win32.Tokens.SE_RELABEL_NAME,
Win32.Tokens.SE_TIME_ZONE_NAME,
Win32.Tokens.SE_CREATE_SYMBOLIC_LINK_NAME, Win32.Tokens.SE_DELEGATE_SESSION_USER_IMPERSONATE_NAME
};
var authId = Win32.Tokens.SYSTEM_LUID;
GetUserToken(false);
Win32.Tokens.DuplicateTokenEx(userToken,
Win32.Tokens.TokenAccessFlags.TOKEN_ALL_ACCESS, IntPtr.Zero,
Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, Win32.Tokens.TOKEN_TYPE.TokenPrimary,
out Win32.TokensEx.SafeTokenHandle dupedUserToken);
Win32.SID.AllocateAndInitializeSid(
ref Win32.SID.SECURITY_MANDATORY_LABEL_AUTHORITY,
1,
(int)Win32.SID.SECURITY_MANDATORY_LABEL.High,
0,
0,
0,
0,
0,
0,
0,
out IntPtr integritySid);
var tokenMandatoryLabel = new Win32.Tokens.TOKEN_MANDATORY_LABEL() {
Label = default(Win32.SID.SID_AND_ATTRIBUTES)
};
tokenMandatoryLabel.Label.Attributes = (uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_INTEGRITY;
tokenMandatoryLabel.Label.Sid = integritySid;
var integritySize = Marshal.SizeOf(tokenMandatoryLabel);
var tokenInfo = Marshal.AllocHGlobal(integritySize);
Marshal.StructureToPtr(tokenMandatoryLabel, tokenInfo, false);
Win32.Tokens.SetTokenInformation(
dupedUserToken,
Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenIntegrityLevel,
tokenInfo,
integritySize + Win32.SID.GetLengthSid(integritySid));
var pTokenUser = Win32.TokensEx.GetInfoFromToken(dupedUserToken, Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenUser);
var pTokenOwner =
Win32.TokensEx.GetInfoFromToken(dupedUserToken, Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenOwner);
var pTokenPrivileges =
Win32.TokensEx.GetInfoFromToken(dupedUserToken, Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenPrivileges);
var pTokenGroups =
Win32.TokensEx.GetInfoFromToken(dupedUserToken, Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenGroups);
var pTokenPrimaryGroup =
Win32.TokensEx.GetInfoFromToken(dupedUserToken, Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenPrimaryGroup);
var pTokenDefaultDacl =
Win32.TokensEx.GetInfoFromToken(dupedUserToken, Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenDefaultDacl);
var pTokenSource =
Win32.TokensEx.GetInfoFromToken(dupedUserToken, Win32.Tokens.TOKEN_INFORMATION_CLASS.TokenSource);
var tokenUser =
(Win32.Tokens.TOKEN_USER)Marshal.PtrToStructure(pTokenUser, typeof(Win32.Tokens.TOKEN_USER));
if (!Win32.TokensEx.CreateTokenPrivileges(privileges, out var tokenPrivileges))
tokenPrivileges =
(Win32.Tokens.TOKEN_PRIVILEGES)Marshal.PtrToStructure(pTokenPrivileges,
typeof(Win32.Tokens.TOKEN_PRIVILEGES));
var tokenGroups = (Win32.Tokens.TOKEN_GROUPS)Marshal.PtrToStructure(
pTokenGroups, typeof(Win32.Tokens.TOKEN_GROUPS));
var tokenOwner =
(Win32.Tokens.TOKEN_OWNER)Marshal.PtrToStructure(pTokenOwner, typeof(Win32.Tokens.TOKEN_OWNER));
var tokenPrimaryGroup =
(Win32.Tokens.TOKEN_PRIMARY_GROUP)Marshal.PtrToStructure(pTokenPrimaryGroup,
typeof(Win32.Tokens.TOKEN_PRIMARY_GROUP));
var tokenDefaultDacl = (Win32.Tokens.TOKEN_DEFAULT_DACL)Marshal.PtrToStructure(
pTokenDefaultDacl, typeof(Win32.Tokens.TOKEN_DEFAULT_DACL));
var tokenSource = (Win32.Tokens.TOKEN_SOURCE)Marshal.PtrToStructure(
pTokenSource, typeof(Win32.Tokens.TOKEN_SOURCE));
/*
for (var idx = 0; idx < tokenPrivileges.PrivilegeCount - 1; idx++)
{
if ((tokenPrivileges.Privileges[idx].Attributes &
(uint)Win32.Tokens.SE_PRIVILEGE_ATTRIBUTES.SE_PRIVILEGE_ENABLED) != 0)
{
}
if ((tokenPrivileges.Privileges[idx].Attributes &
(uint)Win32.Tokens.SE_PRIVILEGE_ATTRIBUTES.SE_PRIVILEGE_ENABLED_BY_DEFAULT) != 0)
{
}
}
*/
IntPtr adminsSid = IntPtr.Zero;
IntPtr localAndAdminSid = IntPtr.Zero;
bool adminsFound = false;
bool localAndAdminFound = false;
for (var idx = 0; idx < tokenGroups.GroupCount - 1; idx++)
{
Win32.SID.ConvertSidToStringSid(tokenGroups.Groups[idx].Sid, out string strSid);
if (string.Compare(strSid, Win32.SID.DOMAIN_ALIAS_RID_ADMINS, StringComparison.OrdinalIgnoreCase) == 0)
{
adminsFound = true;
tokenGroups.Groups[idx].Attributes = (uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_ENABLED |
(uint)Win32.Tokens.SE_GROUP_ATTRIBUTES
.SE_GROUP_ENABLED_BY_DEFAULT | (uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_MANDATORY | (uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_OWNER;
} else if (string.Compare(strSid, Win32.SID.DOMAIN_ALIAS_RID_LOCAL_AND_ADMIN_GROUP, StringComparison.OrdinalIgnoreCase) == 0)
{
localAndAdminFound = true;
tokenGroups.Groups[idx].Attributes = (uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_ENABLED |
(uint)Win32.Tokens.SE_GROUP_ATTRIBUTES
.SE_GROUP_ENABLED_BY_DEFAULT | (uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_MANDATORY;
}
}
if (!adminsFound)
{
Win32.SID.ConvertStringSidToSid(Win32.SID.DOMAIN_ALIAS_RID_ADMINS, out adminsSid);
tokenGroups.Groups[tokenGroups.GroupCount].Sid = adminsSid;
tokenGroups.Groups[tokenGroups.GroupCount].Attributes =
(uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_ENABLED |
(uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_ENABLED_BY_DEFAULT;
tokenGroups.GroupCount++;
}
if (!localAndAdminFound)
{
Win32.SID.ConvertStringSidToSid(Win32.SID.DOMAIN_ALIAS_RID_LOCAL_AND_ADMIN_GROUP, out localAndAdminSid);
tokenGroups.Groups[tokenGroups.GroupCount].Sid = localAndAdminSid;
tokenGroups.Groups[tokenGroups.GroupCount].Attributes =
(uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_ENABLED |
(uint)Win32.Tokens.SE_GROUP_ATTRIBUTES.SE_GROUP_ENABLED_BY_DEFAULT;
tokenGroups.GroupCount++;
}
var expirationTime = new Win32.LARGE_INTEGER() { QuadPart = -1L };
var sqos = new Win32.Tokens.SECURITY_QUALITY_OF_SERVICE(
Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, Win32.Tokens.SECURITY_STATIC_TRACKING,
0);
var oa = new Win32.Tokens.OBJECT_ATTRIBUTES(string.Empty, 0) { };
var pSqos = Marshal.AllocHGlobal(Marshal.SizeOf(sqos));
Marshal.StructureToPtr(sqos, pSqos, true);
oa.SecurityQualityOfService = pSqos;
var status = Win32.Tokens.ZwCreateToken(out elevatedUserToken,
Win32.Tokens.TokenAccessFlags.TOKEN_ALL_ACCESS, ref oa, Win32.Tokens.TOKEN_TYPE.TokenPrimary,
ref authId, ref expirationTime, ref tokenUser, ref tokenGroups, ref tokenPrivileges, ref tokenOwner,
ref tokenPrimaryGroup, ref tokenDefaultDacl, ref tokenSource);
Win32.LocalFree(pTokenUser);
Win32.LocalFree(pTokenOwner);
Win32.LocalFree(pTokenGroups);
Win32.LocalFree(pTokenDefaultDacl);
Win32.LocalFree(pTokenPrivileges);
Win32.LocalFree(pTokenPrimaryGroup);
if (adminsSid != IntPtr.Zero)
Win32.SID.FreeSid(adminsSid);
if (localAndAdminSid != IntPtr.Zero)
Win32.SID.FreeSid(localAndAdminSid);
if (integritySid != IntPtr.Zero)
Win32.SID.FreeSid(integritySid);
if (status != 0)
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error creating elevated user token: " + status);
}
public static void GetSystemToken()
{
if (systemToken.DangerousGetHandle() != IntPtr.Zero)
return;
try
{
var processHandle = Process.GetProcessesByName("winlogon").First().Handle;
if (!Win32.Tokens.OpenProcessToken(processHandle,
Win32.Tokens.TokenAccessFlags.TOKEN_DUPLICATE | Win32.Tokens.TokenAccessFlags.TOKEN_ASSIGN_PRIMARY |
Win32.Tokens.TokenAccessFlags.TOKEN_QUERY | Win32.Tokens.TokenAccessFlags.TOKEN_IMPERSONATE,
out var tokenHandle))
{
Win32.CloseHandle(processHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to open process token for winlogon.");
}
if (!Win32.Tokens.DuplicateTokenEx(tokenHandle, Win32.Tokens.TokenAccessFlags.TOKEN_ALL_ACCESS, IntPtr.Zero,
Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
Win32.Tokens.TOKEN_TYPE.TokenPrimary, out systemToken))
{
Win32.CloseHandle(processHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(),
"Failed to duplicate process token for winlogon.");
}
Win32.CloseHandle(processHandle);
}
catch (Exception e)
{
var sessionId = GetUserSession();
int dwLsassPID = -1;
int dwWinLogonPID = -1;
Win32.WTS.WTS_PROCESS_INFO[] pProcesses;
IntPtr pProcessInfo = IntPtr.Zero;
int dwProcessCount = 0;
if (Win32.WTS.WTSEnumerateProcesses((IntPtr)null, 0, 1, ref pProcessInfo, ref dwProcessCount))
{
IntPtr pMemory = pProcessInfo;
pProcesses = new Win32.WTS.WTS_PROCESS_INFO[dwProcessCount];
for (int i = 0; i < dwProcessCount; i++)
{
pProcesses[i] =
(Win32.WTS.WTS_PROCESS_INFO)Marshal.PtrToStructure(pProcessInfo,
typeof(Win32.WTS.WTS_PROCESS_INFO));
pProcessInfo = (IntPtr)((long)pProcessInfo + Marshal.SizeOf(pProcesses[i]));
var processName = Marshal.PtrToStringAnsi(pProcesses[i].ProcessName);
Win32.SID.ConvertSidToStringSid(pProcesses[i].UserSid, out string sid);
string strSid;
if (processName == null || pProcesses[i].UserSid == default || sid != "S-1-5-18") continue;
if ((-1 == dwLsassPID) && (0 == pProcesses[i].SessionID) && (processName == "lsass.exe"))
{
dwLsassPID = pProcesses[i].ProcessID;
continue;
}
if ((-1 == dwWinLogonPID) && (sessionId == pProcesses[i].SessionID) &&
(processName == "winlogon.exe"))
{
dwWinLogonPID = pProcesses[i].ProcessID;
continue;
}
}
Win32.WTS.WTSFreeMemory(pMemory);
}
IntPtr systemProcessHandle = IntPtr.Zero;
try
{
systemProcessHandle = Process.GetProcessById(dwLsassPID).Handle;
}
catch
{
systemProcessHandle = Process.GetProcessById(dwWinLogonPID).Handle;
}
if (!Win32.Tokens.OpenProcessToken(systemProcessHandle, Win32.Tokens.TokenAccessFlags.TOKEN_DUPLICATE,
out Win32.TokensEx.SafeTokenHandle token))
{
Win32.CloseHandle(systemProcessHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to open process token.");
}
if (!Win32.Tokens.DuplicateTokenEx(token, Win32.Tokens.TokenAccessFlags.MAXIMUM_ALLOWED, IntPtr.Zero,
Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
Win32.Tokens.TOKEN_TYPE.TokenPrimary, out systemToken))
{
Win32.CloseHandle(systemProcessHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to duplicate process token.");
}
Win32.CloseHandle(systemProcessHandle);
}
}
public static Win32.TokensEx.SafeTokenHandle GetCurrentProcessToken()
{
if (!Win32.Tokens.OpenProcessToken(Win32.Process.GetCurrentProcess(),
Win32.Tokens.TokenAccessFlags.TOKEN_READ, out Win32.TokensEx.SafeTokenHandle token))
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error opening token for current process.");
return token;
}
private static Win32.TokensEx.SafeTokenHandle GetProcessTokenByName(string name, bool impersonation)
{
var processHandle = Process.GetProcessesByName(name).First().Handle;
if (!Win32.Tokens.OpenProcessToken(processHandle,
Win32.Tokens.TokenAccessFlags.TOKEN_DUPLICATE | Win32.Tokens.TokenAccessFlags.TOKEN_ASSIGN_PRIMARY |
Win32.Tokens.TokenAccessFlags.TOKEN_QUERY | Win32.Tokens.TokenAccessFlags.TOKEN_IMPERSONATE,
out var tokenHandle))
{
Win32.CloseHandle(processHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to open process token for " + name + ".");
}
if (!Win32.Tokens.DuplicateTokenEx(tokenHandle, Win32.Tokens.TokenAccessFlags.TOKEN_ALL_ACCESS, IntPtr.Zero,
impersonation ? Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation : Win32.Tokens.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
impersonation ? Win32.Tokens.TOKEN_TYPE.TokenImpersonation : Win32.Tokens.TOKEN_TYPE.TokenPrimary, out Win32.TokensEx.SafeTokenHandle handle))
{
Win32.CloseHandle(processHandle);
throw new Win32Exception(Marshal.GetLastWin32Error(),
"Failed to duplicate process token for " + name + ".");
}
Win32.CloseHandle(processHandle);
return handle;
} }
}

+ 1
- 0
TrustedUninstaller.Shared/Tasks/ITaskAction.cs View File

@ -20,5 +20,6 @@ namespace TrustedUninstaller.Shared.Tasks
public string ErrorString();
public UninstallTaskStatus GetStatus();
public Task<bool> RunTask();
public void RunTaskOnMainThread();
}
}

+ 8
- 0
TrustedUninstaller.Shared/Tasks/TaskAction.cs View File

@ -6,8 +6,16 @@ namespace TrustedUninstaller.Shared.Tasks
{
[YamlMember(typeof(bool), Alias = "ignoreErrors")]
public bool IgnoreErrors { get; set; } = false;
[YamlMember(typeof(string), Alias = "option")]
public string Option { get; set; } = null;
[YamlMember(typeof(string[]), Alias = "options")]
public string[] Options { get; set; } = null;
[YamlMember(typeof(string[]), Alias = "builds")]
public string[] Builds { get; set; } = null;
[YamlMember(typeof(string), Alias = "cpuArch")]
public string Arch { get; set; } = null;
}


+ 9
- 0
TrustedUninstaller.Shared/Tasks/UninstallTask.cs View File

@ -24,6 +24,15 @@ namespace TrustedUninstaller.Shared.Tasks
public int Priority { get; set; } = 1;
public UninstallTaskPrivilege Privilege { get; set; } = UninstallTaskPrivilege.Admin;
[YamlMember(typeof(string), Alias = "option")]
public string Option { get; set; } = null;
[YamlMember(typeof(string[]), Alias = "options")]
public string[] Options { get; set; } = null;
[YamlMember(typeof(string[]), Alias = "builds")]
public string[] Builds { get; set; } = null;
[YamlMember(typeof(string), Alias = "cpuArch")]
public string Arch { get; set; } = null;
public List<string> Features { get; set; } = new List<string>();


+ 21
- 13
TrustedUninstaller.Shared/TrustedUninstaller.Shared.csproj View File

@ -51,14 +51,21 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>SINGLE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug Single File|x64' ">
<OutputPath>bin\x64\Release\</OutputPath>
<PlatformTarget>x64</PlatformTarget>
<Optimize>true</Optimize>
<DebugType>embedded</DebugType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>SINGLE;DEBUG</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Core" />
<Reference Include="System.DirectoryServices" />
<Reference Include="System.DirectoryServices.AccountManagement" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Compression, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Private>True</Private>
@ -67,10 +74,7 @@
<Reference Include="System.Net.Http" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="YamlDotNet">
<HintPath>..\TrustedUninstaller.GUI\bin\x64\Release\YamlDotNet.dll</HintPath>
@ -95,10 +99,13 @@
<Compile Include="Actions\UserAction.cs" />
<Compile Include="Actions\WriteStatusAction.cs" />
<Compile Include="AmeliorationUtil.cs" />
<Compile Include="AugmentedProcess.cs" />
<Compile Include="Debug.cs" />
<Compile Include="Defender.cs" />
<Compile Include="DualOut.cs" />
<Compile Include="Globals.cs" />
<Compile Include="Playbook.cs" />
<Compile Include="ProcessPrivilege.cs" />
<Compile Include="ProviderStatus.cs" />
<Compile Include="ErrorLogger.cs" />
<Compile Include="Exceptions\InvalidRegistryEntryException.cs" />
@ -113,6 +120,7 @@
<Compile Include="Tasks\ITaskAction.cs" />
<Compile Include="Tasks\UninstallTaskStatus.cs" />
<Compile Include="Tasks\UninstallTask.cs" />
<Compile Include="Win32.cs" />
<Compile Include="WinUtil.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
@ -131,11 +139,11 @@
<WCFMetadata Include="Connected Services\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.PowerShell.5.ReferenceAssemblies" Version="1.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.IO" Version="4.3.0" />
<PackageReference Include="System.IO.FileSystem" Version="4.3.0" />
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Runtime" Version="4.3.0" />
<PackageReference Include="System.Security.Cryptography.Algorithms" Version="4.3.1" />
<PackageReference Include="System.Security.Cryptography.Encoding" Version="4.3.0" />
@ -156,16 +164,16 @@
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Single File|x64' ">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Single File|x64' Or '$(Configuration)|$(Platform)' == 'Debug Single File|x64' ">
<PostBuildEvent>for /f "usebackq delims=" %%A in (`DIR /B /S /A:d "$(SolutionDir)" ^| FINDSTR /R /c:".*\\bin\\.*\\de$" /c:".*\\bin\\.*\\en$" /c:".*\\bin\\.*\\es$" /c:".*\\bin\\.*\\fr$" /c:".*\\bin\\.*\\it$" /c:".*\\bin\\.*\\ja$" /c:".*\\bin\\.*\\ko$" /c:".*\\bin\\.*\\ru$" /c:".*\\bin\\.*\\zh-Hans$" /c:".*\\bin\\.*\\zh-Hant$" /c:".*\\bin\\.*\\pl$" /c:".*\\bin\\.*\\zh-CN$"`) do (RMDIR /Q /S "%%A" &amp; cmd /c "exit /b 0")
cmd /c "echo Compiled&gt; "$(SolutionDir)\TrustedUninstaller.GUI\gui-builder\Compiled.txt""
PowerShell -NoP -C "Start-Process '$(SolutionDir)\TrustedUninstaller.GUI\gui-builder\ame-builder.exe' -ArgumentList 'Shared','""""x64\$(Configuration)""""' -NoNewWindow -Wait"
</PostBuildEvent>
<AllowedReferenceRelatedFileExtensions>
<!-- Prevent default XML files copied to output.-->
.allowedextension
</AllowedReferenceRelatedFileExtensions>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Single File|x64' ">
<PreBuildEvent>PowerShell -NoP -C "Get-Process 'ame-builder' -EA SilentlyContinue | Wait-Process -EA SilentlyContinue; EXIT 0"
PowerShell -NoP -C "Start-Process '$(SolutionDir)\TrustedUninstaller.GUI\gui-builder\ame-builder.exe' -ArgumentList 'Shared' -WindowStyle Hidden"</PreBuildEvent>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' != 'Single File|x64' ">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' != 'Single File|x64' And '$(Configuration)|$(Platform)' != 'Debug Single File|x64' ">
<PostBuildEvent>for /f "usebackq delims=" %%A in (`DIR /B /S /A:d "$(SolutionDir)" ^| FINDSTR /R /c:".*\\bin\\.*\\de$" /c:".*\\bin\\.*\\en$" /c:".*\\bin\\.*\\es$" /c:".*\\bin\\.*\\fr$" /c:".*\\bin\\.*\\it$" /c:".*\\bin\\.*\\ja$" /c:".*\\bin\\.*\\ko$" /c:".*\\bin\\.*\\ru$" /c:".*\\bin\\.*\\zh-Hans$" /c:".*\\bin\\.*\\zh-Hant$" /c:".*\\bin\\.*\\pl$" /c:".*\\bin\\.*\\zh-CN$"`) do (RMDIR /Q /S "%%A" &amp; cmd /c "exit /b 0")</PostBuildEvent>
</PropertyGroup>
</Project>

+ 1699
- 0
TrustedUninstaller.Shared/Win32.cs
File diff suppressed because it is too large
View File


+ 52
- 25
TrustedUninstaller.Shared/WinUtil.cs View File

@ -5,7 +5,6 @@ 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;
@ -18,6 +17,7 @@ using System.Windows;
using System.Windows.Interop;
using Microsoft.Win32;
using TrustedUninstaller.Shared.Actions;
using TrustedUninstaller.Shared.Tasks;
namespace TrustedUninstaller.Shared
{
@ -444,7 +444,7 @@ namespace TrustedUninstaller.Shared
if (res == ERROR_MORE_DATA)
{
// Create an array to store the process results
RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded];
RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded + 3];
pnProcInfo = pnProcInfoNeeded;
// Get the list
@ -465,7 +465,7 @@ namespace TrustedUninstaller.Shared
catch (ArgumentException) { }
}
}
else throw new Exception("Could not list processes locking resource.");
else throw new Exception("Could not list processes locking resource: " + res);
}
else if (res != 0)
throw new Exception("Could not list processes locking resource. Could not get size of result." + $" Result value: {res}");
@ -609,37 +609,60 @@ namespace TrustedUninstaller.Shared
public static async Task RemoveProtectionAsync()
{
var cmdAction = new CmdAction();
if (!IsVCInstalled())
if (AmeliorationUtil.UseKernelDriver)
{
Console.WriteLine(Environment.NewLine + "Installing VC 15...");
/*
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";
cmdAction.RunTaskOnMainThread();
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "Error while installing VC 15.");
throw;
}
}
*/
try
{
//Install Visual C++ 2015 redistributable package silently
cmdAction.Command = "vc_redist.x64.exe /q /norestart";
await cmdAction.RunTask();
Console.WriteLine(Environment.NewLine + "Installing driver...");
cmdAction.Command = Environment.Is64BitOperatingSystem
? $"ProcessHacker\\x64\\ProcessHacker.exe -s -installkph"
: $"ProcessHacker\\x86\\ProcessHacker.exe -s -installkph";
cmdAction.RunTaskOnMainThread();
await AmeliorationUtil.SafeRunAction(new RegistryValueAction()
{ KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\KProcessHacker2", Value = "DeleteFlag", Type = RegistryValueType.REG_DWORD, Data = 1 });
}
catch (Exception e)
{
ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "Error while installing VC 15.");
ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "ProcessHacker ran into an error while installing its driver.");
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;
}
public static async void CheckKph()
{
if (!AmeliorationUtil.UseKernelDriver || new RegistryKeyAction() { KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\KProcessHacker2", Operation = RegistryKeyOperation.Add }.GetStatus() == UninstallTaskStatus.Completed)
return;
Console.WriteLine(Environment.NewLine + "Installing driver...");
var cmdAction = new CmdAction();
cmdAction.Command = Environment.Is64BitOperatingSystem
? $"ProcessHacker\\x64\\ProcessHacker.exe -s -installkph"
: $"ProcessHacker\\x86\\ProcessHacker.exe -s -installkph";
cmdAction.RunTaskOnMainThread();
await AmeliorationUtil.SafeRunAction(new RegistryValueAction()
{ KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\KProcessHacker2", Value = "DeleteFlag", Type = RegistryValueType.REG_DWORD, Data = 1 });
}
private const int GWL_STYLE = -16;
@ -686,6 +709,10 @@ namespace TrustedUninstaller.Shared
public static async Task UninstallDriver()
{
if (AmeliorationUtil.UseKernelDriver == false)
return;
AmeliorationUtil.UseKernelDriver = false;
CmdAction cmdAction = new CmdAction();
try
{
@ -693,7 +720,7 @@ namespace TrustedUninstaller.Shared
cmdAction.Command = Environment.Is64BitOperatingSystem
? $"ProcessHacker\\x64\\ProcessHacker.exe -s -uninstallkph"
: $"ProcessHacker\\x86\\ProcessHacker.exe -s -uninstallkph";
await cmdAction.RunTask();
cmdAction.RunTaskOnMainThread();
}
catch (Exception e)
{


Loading…
Cancel
Save