Skip to content

Commit

Permalink
Added support for catalog signed files in local file scans in the App…
Browse files Browse the repository at this point in the history
…Control Manager (#533)

Added support for catalog signed files in local file scans. This is a prerequisite for a successful local driver scans since the majority of them are catalog signed. This also improves the overall accuracy of all file scans in the AppControl Manager.

Added support for catalog signed files to the View File Certificates page.
  • Loading branch information
HotCakeX authored Jan 16, 2025
1 parent 6a03164 commit 30dfe20
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 33 deletions.
56 changes: 56 additions & 0 deletions AppControl Manager/IntelGathering/LocalFilesScan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,31 @@ internal static class LocalFilesScan
internal static HashSet<FileIdentity> Scan(List<FileInfo> files, ushort scalability, ProgressBar? UIProgressBar, ProgressRing? UIProgressRing)
{

// A dictionary where each key is a hash and value is the .Cat file path where the hash was found in
Dictionary<string, string> AllSecurityCatalogHashes = [];

// Get the .cat files in the CatRoot directory
List<FileInfo> detectedCatFiles = FileUtility.GetFilesFast([new DirectoryInfo(@"C:\Windows\System32\CatRoot")], null, [".cat"]);

Logger.Write($"Including {detectedCatFiles.Count} Security Catalogs in the scan process");

foreach (FileInfo file in detectedCatFiles)
{
// Get the hashes of the security catalog file
HashSet<string> catHashes = MeowParser.GetHashes(file.FullName);

// If the security catalog file has hashes, then add them to the dictionary
if (catHashes.Count > 0)
{
foreach (string hash in catHashes)
{
_ = AllSecurityCatalogHashes.TryAdd(hash, file.FullName);
}
}
}



// Store the output of all of the parallel tasks in this
ConcurrentDictionary<FileInfo, FileIdentity> temporaryOutput = [];

Expand Down Expand Up @@ -124,6 +149,37 @@ internal static HashSet<FileIdentity> Scan(List<FileInfo> files, ushort scalabil
fileIsSigned = true;
}

// If the file doesn't have certificates in itself, check for catalog signers
else if (AllSecurityCatalogHashes.TryGetValue(fileHashes.SHa1Authenticode!, out string? CurrentFilePathHashSHA1CatResult))
{
try
{
FileSignatureResults = AllCertificatesGrabber.GetAllFileSigners(CurrentFilePathHashSHA1CatResult);
}
catch (HashMismatchInCertificateException)
{
Logger.Write($"The file '{file.FullName}' has hash mismatch.");
}
}
else if (AllSecurityCatalogHashes.TryGetValue(fileHashes.SHA256Authenticode!, out string? CurrentFilePathHashSHA256CatResult))
{
try
{
FileSignatureResults = AllCertificatesGrabber.GetAllFileSigners(CurrentFilePathHashSHA256CatResult);
}
catch (HashMismatchInCertificateException)
{
Logger.Write($"The file '{file.FullName}' has hash mismatch.");
}
}

// Check the signatures again
if (FileSignatureResults.Count > 0)
{
fileIsSigned = true;
}


#endregion

FileIdentity currentFileIdentity = new()
Expand Down
9 changes: 1 addition & 8 deletions AppControl Manager/MyRoots.xml
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
<linker>
<assembly fullname="CommunityToolkit.WinUI.Extensions" preserve="all" />
<assembly fullname="CommunityToolkit.WinUI.UI.Controls.DataGrid" preserve="all" />
<assembly fullname="Microsoft.Web.WebView2.Core.Projection" preserve="all" />
<assembly fullname="Microsoft.Windows.SDK.NET" preserve="all" />
<assembly fullname="Microsoft.Xaml.Interactions" preserve="all" />
<assembly fullname="System.CodeDom" preserve="all" />
<assembly fullname="System.Management" preserve="all" />
<assembly fullname="WinRT.Runtime" preserve="all" />
<assembly fullname="CommunityToolkit.WinUI.UI.Controls.DataGrid" preserve="all"/>
</linker>
14 changes: 0 additions & 14 deletions AppControl Manager/Others/MeowOpener.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Xml;

namespace AppControlManager.Others;

Expand Down Expand Up @@ -55,13 +54,6 @@ internal static HashSet<string> GetHashes(string SecurityCatalogFilePath)
// Initializes a new HashSet to store the hashes.
HashSet<string> OutputHashSet = [];

// Creates a new XmlDocument instance.
XmlDocument PurrfectCatalogXMLDoc = new()
{
// Disables the XML resolver for security reasons.
XmlResolver = null
};

IntPtr MainCryptProviderHandle = IntPtr.Zero; // Initializes the handle to zero.
IntPtr MeowLogHandle = IntPtr.Zero; // Initializes the catalog context handle to zero.
IntPtr KittyPointer = IntPtr.Zero; // Pointer to iterate through catalog members, initialized to zero.
Expand All @@ -87,12 +79,6 @@ internal static HashSet<string> GetHashes(string SecurityCatalogFilePath)
Logger.Write($"CryptCATOpen failed with error code: {lastWin32Error}");
}

// Creates an XML element to represent the catalog file.
XmlElement catalogElement = PurrfectCatalogXMLDoc.CreateElement("MeowFile");

// Appends the element to the XML document.
_ = PurrfectCatalogXMLDoc.AppendChild(catalogElement);

// Iterates through the catalog members.
while ((KittyPointer = WinTrust.CryptCATEnumerateMember(MeowLogHandle, KittyPointer)) != IntPtr.Zero)
{
Expand Down
12 changes: 6 additions & 6 deletions AppControl Manager/Pages/CreateSupplementalPolicy.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -509,25 +509,25 @@ Style="{StaticResource AccentButtonStyle}" Margin="0,0,15,0" Click="StrictKernel


<controls:SettingsCard x:Name="StrictKernelModeAutoDetectAllDriversSettingsCard" Description="Automatically detect and list all of the drivers on the system"
Header="Auto Driver Detection"
IsClickEnabled="True" IsActionIconVisible="False" Click="StrictKernelModeAutoDetectAllDriversSettingsCard_Click">
Header="Auto Driver Detection"
IsClickEnabled="True" IsActionIconVisible="False" Click="StrictKernelModeAutoDetectAllDriversSettingsCard_Click">

<Button x:Name="StrictKernelModeAutoDetectAllDriversButton" Content="Begin" Click="StrictKernelModeAutoDetectAllDriversButton_Click" />

</controls:SettingsCard>

<controls:SettingsCard x:Name="StrictKernelModeScanButtonSettingsCard" Description="Scan the event logs for Kernel-mode files only"
Header="Scan Event Logs"
IsClickEnabled="False" IsActionIconVisible="False" >
Header="Scan Event Logs"
IsClickEnabled="False" IsActionIconVisible="False" >

<controls:WrapPanel Orientation="Vertical" HorizontalSpacing="10" VerticalSpacing="10">

<Button x:Name="StrictKernelModeScanButton" Click="StrictKernelModeScanButton_Click" HorizontalAlignment="Center" Content="Scan for All Kernel-mode Logs" />

<Button x:Name="StrictKernelModeScanSinceLastRebootButton" Click="StrictKernelModeScanSinceLastRebootButton_Click" HorizontalAlignment="Center" Content="Scan for Kernel-mode Logs Since Last Reboot" />

</controls:WrapPanel>

</controls:SettingsCard>


Expand Down
8 changes: 6 additions & 2 deletions AppControl Manager/Pages/CreateSupplementalPolicy.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1383,7 +1383,7 @@ private async void StrictKernelModeCreateButton_Click(object sender, RoutedEvent
{
StrictKernelModeCreateButton.IsEnabled = false;
StrictKernelModeDeployToggleButton.IsEnabled = false;
StrictKernelModeAutoDetectAllDriversSettingsCard.IsEnabled = false;
StrictKernelModeAutoDetectAllDriversSettingsCard.IsClickEnabled = false;
StrictKernelModeAutoDetectAllDriversButton.IsEnabled = false;
StrictKernelModeScanButton.IsEnabled = false;
StrictKernelModeScanSinceLastRebootButton.IsEnabled = false;
Expand Down Expand Up @@ -1489,7 +1489,7 @@ await Task.Run(() =>

StrictKernelModeCreateButton.IsEnabled = true;
StrictKernelModeDeployToggleButton.IsEnabled = true;
StrictKernelModeAutoDetectAllDriversSettingsCard.IsEnabled = true;
StrictKernelModeAutoDetectAllDriversSettingsCard.IsClickEnabled = true;
StrictKernelModeAutoDetectAllDriversButton.IsEnabled = true;
StrictKernelModeScanButton.IsEnabled = true;
StrictKernelModeScanSinceLastRebootButton.IsEnabled = true;
Expand Down Expand Up @@ -1522,6 +1522,8 @@ private async void DriverAutoDetector()
StrictKernelModeAutoDetectAllDriversButton.IsEnabled = false;
StrictKernelModeScanButton.IsEnabled = false;
StrictKernelModeScanSinceLastRebootButton.IsEnabled = false;
StrictKernelModeAutoDetectAllDriversSettingsCard.IsClickEnabled = false;
StrictKernelModeCreateButton.IsEnabled = false;

StrictKernelModeInfoBar.IsClosable = false;
StrictKernelModeInfoBar.IsOpen = true;
Expand Down Expand Up @@ -1625,6 +1627,8 @@ await Task.Run(() =>
StrictKernelModeAutoDetectAllDriversButton.IsEnabled = true;
StrictKernelModeScanButton.IsEnabled = true;
StrictKernelModeScanSinceLastRebootButton.IsEnabled = true;
StrictKernelModeAutoDetectAllDriversSettingsCard.IsClickEnabled = true;
StrictKernelModeCreateButton.IsEnabled = true;
}
}

Expand Down
8 changes: 8 additions & 0 deletions AppControl Manager/Pages/ViewFileCertificates.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@

</controls:SettingsCard>

<controls:SettingsCard Description="Many files are signed using Security Catalogs. Enabling this option ensures accurate results. Security Catalogs are processed only once and reused in subsequent checks, enhancing performance."
x:Name="IncludeSecurityCatalogsSettingsCard"
Header="Include Catalog Signers" Click="IncludeSecurityCatalogsSettingsCard_Click" IsClickEnabled="True" IsActionIconVisible="False">

<ToggleSwitch x:Name="IncludeSecurityCatalogsToggleSwitch" IsOn="True" />

</controls:SettingsCard>

</StackPanel>


Expand Down
84 changes: 82 additions & 2 deletions AppControl Manager/Pages/ViewFileCertificates.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using AppControlManager.Main;
using AppControlManager.Others;
using AppControlManager.SimulationMethods;
using Microsoft.UI.Xaml;
Expand All @@ -23,7 +24,7 @@ public ViewFileCertificates()
this.InitializeComponent();

// Make sure navigating to/from this page maintains its state
this.NavigationCacheMode = NavigationCacheMode.Enabled;
this.NavigationCacheMode = NavigationCacheMode.Required;
}

// Main collection assigned to the DataGrid
Expand All @@ -32,6 +33,36 @@ public ViewFileCertificates()
// Collection used during search
private ObservableCollection<FileCertificateInfoCol> FilteredCertificates = [];

// A dictionary where each key is a hash and value is the .Cat file path where the hash was found in
private readonly Dictionary<string, string> AllSecurityCatalogHashes = [];

private bool SecurityCatalogsWereCached;

private void GatherSecurityCatalogs()
{

// Get the .cat files in the CatRoot directory
List<FileInfo> detectedCatFiles = FileUtility.GetFilesFast([new DirectoryInfo(@"C:\Windows\System32\CatRoot")], null, [".cat"]);

Logger.Write($"Including {detectedCatFiles.Count} Security Catalogs in the file certificate acquisition process");

foreach (FileInfo file in detectedCatFiles)
{
// Get the hashes of the security catalog file
HashSet<string> catHashes = MeowParser.GetHashes(file.FullName);

// If the security catalog file has hashes, then add them to the dictionary
if (catHashes.Count > 0)
{
foreach (string hash in catHashes)
{
_ = AllSecurityCatalogHashes.TryAdd(hash, file.FullName);
}
}
}
}



/// <summary>
/// Event handler for the Browse button
Expand Down Expand Up @@ -251,16 +282,60 @@ await Task.Run(() =>
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
private static async Task<List<FileCertificateInfoCol>> Fetch(string file)
private async Task<List<FileCertificateInfoCol>> Fetch(string file)
{
// A List to return at the end
List<FileCertificateInfoCol> output = [];

// Query the UI toggle switch
bool shouldProcessSecurityCats = IncludeSecurityCatalogsToggleSwitch.IsOn;

await Task.Run(() =>
{
// Get all of the file's certificates
List<AllFileSigners> signerDetails = AllCertificatesGrabber.GetAllFileSigners(file);

// If the file has no signers and the user wants to include security catalogs
if (signerDetails.Count is 0 && shouldProcessSecurityCats)
{
// Process the security catalogs if they haven't been processed
if (!SecurityCatalogsWereCached)
{
GatherSecurityCatalogs();
SecurityCatalogsWereCached = true;
}

// Grab the file's Code Integrity hashes
CodeIntegrityHashes fileHashes = CiFileHash.GetCiFileHashes(file);


if (AllSecurityCatalogHashes.TryGetValue(fileHashes.SHa1Authenticode!, out string? CurrentFilePathHashSHA1CatResult))
{
try
{
signerDetails = AllCertificatesGrabber.GetAllFileSigners(CurrentFilePathHashSHA1CatResult);
}
catch (HashMismatchInCertificateException)
{
Logger.Write($"The file '{file}' has hash mismatch.");
}
}
else if (AllSecurityCatalogHashes.TryGetValue(fileHashes.SHA256Authenticode!, out string? CurrentFilePathHashSHA256CatResult))
{
try
{
signerDetails = AllCertificatesGrabber.GetAllFileSigners(CurrentFilePathHashSHA256CatResult);
}
catch (HashMismatchInCertificateException)
{
Logger.Write($"The file '{file}' has hash mismatch.");
}
}

}



// Get full chains of all of the file's certificates
List<ChainPackage> result = GetCertificateDetails.Get([.. signerDetails]);

Expand Down Expand Up @@ -515,4 +590,9 @@ private void SearchBox_TextChanged(object sender, TextChangedEventArgs e)
FileCertificatesDataGrid.ItemsSource = FilteredCertificates;
}


private void IncludeSecurityCatalogsSettingsCard_Click(object sender, RoutedEventArgs e)
{
IncludeSecurityCatalogsToggleSwitch.IsOn = !IncludeSecurityCatalogsToggleSwitch.IsOn;
}
}
2 changes: 1 addition & 1 deletion AppControl Manager/global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "9.0.101",
"version": "9.0.1",
"rollForward": "latestMajor",
"allowPrerelease": true
}
Expand Down

0 comments on commit 30dfe20

Please sign in to comment.