From fcdd67bb0f641aedf2a1fb12092ef2ece053a78a Mon Sep 17 00:00:00 2001 From: Ryan Newington Date: Wed, 28 Aug 2024 01:29:34 +1000 Subject: [PATCH 1/5] Adds support for reading 'v2' consent ui headers --- .../Helpers.cs | 19 ++++ ...et.CredentialProvider.UnitTests.x64.csproj | 25 +++++ .../Samples/V1}/dump-consent-com-x64.dat | Bin .../Samples/V1}/dump-consent-exe-x64.dat | Bin .../Samples/V1}/dump-consent-msi-x64.dat | Bin .../Samples/V1}/dump-consent-msix-x64.dat | Bin .../Samples/V2/dump-consent-com-x64.dat | Bin 0 -> 408 bytes .../Samples/V2/dump-consent-exe-x64.dat | Bin 0 -> 604 bytes .../Samples/V2/dump-consent-msi-x64.dat | Bin 0 -> 538 bytes .../Samples/V2/dump-consent-msix-x64.dat | Bin 0 -> 868 bytes .../V1HeaderTests.cs | 96 +++++++++++++++++ .../V2HeaderTests.cs | 97 ++++++++++++++++++ .../Helpers.cs | 19 ++++ ...et.CredentialProvider.UnitTests.x86.csproj | 25 +++++ .../Samples/V1}/dump-consent-com-x86.dat | Bin .../Samples/V1}/dump-consent-exe-x86.dat | Bin .../Samples/V1}/dump-consent-msi-x86.dat | Bin .../Samples/V1}/dump-consent-msix-x86.dat | Bin .../V1HeaderTests.cs | 96 +++++++++++++++++ src/Lithnet.CredentialProvider.sln | 12 +++ .../ConsentUI/ConsentUIData.cs | 11 +- .../ConsentUI/ConsentUIDataCom.cs | 2 +- .../ConsentUI/ConsentUIDataExe.cs | 2 +- .../ConsentUI/ConsentUIDataMsi.cs | 2 +- .../ConsentUI/ConsentUIDataMsix.cs | 2 +- .../Samples/dump-consent-winsec-x86.dat | Bin 384 -> 0 bytes .../Interop/SafeHGlobalHandle.cs | 5 + .../Interop/Structs/ConsentUIStructureCom.cs | 2 - .../Interop/Structs/ConsentUIStructureExe.cs | 2 - ...der.cs => ConsentUIStructureHeaderBase.cs} | 5 +- .../Structs/ConsentUIStructureHeaderV1.cs | 15 +++ .../Structs/ConsentUIStructureHeaderV2.cs | 16 +++ .../Interop/Structs/ConsentUIStructureMsi.cs | 2 - .../Interop/Structs/ConsentUIStructureMsix.cs | 2 - .../Lithnet.CredentialProvider.csproj | 9 ++ .../NativeMethods.json | 3 - 36 files changed, 447 insertions(+), 22 deletions(-) create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/Helpers.cs create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/Lithnet.CredentialProvider.UnitTests.x64.csproj rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x64/Samples/V1}/dump-consent-com-x64.dat (100%) rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x64/Samples/V1}/dump-consent-exe-x64.dat (100%) rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x64/Samples/V1}/dump-consent-msi-x64.dat (100%) rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x64/Samples/V1}/dump-consent-msix-x64.dat (100%) create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-com-x64.dat create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-exe-x64.dat create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-msi-x64.dat create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-msix-x64.dat create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x86/Helpers.cs create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x86/Lithnet.CredentialProvider.UnitTests.x86.csproj rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x86/Samples/V1}/dump-consent-com-x86.dat (100%) rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x86/Samples/V1}/dump-consent-exe-x86.dat (100%) rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x86/Samples/V1}/dump-consent-msi-x86.dat (100%) rename src/{Lithnet.CredentialProvider/ConsentUI/Samples => Lithnet.CredentialProvider.UnitTests.x86/Samples/V1}/dump-consent-msix-x86.dat (100%) create mode 100644 src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs delete mode 100644 src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-winsec-x86.dat rename src/Lithnet.CredentialProvider/Interop/Structs/{ConsentUIStructureHeader.cs => ConsentUIStructureHeaderBase.cs} (86%) create mode 100644 src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV1.cs create mode 100644 src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV2.cs delete mode 100644 src/Lithnet.CredentialProvider/NativeMethods.json diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/Helpers.cs b/src/Lithnet.CredentialProvider.UnitTests.x64/Helpers.cs new file mode 100644 index 0000000..4b7328e --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x64/Helpers.cs @@ -0,0 +1,19 @@ +using System.IO; +using System.Runtime.InteropServices; +using Lithnet.CredentialProvider.Interop; +using NUnit.Framework; + +namespace Lithnet.CredentialProvider.UnitTests +{ + internal static class Helpers + { + public static SafeHGlobalHandle ReadFile(string filename) + { + var data = File.ReadAllBytes(Path.Combine(TestContext.CurrentContext.TestDirectory, filename)); + var p = SafeHGlobalHandle.AllocHGlobal(data.Length); + Marshal.Copy(data, 0, p.ToIntPtr(), data.Length); + + return p; + } + } +} diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/Lithnet.CredentialProvider.UnitTests.x64.csproj b/src/Lithnet.CredentialProvider.UnitTests.x64/Lithnet.CredentialProvider.UnitTests.x64.csproj new file mode 100644 index 0000000..a3489d9 --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x64/Lithnet.CredentialProvider.UnitTests.x64.csproj @@ -0,0 +1,25 @@ + + + + net48 + false + x64 + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-com-x64.dat b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-com-x64.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-com-x64.dat rename to src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-com-x64.dat diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-exe-x64.dat b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-exe-x64.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-exe-x64.dat rename to src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-exe-x64.dat diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msi-x64.dat b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-msi-x64.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msi-x64.dat rename to src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-msi-x64.dat diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msix-x64.dat b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-msix-x64.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msix-x64.dat rename to src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V1/dump-consent-msix-x64.dat diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-com-x64.dat b/src/Lithnet.CredentialProvider.UnitTests.x64/Samples/V2/dump-consent-com-x64.dat new file mode 100644 index 0000000000000000000000000000000000000000..ad14352e75ed533d472d18b8c56502ffa2aab3c4 GIT binary patch literal 408 zcmbQi$iM(Z49q|b0&+~eV44F$F|Yu6OhDYD1Qup+0xF(q!N`zq=53x|XzuH8;9OEx zYFv_1<*eVhCGH8hJ1!{ zhGHN;n4uC#moTI<xU|ftN*Wp?` zxBU@U;Qu=JaqhYI-&_M7in_KM#jOnI+ZnJfu>9Lj?l%kY5fm5)&9GWI>7GTki%!^& z;z}!BTzP)Z`oH)6yEXj$({4la**bT4=P+^j>hQ~9&W2^(66=(?Wx$vcH4gCb31sgw z=SY5u2kw=h>W+9~PeLo6vHh$Ds=xb*(M%U zE`@=51`t*BBRd|d=k5bq_W^3O&J0!zF$@6=MGW~2=|D1( zA(ugc!Hpr4A%`KAp%^F^4rJ#sqyXj1fqX}X0w4s5`vS$2!TO4Ua%l`D40=GZUnS literal 0 HcmV?d00001 diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs b/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs new file mode 100644 index 0000000..6bf34d8 --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs @@ -0,0 +1,96 @@ +using System; +using Lithnet.CredentialProvider.Interop; +using NUnit.Framework; + +namespace Lithnet.CredentialProvider.UnitTests +{ + public class V1HeaderTests + { + [SetUp] + public void Setup() + { + ConsentUIData.HeaderSize = ConsentUIData.v1HeaderSize; + } + + [Test] + public void TestExe() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-exe-x64.dat"); + + var d = new ConsentUIDataExe(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Exe, d.Type); + Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); + Assert.AreEqual(3, d.SessionId); + Assert.AreEqual((IntPtr)0x0000000000010128, d.HWnd); + Assert.AreEqual((ConsentUIElevationType)6, d.ElevationType); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.ExecutablePath); + Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.Unknown1); + Assert.AreEqual("\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" ARGS1 ARGS2", d.CommandLine); + Assert.AreEqual("", d.Unknown2); + } + + [Test] + public void TestMsi() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-msi-x64.dat"); + + var d = new ConsentUIDataMsi(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Msi, d.Type); + Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther, d.Flags); + Assert.AreEqual(3, d.SessionId); + Assert.AreEqual((IntPtr)0x0000000000230370, d.HWnd); + Assert.AreEqual((ConsentUIElevationType)5, d.ElevationType); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("7-Zip 23.01 (x64 edition)", d.ProductName); + Assert.AreEqual(ConsentUIMsiAction.Install, d.Action); + Assert.AreEqual("C:\\Windows\\Installer\\b733392.msi", d.ExecutionPath); + Assert.AreEqual("1033", d.Locale); + Assert.AreEqual("C:\\Users\\ryan2\\Downloads\\7z2301-x64.msi", d.OriginalMsi); + Assert.AreEqual("7-Zip 23.01 (x64 edition)", d.ProductName); + Assert.AreEqual("Igor Pavlov", d.Publisher); + Assert.AreEqual("23.01.00.0", d.Version); + } + + [Test] + public void TestMsix() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-msix-x64.dat"); + + var d = new ConsentUIDataMsix(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Msix, d.Type); + Assert.AreEqual( ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); + Assert.AreEqual(3, d.SessionId); + Assert.AreEqual((IntPtr)0x0, d.HWnd); + Assert.AreEqual((ConsentUIElevationType)8, d.ElevationType); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("\"C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe\" ", d.CommandLine); + Assert.AreEqual("C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe", d.ExecutablePath); + Assert.AreEqual("Microsoft.MSIXPackagingTool_8wekyb3d8bbwe!Msix.App", d.OtherName); + Assert.AreEqual("Microsoft.MSIXPackagingTool_8wekyb3d8bbwe", d.PackageName); + } + + [Test] + public void TestCom() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-com-x64.dat"); + + var d = new ConsentUIDataCom(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Com, d.Type); + Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther | ConsentUIFlags.InWindowsDirectory, d.Flags); + Assert.AreEqual(3, d.SessionId); + Assert.AreEqual((IntPtr)0x00000000000903c2, d.HWnd); + Assert.AreEqual((ConsentUIElevationType)4, d.ElevationType); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual(new Guid("{3ad05575-8857-4850-9277-11b85bdb8e09}"), d.ClsId); + Assert.AreEqual("C:\\Windows\\system32\\windows.storage.dll", d.ComComponentPath); + Assert.AreEqual("", d.ImageResourcePath); + Assert.AreEqual("File Operation", d.OperationType); + Assert.AreEqual("C:\\Windows\\Explorer.EXE", d.ProcessPath); + } + } +} \ No newline at end of file diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs b/src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs new file mode 100644 index 0000000..fbd5af1 --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs @@ -0,0 +1,97 @@ +using System; +using Lithnet.CredentialProvider.Interop; +using NUnit.Framework; + +namespace Lithnet.CredentialProvider.UnitTests +{ + public class V2HeaderTests + { + + [SetUp] + public void Setup() + { + ConsentUIData.HeaderSize = ConsentUIData.v2HeaderSize; + } + + [Test] + public void TestExe() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V2\\dump-consent-exe-x64.dat"); + + ConsentUIDataExe d = new ConsentUIDataExe(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Exe, d.Type); + Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); + Assert.AreEqual(3, d.SessionId); + Assert.AreEqual((IntPtr)0x0, d.HWnd); // this seems odd + Assert.AreEqual((ConsentUIElevationType)6, d.ElevationType); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.ExecutablePath); + Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.Unknown1); + Assert.AreEqual("\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" ", d.CommandLine); + Assert.AreEqual("", d.Unknown2); + } + + [Test] + public void TestMsi() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V2\\dump-consent-msi-x64.dat"); + + var d = new ConsentUIDataMsi(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Msi, d.Type); + Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther, d.Flags); + Assert.AreEqual(2, d.SessionId); + Assert.AreEqual((IntPtr)0x00000000001e033a, d.HWnd); + Assert.AreEqual((ConsentUIElevationType)5, d.ElevationType); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("7-Zip 24.08 (x64 edition)", d.ProductName); + Assert.AreEqual(ConsentUIMsiAction.Install, d.Action); + Assert.AreEqual("C:\\WINDOWS\\Installer\\58ca98.msi", d.ExecutionPath); + Assert.AreEqual("1033", d.Locale); + Assert.AreEqual("C:\\Users\\testuser\\Downloads\\7z2408-x64.msi", d.OriginalMsi); + Assert.AreEqual("7-Zip 24.08 (x64 edition)", d.ProductName); + Assert.AreEqual("Igor Pavlov", d.Publisher); + Assert.AreEqual("24.08.00.0", d.Version); + } + + [Test] + public void TestMsix() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V2\\dump-consent-msix-x64.dat"); + + var d = new ConsentUIDataMsix(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Msix, d.Type); + Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); + Assert.AreEqual(2, d.SessionId); + Assert.AreEqual((IntPtr)0x0, d.HWnd); + Assert.AreEqual((ConsentUIElevationType)8, d.ElevationType); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("\"C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2024.405.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe\" ", d.CommandLine); + Assert.AreEqual("C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2024.405.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe", d.ExecutablePath); + Assert.AreEqual("Microsoft.MSIXPackagingTool_8wekyb3d8bbwe!Msix.App", d.OtherName); + Assert.AreEqual("Microsoft.MSIXPackagingTool_8wekyb3d8bbwe", d.PackageName); + } + + [Test] + public void TestCom() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V2\\dump-consent-com-x64.dat"); + + var d = new ConsentUIDataCom(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Com, d.Type); + Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther | ConsentUIFlags.InWindowsDirectory, d.Flags); + Assert.AreEqual(2, d.SessionId); + Assert.AreEqual((IntPtr)0x00000000000d021e, d.HWnd); + Assert.AreEqual((ConsentUIElevationType)4, d.ElevationType); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual(new Guid("{3ad05575-8857-4850-9277-11b85bdb8e09}"), d.ClsId); + Assert.AreEqual("C:\\WINDOWS\\system32\\windows.storage.dll", d.ComComponentPath); + Assert.AreEqual("", d.ImageResourcePath); + Assert.AreEqual("File Operation", d.OperationType); + Assert.AreEqual("C:\\WINDOWS\\Explorer.EXE", d.ProcessPath); + } + } +} \ No newline at end of file diff --git a/src/Lithnet.CredentialProvider.UnitTests.x86/Helpers.cs b/src/Lithnet.CredentialProvider.UnitTests.x86/Helpers.cs new file mode 100644 index 0000000..4b7328e --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x86/Helpers.cs @@ -0,0 +1,19 @@ +using System.IO; +using System.Runtime.InteropServices; +using Lithnet.CredentialProvider.Interop; +using NUnit.Framework; + +namespace Lithnet.CredentialProvider.UnitTests +{ + internal static class Helpers + { + public static SafeHGlobalHandle ReadFile(string filename) + { + var data = File.ReadAllBytes(Path.Combine(TestContext.CurrentContext.TestDirectory, filename)); + var p = SafeHGlobalHandle.AllocHGlobal(data.Length); + Marshal.Copy(data, 0, p.ToIntPtr(), data.Length); + + return p; + } + } +} diff --git a/src/Lithnet.CredentialProvider.UnitTests.x86/Lithnet.CredentialProvider.UnitTests.x86.csproj b/src/Lithnet.CredentialProvider.UnitTests.x86/Lithnet.CredentialProvider.UnitTests.x86.csproj new file mode 100644 index 0000000..d37d745 --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x86/Lithnet.CredentialProvider.UnitTests.x86.csproj @@ -0,0 +1,25 @@ + + + + net48 + false + x86 + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-com-x86.dat b/src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-com-x86.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-com-x86.dat rename to src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-com-x86.dat diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-exe-x86.dat b/src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-exe-x86.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-exe-x86.dat rename to src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-exe-x86.dat diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msi-x86.dat b/src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-msi-x86.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msi-x86.dat rename to src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-msi-x86.dat diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msix-x86.dat b/src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-msix-x86.dat similarity index 100% rename from src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-msix-x86.dat rename to src/Lithnet.CredentialProvider.UnitTests.x86/Samples/V1/dump-consent-msix-x86.dat diff --git a/src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs b/src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs new file mode 100644 index 0000000..e4c6dbe --- /dev/null +++ b/src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs @@ -0,0 +1,96 @@ +using System; +using Lithnet.CredentialProvider.Interop; +using NUnit.Framework; + +namespace Lithnet.CredentialProvider.UnitTests +{ + public class V1HeaderTests + { + [SetUp] + public void Setup() + { + ConsentUIData.HeaderSize = ConsentUIData.v1HeaderSize; + } + + [Test] + public void TestExe() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-exe-x86.dat"); + + var d = new ConsentUIDataExe(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Exe, d.Type); + Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); + Assert.AreEqual(2, d.SessionId); + Assert.AreEqual((IntPtr)0x0006056a, d.HWnd); + Assert.AreEqual((ConsentUIElevationType)6, d.ElevationType); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.ExecutablePath); + Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.Unknown1); + Assert.AreEqual("\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" ARGS1 ARGS2", d.CommandLine); + Assert.AreEqual("", d.Unknown2); + } + + [Test] + public void TestMsi() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-msi-x86.dat"); + + var d = new ConsentUIDataMsi(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Msi, d.Type); + Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther, d.Flags); + Assert.AreEqual(2, d.SessionId); + Assert.AreEqual((IntPtr)0x000705bc, d.HWnd); + Assert.AreEqual((ConsentUIElevationType)5, d.ElevationType); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("7-Zip 23.01", d.ProductName); + Assert.AreEqual(ConsentUIMsiAction.Install, d.Action); + Assert.AreEqual("C:\\Windows\\Installer\\26396d5.msi", d.ExecutionPath); + Assert.AreEqual("1033", d.Locale); + Assert.AreEqual("C:\\Users\\std\\Downloads\\7z2301.msi", d.OriginalMsi); + Assert.AreEqual("7-Zip 23.01", d.ProductName); + Assert.AreEqual("Igor Pavlov", d.Publisher); + Assert.AreEqual("23.01.00.0", d.Version); + } + + [Test] + public void TestMsix() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-msix-x86.dat"); + + var d = new ConsentUIDataMsix(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Msix, d.Type); + Assert.AreEqual( ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); + Assert.AreEqual(2, d.SessionId); + Assert.AreEqual((IntPtr)0x0, d.HWnd); + Assert.AreEqual((ConsentUIElevationType)8, d.ElevationType); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual("\"C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x86__8wekyb3d8bbwe\\MsixPackageTool.exe\" ", d.CommandLine); + Assert.AreEqual("C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x86__8wekyb3d8bbwe\\MsixPackageTool.exe", d.ExecutablePath); + Assert.AreEqual("Microsoft.MSIXPackagingTool_8wekyb3d8bbwe!Msix.App", d.OtherName); + Assert.AreEqual("Microsoft.MSIXPackagingTool_8wekyb3d8bbwe", d.PackageName); + } + + [Test] + public void TestCom() + { + SafeHGlobalHandle p = Helpers.ReadFile($"Samples\\V1\\dump-consent-com-x86.dat"); + + var d = new ConsentUIDataCom(p.ToIntPtr(), p.Size); + + Assert.AreEqual(ConsentUIType.Com, d.Type); + Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther | ConsentUIFlags.InWindowsDirectory, d.Flags); + Assert.AreEqual(2, d.SessionId); + Assert.AreEqual((IntPtr)0x000b0586, d.HWnd); + Assert.AreEqual((ConsentUIElevationType)4, d.ElevationType); + Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); + Assert.AreEqual(new Guid("{3ad05575-8857-4850-9277-11b85bdb8e09}"), d.ClsId); + Assert.AreEqual("C:\\Windows\\system32\\windows.storage.dll", d.ComComponentPath); + Assert.AreEqual("", d.ImageResourcePath); + Assert.AreEqual("File Operation", d.OperationType); + Assert.AreEqual("C:\\Windows\\Explorer.EXE", d.ProcessPath); + } + } +} \ No newline at end of file diff --git a/src/Lithnet.CredentialProvider.sln b/src/Lithnet.CredentialProvider.sln index 52e6520..4460844 100644 --- a/src/Lithnet.CredentialProvider.sln +++ b/src/Lithnet.CredentialProvider.sln @@ -23,6 +23,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lithnet.CredentialProvider. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lithnet.CredentialProvider.TestApp.x86", "samples\Lithnet.CredentialProvider.TestApp.x86\Lithnet.CredentialProvider.TestApp.x86.csproj", "{F39C84F2-60C2-45EB-BC87-0ED095D41C96}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lithnet.CredentialProvider.UnitTests.x64", "Lithnet.CredentialProvider.UnitTests.x64\Lithnet.CredentialProvider.UnitTests.x64.csproj", "{21E66D65-6E3F-4ACA-B1D0-CA4CC7C58D0C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lithnet.CredentialProvider.UnitTests.x86", "Lithnet.CredentialProvider.UnitTests.x86\Lithnet.CredentialProvider.UnitTests.x86.csproj", "{DA23151B-B7B6-4942-B7A4-48E1918EF145}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -57,6 +61,14 @@ Global {F39C84F2-60C2-45EB-BC87-0ED095D41C96}.Debug|Any CPU.Build.0 = Debug|Any CPU {F39C84F2-60C2-45EB-BC87-0ED095D41C96}.Release|Any CPU.ActiveCfg = Release|Any CPU {F39C84F2-60C2-45EB-BC87-0ED095D41C96}.Release|Any CPU.Build.0 = Release|Any CPU + {21E66D65-6E3F-4ACA-B1D0-CA4CC7C58D0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21E66D65-6E3F-4ACA-B1D0-CA4CC7C58D0C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21E66D65-6E3F-4ACA-B1D0-CA4CC7C58D0C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21E66D65-6E3F-4ACA-B1D0-CA4CC7C58D0C}.Release|Any CPU.Build.0 = Release|Any CPU + {DA23151B-B7B6-4942-B7A4-48E1918EF145}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA23151B-B7B6-4942-B7A4-48E1918EF145}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA23151B-B7B6-4942-B7A4-48E1918EF145}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA23151B-B7B6-4942-B7A4-48E1918EF145}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs index de92d28..37596df 100644 --- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs +++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs @@ -23,8 +23,12 @@ namespace Lithnet.CredentialProvider { private static bool? isConsentUI; private static ConsentUICommandLineArgs commandLineArgs; - private protected ConsentUIStructureHeader header; + private protected ConsentUIStructureHeaderBase header; private readonly byte[] rawData; + private static readonly Version v2HeaderOsVersion = new Version(10, 0, 26100, 0); + internal static int v2HeaderSize = Marshal.SizeOf(); + internal static int v1HeaderSize = Marshal.SizeOf(); + internal static int HeaderSize { get; set; } = Environment.OSVersion.Version >= v2HeaderOsVersion ? v2HeaderSize : v1HeaderSize; /// /// Gets a value indicating the type of ConsentUI data structure @@ -62,7 +66,8 @@ namespace Lithnet.CredentialProvider private protected ConsentUIData(IntPtr pData, int expectedSize) { this.rawData = GetRawBytes(pData, expectedSize); - this.header = Marshal.PtrToStructure(pData); + + this.header = Marshal.PtrToStructure(pData); if (this.header.Size != expectedSize) { @@ -330,7 +335,7 @@ namespace Lithnet.CredentialProvider /// The handle to duplicate /// A duplicated reference to the handle /// Thrown when the handle could not be duplicated - protected private static SafeHandle DuplicateHandleInternal(IntPtr handle) + private protected static SafeHandle DuplicateHandleInternal(IntPtr handle) { commandLineArgs ??= GetConsentUICommandLineArgs(); diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataCom.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataCom.cs index c596f0e..bc6c29d 100644 --- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataCom.cs +++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataCom.cs @@ -41,7 +41,7 @@ namespace Lithnet.CredentialProvider throw new InvalidOperationException("The data structure is not of type COM"); } - var s = Marshal.PtrToStructure(pData); + var s = Marshal.PtrToStructure(pData + HeaderSize); this.ComComponentPath = this.GetStringValueIfValid(pData, (int)s.oComComponentPath); this.ImageResourcePath = this.GetStringValueIfValid(pData, (int)s.oImageResourcePath); diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataExe.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataExe.cs index 7a90c44..80cae5f 100644 --- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataExe.cs +++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataExe.cs @@ -50,7 +50,7 @@ namespace Lithnet.CredentialProvider throw new InvalidOperationException("The data structure is not of type EXE"); } - var s = Marshal.PtrToStructure(pData); + var s = Marshal.PtrToStructure(pData + HeaderSize); this.hFile = s.hFile; this.ExecutablePath = this.GetStringValueIfValid(pData, (int)s.oExecutablePath1); diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsi.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsi.cs index 436999d..1197f0d 100644 --- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsi.cs +++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsi.cs @@ -51,7 +51,7 @@ namespace Lithnet.CredentialProvider throw new InvalidOperationException("The data structure is not of type MSI"); } - var s = Marshal.PtrToStructure(pData); + var s = Marshal.PtrToStructure(pData + HeaderSize); this.Action = s.MsiAction; this.ProductName = this.GetStringValueIfValid(pData, (int)s.oProductName); diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsix.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsix.cs index d93e4ee..6589216 100644 --- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsix.cs +++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIDataMsix.cs @@ -36,7 +36,7 @@ namespace Lithnet.CredentialProvider throw new InvalidOperationException("The data structure is not of type MSIX"); } - var s = Marshal.PtrToStructure(pData); + var s = Marshal.PtrToStructure(pData + HeaderSize); this.ExecutablePath = this.GetStringValueIfValid(pData, (int)s.oExecutablePath); this.PackageName = this.GetStringValueIfValid(pData, (int)s.oPackageName); diff --git a/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-winsec-x86.dat b/src/Lithnet.CredentialProvider/ConsentUI/Samples/dump-consent-winsec-x86.dat deleted file mode 100644 index 311afd6fc1222df83e9605acdba8667c3dfa233a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmZo*WMBXy24*1EU{zxHpuoVu0%S7*@ex%91}C88wx5Pf6F!~c@&StF0r4>))&h#_ zAO7Sj_I8R-%jD~NKdo4$!x=Jx@+l1Y4CM^P3`%V5l41XO{p(*r1%$dCh6lfmG~kPhVK0oi&$yK;b#fx&@BChIWh eG8i%#05LAN2b1J>4`A4Ue5wcZK?M*qFaQ8igGoUE diff --git a/src/Lithnet.CredentialProvider/Interop/SafeHGlobalHandle.cs b/src/Lithnet.CredentialProvider/Interop/SafeHGlobalHandle.cs index 7650635..80828d6 100644 --- a/src/Lithnet.CredentialProvider/Interop/SafeHGlobalHandle.cs +++ b/src/Lithnet.CredentialProvider/Interop/SafeHGlobalHandle.cs @@ -10,6 +10,8 @@ namespace Lithnet.CredentialProvider.Interop /// IntPtr pointer; + int size; + SafeHGlobalHandle() { this.pointer = IntPtr.Zero; @@ -25,6 +27,8 @@ namespace Lithnet.CredentialProvider.Interop this.Dispose(); } + public int Size => size; + public static SafeHGlobalHandle InvalidHandle => new SafeHGlobalHandle(IntPtr.Zero); /// @@ -58,6 +62,7 @@ namespace Lithnet.CredentialProvider.Interop SafeHGlobalHandle result = new SafeHGlobalHandle(); result.pointer = Marshal.AllocHGlobal(cb); + result.size = cb; return result; } } diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureCom.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureCom.cs index 24a35a3..6c28aaa 100644 --- a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureCom.cs +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureCom.cs @@ -6,8 +6,6 @@ namespace Lithnet.CredentialProvider.Interop [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct ConsentUIStructureCom { - public ConsentUIStructureHeader Header; - // 64 public IntPtr oOperationType; // 8 diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureExe.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureExe.cs index ed69888..ff0682e 100644 --- a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureExe.cs +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureExe.cs @@ -6,8 +6,6 @@ namespace Lithnet.CredentialProvider.Interop [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct ConsentUIStructureExe { - public ConsentUIStructureHeader Header; - // 64 public IntPtr hFile; // 8 diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeader.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderBase.cs similarity index 86% rename from src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeader.cs rename to src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderBase.cs index f016be1..f58c6b7 100644 --- a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeader.cs +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderBase.cs @@ -4,7 +4,7 @@ using System.Runtime.InteropServices; namespace Lithnet.CredentialProvider.Interop { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct ConsentUIStructureHeader + internal struct ConsentUIStructureHeaderBase { public int Size; // 4 public ConsentUIType Type; // 4 @@ -26,8 +26,5 @@ namespace Lithnet.CredentialProvider.Interop public ConsentUIFlags Flags; // 4 public int unknown0; // 4 - public IntPtr pReturnAddress; // 8 - - // 64 } } diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV1.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV1.cs new file mode 100644 index 0000000..9d387ed --- /dev/null +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV1.cs @@ -0,0 +1,15 @@ +using System; +using System.Runtime.InteropServices; + +namespace Lithnet.CredentialProvider.Interop +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct ConsentUIStructureHeaderV1 + { + public ConsentUIStructureHeaderBase BaseHeader; + + public IntPtr pReturnAddress; // 8 + + // 64 + } +} diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV2.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV2.cs new file mode 100644 index 0000000..4fae264 --- /dev/null +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderV2.cs @@ -0,0 +1,16 @@ +using System; +using System.Runtime.InteropServices; + +namespace Lithnet.CredentialProvider.Interop +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct ConsentUIStructureHeaderV2 + { + public ConsentUIStructureHeaderBase BaseHeader; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x81)] + public byte[] unknown1; + + public IntPtr pReturnAddress; // 8 + } +} \ No newline at end of file diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsi.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsi.cs index b7a04bc..3d3b543 100644 --- a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsi.cs +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsi.cs @@ -6,8 +6,6 @@ namespace Lithnet.CredentialProvider.Interop [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct ConsentUIStructureMsi { - public ConsentUIStructureHeader Header; - // 64 public ConsentUIMsiAction MsiAction; // 8 diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsix.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsix.cs index 456624a..c58c24d 100644 --- a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsix.cs +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureMsix.cs @@ -6,8 +6,6 @@ namespace Lithnet.CredentialProvider.Interop [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct ConsentUIStructureMsix { - public ConsentUIStructureHeader Header; - // 64 public IntPtr oExecutablePath; // 8 diff --git a/src/Lithnet.CredentialProvider/Lithnet.CredentialProvider.csproj b/src/Lithnet.CredentialProvider/Lithnet.CredentialProvider.csproj index 34d41dc..3d5ea3c 100644 --- a/src/Lithnet.CredentialProvider/Lithnet.CredentialProvider.csproj +++ b/src/Lithnet.CredentialProvider/Lithnet.CredentialProvider.csproj @@ -38,6 +38,15 @@ true + + + <_Parameter1>Lithnet.CredentialProvider.UnitTests.x64 + + + <_Parameter1>Lithnet.CredentialProvider.UnitTests.x86 + + + all diff --git a/src/Lithnet.CredentialProvider/NativeMethods.json b/src/Lithnet.CredentialProvider/NativeMethods.json deleted file mode 100644 index 6d04a57..0000000 --- a/src/Lithnet.CredentialProvider/NativeMethods.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "$schema": "https://aka.ms/CsWin32.schema.json" -} \ No newline at end of file From 10505c864113e842aadcfdba79dc53ce9fecf7dd Mon Sep 17 00:00:00 2001 From: Ryan Newington Date: Wed, 28 Aug 2024 01:37:33 +1000 Subject: [PATCH 2/5] Update tfms --- .../Lithnet.CredentialProvider.UnitTests.x64.csproj | 2 +- .../Lithnet.CredentialProvider.UnitTests.x86.csproj | 2 +- .../Lithnet.CredentialProvider.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/Lithnet.CredentialProvider.UnitTests.x64.csproj b/src/Lithnet.CredentialProvider.UnitTests.x64/Lithnet.CredentialProvider.UnitTests.x64.csproj index a3489d9..86fc565 100644 --- a/src/Lithnet.CredentialProvider.UnitTests.x64/Lithnet.CredentialProvider.UnitTests.x64.csproj +++ b/src/Lithnet.CredentialProvider.UnitTests.x64/Lithnet.CredentialProvider.UnitTests.x64.csproj @@ -1,7 +1,7 @@  - net48 + net6.0-windows;net7.0-windows;net8.0-windows;net461;net48 false x64 diff --git a/src/Lithnet.CredentialProvider.UnitTests.x86/Lithnet.CredentialProvider.UnitTests.x86.csproj b/src/Lithnet.CredentialProvider.UnitTests.x86/Lithnet.CredentialProvider.UnitTests.x86.csproj index d37d745..31f57a7 100644 --- a/src/Lithnet.CredentialProvider.UnitTests.x86/Lithnet.CredentialProvider.UnitTests.x86.csproj +++ b/src/Lithnet.CredentialProvider.UnitTests.x86/Lithnet.CredentialProvider.UnitTests.x86.csproj @@ -1,7 +1,7 @@ - net48 + net6.0-windows;net7.0-windows;net8.0-windows;net461;net48 false x86 diff --git a/src/Lithnet.CredentialProvider/Lithnet.CredentialProvider.csproj b/src/Lithnet.CredentialProvider/Lithnet.CredentialProvider.csproj index 3d5ea3c..7dfebbb 100644 --- a/src/Lithnet.CredentialProvider/Lithnet.CredentialProvider.csproj +++ b/src/Lithnet.CredentialProvider/Lithnet.CredentialProvider.csproj @@ -1,6 +1,6 @@  - net6.0-windows;net7.0-windows;net461 + net6.0-windows;net7.0-windows;net8.0-windows;net461 false Library true From e4ddea52673a53d7f3e935e30740d7990efdb91d Mon Sep 17 00:00:00 2001 From: Ryan Newington Date: Wed, 28 Aug 2024 16:17:52 +1000 Subject: [PATCH 3/5] Add check to make sure the size of the consent UI header is at least the size of the header as known for the platform/OS version --- src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs index 37596df..55da8fb 100644 --- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs +++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs @@ -73,6 +73,11 @@ namespace Lithnet.CredentialProvider { throw new InvalidDataException($"The size of the data structure {this.header.Size} does not match the expected size {expectedSize}"); } + + if (HeaderSize > this.header.Size) + { + throw new InvalidDataException($"The size of the data structure {this.header.Size} is less than the expected header size {HeaderSize}"); + } } /// From 97fb10713ff9e086509810f848eee797f8a30913 Mon Sep 17 00:00:00 2001 From: James Spencer Date: Sun, 1 Sep 2024 18:52:42 +1000 Subject: [PATCH 4/5] Correctly document 'ConsentUIElevationReason' based on ELEVATION_REASON enum from Windows headers. Update tests to match --- .../V1HeaderTests.cs | 8 +-- .../V2HeaderTests.cs | 8 +-- .../V1HeaderTests.cs | 8 +-- .../ConsentUI/ConsentUIData.cs | 11 +-- .../Enums/ConsentUIElevationReason.cs | 70 +++++++++++++++++++ .../Enums/ConsentUIElevationType.cs | 24 ------- .../Enums/ConsentUIFlags.cs | 2 +- .../Structs/ConsentUIStructureHeaderBase.cs | 2 +- 8 files changed, 90 insertions(+), 43 deletions(-) create mode 100644 src/Lithnet.CredentialProvider/Enums/ConsentUIElevationReason.cs delete mode 100644 src/Lithnet.CredentialProvider/Enums/ConsentUIElevationType.cs diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs b/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs index 6bf34d8..a8d3126 100644 --- a/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs +++ b/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs @@ -23,7 +23,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); Assert.AreEqual(3, d.SessionId); Assert.AreEqual((IntPtr)0x0000000000010128, d.HWnd); - Assert.AreEqual((ConsentUIElevationType)6, d.ElevationType); + Assert.AreEqual(ConsentUIElevationReason.Request, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.ExecutablePath); Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.Unknown1); @@ -42,7 +42,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther, d.Flags); Assert.AreEqual(3, d.SessionId); Assert.AreEqual((IntPtr)0x0000000000230370, d.HWnd); - Assert.AreEqual((ConsentUIElevationType)5, d.ElevationType); + Assert.AreEqual(ConsentUIElevationReason.Msi, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual("7-Zip 23.01 (x64 edition)", d.ProductName); Assert.AreEqual(ConsentUIMsiAction.Install, d.Action); @@ -65,7 +65,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual( ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); Assert.AreEqual(3, d.SessionId); Assert.AreEqual((IntPtr)0x0, d.HWnd); - Assert.AreEqual((ConsentUIElevationType)8, d.ElevationType); + Assert.AreEqual(ConsentUIElevationReason.PackagedApp, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual("\"C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe\" ", d.CommandLine); Assert.AreEqual("C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe", d.ExecutablePath); @@ -84,7 +84,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther | ConsentUIFlags.InWindowsDirectory, d.Flags); Assert.AreEqual(3, d.SessionId); Assert.AreEqual((IntPtr)0x00000000000903c2, d.HWnd); - Assert.AreEqual((ConsentUIElevationType)4, d.ElevationType); + Assert.AreEqual(ConsentUIElevationReason.CLSID, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual(new Guid("{3ad05575-8857-4850-9277-11b85bdb8e09}"), d.ClsId); Assert.AreEqual("C:\\Windows\\system32\\windows.storage.dll", d.ComComponentPath); diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs b/src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs index fbd5af1..0417bd3 100644 --- a/src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs +++ b/src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs @@ -24,7 +24,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); Assert.AreEqual(3, d.SessionId); Assert.AreEqual((IntPtr)0x0, d.HWnd); // this seems odd - Assert.AreEqual((ConsentUIElevationType)6, d.ElevationType); + Assert.AreEqual(ConsentUIElevationReason.Request, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.ExecutablePath); Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.Unknown1); @@ -43,7 +43,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther, d.Flags); Assert.AreEqual(2, d.SessionId); Assert.AreEqual((IntPtr)0x00000000001e033a, d.HWnd); - Assert.AreEqual((ConsentUIElevationType)5, d.ElevationType); + Assert.AreEqual(ConsentUIElevationReason.Msi, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual("7-Zip 24.08 (x64 edition)", d.ProductName); Assert.AreEqual(ConsentUIMsiAction.Install, d.Action); @@ -66,7 +66,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); Assert.AreEqual(2, d.SessionId); Assert.AreEqual((IntPtr)0x0, d.HWnd); - Assert.AreEqual((ConsentUIElevationType)8, d.ElevationType); + Assert.AreEqual(ConsentUIElevationReason.PackagedApp, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual("\"C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2024.405.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe\" ", d.CommandLine); Assert.AreEqual("C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2024.405.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe", d.ExecutablePath); @@ -85,7 +85,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther | ConsentUIFlags.InWindowsDirectory, d.Flags); Assert.AreEqual(2, d.SessionId); Assert.AreEqual((IntPtr)0x00000000000d021e, d.HWnd); - Assert.AreEqual((ConsentUIElevationType)4, d.ElevationType); + Assert.AreEqual(ConsentUIElevationReason.CLSID, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual(new Guid("{3ad05575-8857-4850-9277-11b85bdb8e09}"), d.ClsId); Assert.AreEqual("C:\\WINDOWS\\system32\\windows.storage.dll", d.ComComponentPath); diff --git a/src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs b/src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs index e4c6dbe..4aa43e8 100644 --- a/src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs +++ b/src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs @@ -23,7 +23,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); Assert.AreEqual(2, d.SessionId); Assert.AreEqual((IntPtr)0x0006056a, d.HWnd); - Assert.AreEqual((ConsentUIElevationType)6, d.ElevationType); + Assert.AreEqual(ConsentUIElevationReason.Request, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.ExecutablePath); Assert.AreEqual("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", d.Unknown1); @@ -42,7 +42,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual(ConsentUIFlags.InWindowsDirectory | ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther, d.Flags); Assert.AreEqual(2, d.SessionId); Assert.AreEqual((IntPtr)0x000705bc, d.HWnd); - Assert.AreEqual((ConsentUIElevationType)5, d.ElevationType); + Assert.AreEqual(ConsentUIElevationReason.Msi, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual("7-Zip 23.01", d.ProductName); Assert.AreEqual(ConsentUIMsiAction.Install, d.Action); @@ -65,7 +65,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual( ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); Assert.AreEqual(2, d.SessionId); Assert.AreEqual((IntPtr)0x0, d.HWnd); - Assert.AreEqual((ConsentUIElevationType)8, d.ElevationType); + Assert.AreEqual(ConsentUIElevationReason.PackagedApp, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual("\"C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x86__8wekyb3d8bbwe\\MsixPackageTool.exe\" ", d.CommandLine); Assert.AreEqual("C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x86__8wekyb3d8bbwe\\MsixPackageTool.exe", d.ExecutablePath); @@ -84,7 +84,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther | ConsentUIFlags.InWindowsDirectory, d.Flags); Assert.AreEqual(2, d.SessionId); Assert.AreEqual((IntPtr)0x000b0586, d.HWnd); - Assert.AreEqual((ConsentUIElevationType)4, d.ElevationType); + Assert.AreEqual(ConsentUIElevationReason.CLSID, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual(new Guid("{3ad05575-8857-4850-9277-11b85bdb8e09}"), d.ClsId); Assert.AreEqual("C:\\Windows\\system32\\windows.storage.dll", d.ComComponentPath); diff --git a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs index 55da8fb..34fe588 100644 --- a/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs +++ b/src/Lithnet.CredentialProvider/ConsentUI/ConsentUIData.cs @@ -36,7 +36,8 @@ namespace Lithnet.CredentialProvider public ConsentUIType Type => this.header.Type; /// - /// Gets a value indicating the consent prompt type + /// Gets a value indicating how UAC has been told to fetch approval. + /// In the case where a Credential Provider is initialised, this should always be `Credentials`. /// public ConsentUIPromptType PromptType => this.header.PromptType; @@ -46,13 +47,13 @@ namespace Lithnet.CredentialProvider public IntPtr HWnd => this.header.hWindow; /// - /// Gets the method that ConsentUI has been told to fetch approval. - /// In the case where a Credential Provider is initialised, this should always be `Credentials`. + /// Gets the reason why `consent.exe` was started in the first place. In other words, + /// the type of action that led to an elevation request. /// - public ConsentUIElevationType ElevationType => this.header.ElevationType; + public ConsentUIElevationReason ElevationReason => this.header.ElevationReason; /// - /// A series of flags that AppInfo passes to ConsentUI to signifiy actions that need to + /// A series of flags that AppInfo passes to ConsentUI to signify actions that need to /// take place on the UI side. /// This includes specifics around the UI that should be presented & signature verification settings. /// diff --git a/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationReason.cs b/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationReason.cs new file mode 100644 index 0000000..76b0025 --- /dev/null +++ b/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationReason.cs @@ -0,0 +1,70 @@ +namespace Lithnet.CredentialProvider +{ + public enum ConsentUIElevationReason + { + /// + /// Application Compatibility + /// e.g. "Run this program as an Administrator" explicitly configured + /// + /// > "The AppCompat database stores information in the application + /// > compatibility fix entries for an application." + /// + AppCompatExplicit = 0, + + /// + /// Application Compatibility + /// e.g. "Run this program as an Administrator" set via Windows heuristics + /// + /// > "The AppCompat database stores information in the application + /// > compatibility fix entries for an application." + /// + AppCompatHeuristic = 1, + + /// + /// Application manifest + /// > "The Fusion database stores information from application + /// > manifests that describe the applications. The manifest schema + /// > is updated to add a new requested execution level field." + /// + /// See also: https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests#trustinfo + /// + Fusion = 2, + + /// + /// Automatically detected Windows Installer package (e.g. an EXE installer) + /// > "Installer detection detects setup files, which helps prevent installations + /// > from being run without the user's knowledge and consent." + /// + Installer = 3, + + /// + /// COM elevation action + /// + CLSID = 4, + + /// + /// Windows Installer package installation (MSI) + /// + Msi = 5, + + /// + /// "Run as Administrator..." (e.g. manual UAC) + /// + Request = 6, + + /// + /// ActiveX Installer Service (AXIS) + /// + AxIS = 7, + + /// + /// Packaged Applications (MSIX / APPX) + /// + PackagedApp = 8, + + /// + /// Unknown + /// + NumReasons = 9, + } +} \ No newline at end of file diff --git a/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationType.cs b/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationType.cs deleted file mode 100644 index b01808b..0000000 --- a/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationType.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Lithnet.CredentialProvider -{ - public enum ConsentUIElevationType - { - Unknown = 0, - - /// - /// Automatic Admin Mode. - /// This seems to be an instance where UAC creates a local, secondary - /// account called '%username%_admin' which is used to elevate a process. - /// - AutomaticAdmin = 1, - - /// - /// Prompt the user for consent (i.e. Yes or No) - /// - Consent = 2, - - /// - /// Prompt the user for credentials - /// - Credentials = 3 - } -} \ No newline at end of file diff --git a/src/Lithnet.CredentialProvider/Enums/ConsentUIFlags.cs b/src/Lithnet.CredentialProvider/Enums/ConsentUIFlags.cs index 08bda47..04a82bf 100644 --- a/src/Lithnet.CredentialProvider/Enums/ConsentUIFlags.cs +++ b/src/Lithnet.CredentialProvider/Enums/ConsentUIFlags.cs @@ -62,7 +62,7 @@ namespace Lithnet.CredentialProvider BlockElevation = 0x1000, /// - /// Corresponds to `ConsentUIElevationType.AutomaticAdmin` + /// Corresponds to `ConsentUIPromptType.AutomaticAdmin` /// This seems to be an instance where UAC creates a local, secondary /// account called '%username%_admin' which is used to elevate a process. /// diff --git a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderBase.cs b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderBase.cs index f58c6b7..2edb82c 100644 --- a/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderBase.cs +++ b/src/Lithnet.CredentialProvider/Interop/Structs/ConsentUIStructureHeaderBase.cs @@ -18,7 +18,7 @@ namespace Lithnet.CredentialProvider.Interop // 32 - public ConsentUIElevationType ElevationType; // 4 + public ConsentUIElevationReason ElevationReason; // 4 public int sessionId; // 4 public IntPtr hMutex; // 8 From 27fe73e32e44b012c0c2d6f483c072af70716354 Mon Sep 17 00:00:00 2001 From: James Spencer Date: Sun, 1 Sep 2024 20:46:37 +1000 Subject: [PATCH 5/5] Update names of ConsentUIElevationReason struct members --- .../V1HeaderTests.cs | 4 +-- .../V2HeaderTests.cs | 4 +-- .../V1HeaderTests.cs | 4 +-- .../Enums/ConsentUIElevationReason.cs | 27 ++++++++++++++++--- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs b/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs index a8d3126..abf486c 100644 --- a/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs +++ b/src/Lithnet.CredentialProvider.UnitTests.x64/V1HeaderTests.cs @@ -65,7 +65,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual( ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); Assert.AreEqual(3, d.SessionId); Assert.AreEqual((IntPtr)0x0, d.HWnd); - Assert.AreEqual(ConsentUIElevationReason.PackagedApp, d.ElevationReason); + Assert.AreEqual(ConsentUIElevationReason.Msix, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual("\"C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe\" ", d.CommandLine); Assert.AreEqual("C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe", d.ExecutablePath); @@ -84,7 +84,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther | ConsentUIFlags.InWindowsDirectory, d.Flags); Assert.AreEqual(3, d.SessionId); Assert.AreEqual((IntPtr)0x00000000000903c2, d.HWnd); - Assert.AreEqual(ConsentUIElevationReason.CLSID, d.ElevationReason); + Assert.AreEqual(ConsentUIElevationReason.Clsid, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual(new Guid("{3ad05575-8857-4850-9277-11b85bdb8e09}"), d.ClsId); Assert.AreEqual("C:\\Windows\\system32\\windows.storage.dll", d.ComComponentPath); diff --git a/src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs b/src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs index 0417bd3..d32e3f3 100644 --- a/src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs +++ b/src/Lithnet.CredentialProvider.UnitTests.x64/V2HeaderTests.cs @@ -66,7 +66,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); Assert.AreEqual(2, d.SessionId); Assert.AreEqual((IntPtr)0x0, d.HWnd); - Assert.AreEqual(ConsentUIElevationReason.PackagedApp, d.ElevationReason); + Assert.AreEqual(ConsentUIElevationReason.Msix, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual("\"C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2024.405.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe\" ", d.CommandLine); Assert.AreEqual("C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2024.405.0_x64__8wekyb3d8bbwe\\MsixPackageTool.exe", d.ExecutablePath); @@ -85,7 +85,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther | ConsentUIFlags.InWindowsDirectory, d.Flags); Assert.AreEqual(2, d.SessionId); Assert.AreEqual((IntPtr)0x00000000000d021e, d.HWnd); - Assert.AreEqual(ConsentUIElevationReason.CLSID, d.ElevationReason); + Assert.AreEqual(ConsentUIElevationReason.Clsid, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual(new Guid("{3ad05575-8857-4850-9277-11b85bdb8e09}"), d.ClsId); Assert.AreEqual("C:\\WINDOWS\\system32\\windows.storage.dll", d.ComComponentPath); diff --git a/src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs b/src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs index 4aa43e8..b2ad989 100644 --- a/src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs +++ b/src/Lithnet.CredentialProvider.UnitTests.x86/V1HeaderTests.cs @@ -65,7 +65,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual( ConsentUIFlags.SecureDesktop | ConsentUIFlags.Unknown3, d.Flags); Assert.AreEqual(2, d.SessionId); Assert.AreEqual((IntPtr)0x0, d.HWnd); - Assert.AreEqual(ConsentUIElevationReason.PackagedApp, d.ElevationReason); + Assert.AreEqual(ConsentUIElevationReason.Msix, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual("\"C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x86__8wekyb3d8bbwe\\MsixPackageTool.exe\" ", d.CommandLine); Assert.AreEqual("C:\\Program Files\\WindowsApps\\Microsoft.MSIXPackagingTool_1.2023.807.0_x86__8wekyb3d8bbwe\\MsixPackageTool.exe", d.ExecutablePath); @@ -84,7 +84,7 @@ namespace Lithnet.CredentialProvider.UnitTests Assert.AreEqual(ConsentUIFlags.SecureDesktop | ConsentUIFlags.AutoElevationOther | ConsentUIFlags.InWindowsDirectory, d.Flags); Assert.AreEqual(2, d.SessionId); Assert.AreEqual((IntPtr)0x000b0586, d.HWnd); - Assert.AreEqual(ConsentUIElevationReason.CLSID, d.ElevationReason); + Assert.AreEqual(ConsentUIElevationReason.Clsid, d.ElevationReason); Assert.AreEqual(ConsentUIPromptType.Credentials, d.PromptType); Assert.AreEqual(new Guid("{3ad05575-8857-4850-9277-11b85bdb8e09}"), d.ClsId); Assert.AreEqual("C:\\Windows\\system32\\windows.storage.dll", d.ComComponentPath); diff --git a/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationReason.cs b/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationReason.cs index 76b0025..9c07c1e 100644 --- a/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationReason.cs +++ b/src/Lithnet.CredentialProvider/Enums/ConsentUIElevationReason.cs @@ -8,6 +8,8 @@ /// /// > "The AppCompat database stores information in the application /// > compatibility fix entries for an application." + /// + /// `ELEVATION_REASON.ELEVATION_REASON_APPCOMPAT_EXPLICIT (ole32.dll)` /// AppCompatExplicit = 0, @@ -17,6 +19,8 @@ /// /// > "The AppCompat database stores information in the application /// > compatibility fix entries for an application." + /// + /// `ELEVATION_REASON.ELEVATION_REASON_APPCOMPAT_HEURISTIC (ole32.dll)` /// AppCompatHeuristic = 1, @@ -25,8 +29,9 @@ /// > "The Fusion database stores information from application /// > manifests that describe the applications. The manifest schema /// > is updated to add a new requested execution level field." - /// /// See also: https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests#trustinfo + /// + /// `ELEVATION_REASON.ELEVATION_REASON_FUSION (ole32.dll)` /// Fusion = 2, @@ -34,36 +39,50 @@ /// Automatically detected Windows Installer package (e.g. an EXE installer) /// > "Installer detection detects setup files, which helps prevent installations /// > from being run without the user's knowledge and consent." + /// + /// `ELEVATION_REASON.ELEVATION_REASON_INSTALLER (ole32.dll)` /// Installer = 3, /// /// COM elevation action + /// + /// `ELEVATION_REASON.ELEVATION_REASON_CLSID (ole32.dll)` /// - CLSID = 4, + Clsid = 4, /// /// Windows Installer package installation (MSI) + /// + /// `ELEVATION_REASON.ELEVATION_REASON_MSI (ole32.dll)` /// Msi = 5, /// /// "Run as Administrator..." (e.g. manual UAC) + /// + /// `ELEVATION_REASON.ELEVATION_REASON_REQUEST (ole32.dll)` /// Request = 6, /// /// ActiveX Installer Service (AXIS) + /// + /// `ELEVATION_REASON.ELEVATION_REASON_AXIS (ole32.dll)` /// - AxIS = 7, + Axis = 7, /// /// Packaged Applications (MSIX / APPX) + /// + /// `ELEVATION_REASON.ELEVATION_REASON_PACKAGED_APP (ole32.dll)` /// - PackagedApp = 8, + Msix = 8, /// /// Unknown + /// + /// `ELEVATION_REASON.ELEVATION_REASON_NUM_REASONS (ole32.dll)` /// NumReasons = 9, }