Skip to content

Commit

Permalink
Code refactor and improved resource file usage (#601)
Browse files Browse the repository at this point in the history
Refactor lots of code due to the custom serialization/deserialization logic implemented in the version 1.9.0.0 of the AppControl Manager. The result is a cleaner and better interop between different components.

Moved lots of strings to the resource file to improve the ability of the app to be translated into other languages.

Improved the Configure Policy Rule Options page, it now shows details and description of each rule option, helping you to decide which one is suitable for your use case.

Updated a NuGet dependency to the latest version.
  • Loading branch information
HotCakeX authored Feb 17, 2025
1 parent 0f95acc commit 5f527ff
Show file tree
Hide file tree
Showing 57 changed files with 1,493 additions and 1,551 deletions.
27 changes: 16 additions & 11 deletions AppControl Manager/AppControl Manager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<EnableMsixTooling>true</EnableMsixTooling>
<Nullable>enable</Nullable>


<!-- https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#satelliteresourcelanguages -->
<SatelliteResourceLanguages>en-US</SatelliteResourceLanguages>

Expand Down Expand Up @@ -57,8 +58,8 @@


<PublishTrimmed>false</PublishTrimmed>
<!--
<!--
<TrimMode>partial</TrimMode>
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
<TrimmerSingleWarn>false</TrimmerSingleWarn>
Expand Down Expand Up @@ -110,13 +111,13 @@
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
</PropertyGroup>

<!--
<!--
This section is no longer necessary since this generator is not Native AOT compatible and serialization/deserialization logic has been manually implemented with static code
ARM64 doesn't support source generated XML de(serialization)
ARM64 doesn't support source generated XML de(serialization)
<ItemGroup Condition="'$(RuntimeIdentifier)' != 'win-arm64'">
<DotNetCliToolReference Include="Microsoft.XmlSerializer.Generator" Version="9.0.1" />
</ItemGroup>
</ItemGroup>
-->

<!--
Expand All @@ -136,7 +137,7 @@
</ItemGroup>

<!-- Nuget packages
All transitive/nested packages under the main packages are added
All transitive/nested packages under the main packages are added
so they can be updated separately and receive bug/security vulnerability fixes faster
https://devblogs.microsoft.com/nuget/introducing-transitive-dependencies-in-visual-studio/
Expand All @@ -156,11 +157,11 @@
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.3.2" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.68.0" />
<PackageReference Include="Microsoft.IdentityModel.Abstractions" Version="8.4.0" />
<PackageReference Include="Microsoft.IdentityModel.Abstractions" Version="8.5.0" />
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3065.39" />
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.183">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<IncludeAssets>build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1742" />
Expand All @@ -174,8 +175,8 @@

<!--
No longer needed - manual static code has been implemented
ARM64 doesn't support source generated XML de(serialization)
ARM64 doesn't support source generated XML de(serialization)
<PackageReference Include="Microsoft.XmlSerializer.Generator" Version="9.0.2" Condition="'$(RuntimeIdentifier)' != 'win-arm64'" />
-->

Expand Down Expand Up @@ -243,6 +244,7 @@
<None Remove="Pages\ViewCurrentPolicies.xaml" />
<None Remove="Pages\ViewFileCertificates.xaml" />
<None Remove="Resources\AppControlManagerSupplementalPolicy.xml" />
<None Remove="Resources\EmptyPolicy.xml" />
<None Remove="Resources\ISGBasedSupplementalPolicy.xml" />
<None Remove="Resources\StrictKernelMode.xml" />
<None Remove="Resources\StrictKernelMode_NoFlightRoots.xml" />
Expand All @@ -257,6 +259,9 @@
<Content Include="Resources\AppControlManagerSupplementalPolicy.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Resources\EmptyPolicy.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Resources\ISGBasedSupplementalPolicy.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
CornerRadius="8"
Style="{ThemeResource DefaultContentDialogStyle}"
BorderBrush="{ThemeResource AccentFillColorDefaultBrush}">

<ContentDialog.Resources>
<!-- https://github.com/microsoft/microsoft-ui-xaml/issues/424 -->
<x:Double x:Key="ContentDialogMaxWidth">2000</x:Double>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ private async void VerifyButton_Click(object sender, RoutedEventArgs e)
await Task.Run(() =>
{
// Instantiate the selected XML policy file
policyObject = SiPolicy.Management.Initialize(policyPathFromUI);
policyObject = SiPolicy.Management.Initialize(policyPathFromUI, null);

// See if the deployed base policy IDs contain the ID of the policy being removed
// Only checking among base policies because supplemental policies can be removed normally whether they're signed or not
Expand Down
16 changes: 8 additions & 8 deletions AppControl Manager/IntelGathering/KernelModeDrivers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ internal static class KernelModeDrivers
private static readonly Guid CRYPT_SUBJTYPE_CATALOG_IMAGE = new("DE351A43-8E59-11d0-8C47-00C04FC295EE");
private static readonly Guid CRYPT_SUBJTYPE_CTL_IMAGE = new("9BA61D3F-E73A-11d0-8CD2-00C04FC295EE");

// If any of these DLLs are found in the imports list, the file is (likely) a user-mode PE.
// When a binary (such as a .exe or .dll) imports any of these user-mode libraries, it indicates that the binary relies on user-space functions, which are designed for normal applications.
// E.g., functions like CreateFile, MessageBox, or CreateWindow etc. are provided by kernel32.dll and user32.dll for user-mode applications, not for code running in kernel mode.
// Kernel-mode components do not interact with these user-mode DLLs. Instead, they access the kernel directly through SysCalls and low-level APIs.

private static readonly HashSet<string> UserModeDlls = ["kernel32.dll", "kernelbase.dll", "mscoree.dll", "ntdll.dll", "user32.dll"];

public struct IMAGE_IMPORT_DESCRIPTOR
{
public uint CharacteristicsOrOriginalFirstThunk;
Expand Down Expand Up @@ -328,14 +335,7 @@ internal static KernelUserVerdict CheckKernelUserModeStatus(string filePath)
}



// If any of these DLLs are found in the imports list, the file is (likely) a user-mode PE.
// When a binary (such as a .exe or .dll) imports any of these user-mode libraries, it indicates that the binary relies on user-space functions, which are designed for normal applications.
// E.g., functions like CreateFile, MessageBox, or CreateWindow etc. are provided by kernel32.dll and user32.dll for user-mode applications, not for code running in kernel mode.
// Kernel-mode components do not interact with these user-mode DLLs. Instead, they access the kernel directly through SysCalls and low-level APIs.
List<string> userModeDlls = ["kernel32.dll", "kernelbase.dll", "mscoree.dll", "ntdll.dll", "user32.dll"];

Verdict = importNames.Any(import => userModeDlls.Any(dll => string.Equals(import, dll, StringComparison.OrdinalIgnoreCase))) ? SSType.UserMode : SSType.KernelMode;
Verdict = importNames.Any(import => UserModeDlls.Any(dll => string.Equals(import, dll, StringComparison.OrdinalIgnoreCase))) ? SSType.UserMode : SSType.KernelMode;

// Return the actual output which happens when no errors occurred before
return new KernelUserVerdict
Expand Down
13 changes: 2 additions & 11 deletions AppControl Manager/IntelGathering/PrepareEmptyPolicy.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,21 @@
using System.IO;
using AppControlManager.Others;
using AppControlManager.XMLOps;

namespace AppControlManager.IntelGathering;

public static class PrepareEmptyPolicy
{

/// <summary>
/// Copies one of the template Code Integrity policies to the directory it receives, empties it and returns its path
/// Copies the empty policy in app resources to the defined directory and returns its new path
/// </summary>
/// <param name="directory"></param>
/// <returns></returns>
public static string Prepare(string directory)
{

string pathToReturn = Path.Combine(directory, "EmptyPolicyFile.xml");

Logger.Write("Copying the template policy to the staging area");

File.Copy(@"C:\Windows\schemas\CodeIntegrity\ExamplePolicies\AllowAll.xml", pathToReturn, true);

Logger.Write("Emptying the policy file in preparation for the new data insertion");
ClearCiPolicySemantic.Clear(pathToReturn);
File.Copy(GlobalVars.EmptyPolicyPath, pathToReturn, true);

return pathToReturn;

}
}
17 changes: 8 additions & 9 deletions AppControl Manager/Main/BasePolicyCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -349,15 +349,15 @@ internal static void GetDriversBlockRules(string StagingArea)
driverBlockRulesXML.LoadXml(xmlContent);

// Instantiate the policy
CodeIntegrityPolicy codeIntegrityPolicy = new(null, driverBlockRulesXML);
SiPolicy.SiPolicy policyObj = SiPolicy.Management.Initialize(null, driverBlockRulesXML);

// Generate the path for the XML file
string xmlPath = Path.Combine(StagingArea, $"{name}.xml");

// Save the XML content to a file
CodeIntegrityPolicy.Save(codeIntegrityPolicy.XmlDocument, xmlPath);
SiPolicy.Management.SavePolicyToFile(policyObj, xmlPath);

CiRuleOptions.Set(filePath: xmlPath, rulesToRemove: [CiRuleOptions.PolicyRuleOptions.EnabledAuditMode]);
CiRuleOptions.Set(filePath: xmlPath, rulesToRemove: [SiPolicy.OptionType.EnabledAuditMode]);

// The final path where the XML policy file will be located
string savePathLocation = Path.Combine(GlobalVars.UserConfigDir, $"{name}.xml");
Expand Down Expand Up @@ -580,22 +580,21 @@ internal static void GetBlockRules(string StagingArea, bool deploy)
throw new InvalidOperationException("No XML content found on the Microsoft GitHub source for Microsoft Recommended User Mode Block Rules.");
}


// Load the XML content into an XmlDocument
XmlDocument userModeBlockRulesXML = new();
userModeBlockRulesXML.LoadXml(xmlContent);

// Instantiate the policy
CodeIntegrityPolicy codeIntegrityPolicy = new(null, userModeBlockRulesXML);
SiPolicy.SiPolicy policyObj = SiPolicy.Management.Initialize(null, userModeBlockRulesXML);

// Paths only used during staging area processing
string tempPolicyPath = Path.Combine(StagingArea, $"{policyName}.xml");
string tempPolicyCIPPath = Path.Combine(StagingArea, $"{policyName}.cip");

// Save the XML content to a file
CodeIntegrityPolicy.Save(codeIntegrityPolicy.XmlDocument, tempPolicyPath);
SiPolicy.Management.SavePolicyToFile(policyObj, tempPolicyPath);

CiRuleOptions.Set(filePath: tempPolicyPath, rulesToAdd: [CiRuleOptions.PolicyRuleOptions.EnabledUpdatePolicyNoReboot, CiRuleOptions.PolicyRuleOptions.DisabledScriptEnforcement], rulesToRemove: [CiRuleOptions.PolicyRuleOptions.EnabledAuditMode, CiRuleOptions.PolicyRuleOptions.EnabledAdvancedBootOptionsMenu]);
CiRuleOptions.Set(filePath: tempPolicyPath, rulesToAdd: [SiPolicy.OptionType.EnabledUpdatePolicyNoReboot, SiPolicy.OptionType.DisabledScriptEnforcement], rulesToRemove: [SiPolicy.OptionType.EnabledAuditMode, SiPolicy.OptionType.EnabledAdvancedBootOptionsMenu]);

Logger.Write("Assigning policy name and resetting policy ID");

Expand All @@ -621,7 +620,7 @@ internal static void GetBlockRules(string StagingArea, bool deploy)
Logger.Write($"{policyName} policy is already deployed, updating it using the same GUID which is {CurrentlyDeployedBlockRulesGUID}.");

// Swap the policyID in the current policy XML file with the one from the deployed policy
PolicyEditor.EditGuids(CurrentlyDeployedBlockRulesGUID, new FileInfo(tempPolicyPath));
PolicyEditor.EditGuids(CurrentlyDeployedBlockRulesGUID, tempPolicyPath);
}
else
{
Expand Down Expand Up @@ -761,7 +760,7 @@ internal static void BuildStrictKernelMode(string StagingArea, bool IsAudit, boo
if (IsAudit)
{
// Add the audit mode rule option to the policy
CiRuleOptions.Set(filePath: policyPath, rulesToAdd: [CiRuleOptions.PolicyRuleOptions.EnabledAuditMode]);
CiRuleOptions.Set(filePath: policyPath, rulesToAdd: [SiPolicy.OptionType.EnabledAuditMode]);
}

string policyID;
Expand Down
Loading

0 comments on commit 5f527ff

Please sign in to comment.