从C#程序中在没有管理员权限的情况下检测BitLocker

9

从各个线程中我整合了如何以编程方式检查 BitLocker 的方法,如下:

private void TestBitLockerMenuItem_Click(object sender, RoutedEventArgs e) {
   var path=new ManagementPath(@"\ROOT\CIMV2\Security\MicrosoftVolumeEncryption")
               { ClassName="Win32_EncryptableVolume" };
   var scope=new ManagementScope(path);
   path.Server=Environment.MachineName;
   var objectSearcher=new ManagementClass(scope, path, new ObjectGetOptions());
   foreach (var item in objectSearcher.GetInstances()) {
      MessageBox.Show(item["DeviceID"].ToString()+" "+item["ProtectionStatus"].ToString());
   }
}

但是只有拥有管理员权限的进程才能起作用。

似乎很奇怪,任何普通的Windows用户都可以进入资源管理器,右键单击驱动器,并查找是否已打开BitLocker,但某些程序似乎无法实现此功能。 有没有人知道如何解决这个问题?


只检查系统驱动器?还是需要检查其他驱动器? - slypete
理想情况下可以使用任何驱动器,但系统驱动器也可以应付。 - Kevin Donn
现在不相关了,因为我已经想出如何检查任何驱动器了。 - slypete
2个回答

12

Windows使用Win32 API中的Windows Property System检查未记录在案的外壳属性System.Volume.BitLockerProtection,在Shell中显示此属性。您的程序也可以在无需提升权限的情况下检查此属性。

如果此属性的值为1、3或5,则表示磁盘上启用了BitLocker加密,其他任何值则表示关闭了BitLocker。

在寻找解决方案的过程中,我发现参考文献中提到了该外壳属性: HKEY_CLASSES_ROOT\Drive\shell\manage-bde\AppliesTo。最终,这个发现帮助我找到了解决方法。

Windows Property System是一个底层API,但您可以使用Windows API Code Pack中可用的包装器。

Package

Install-Package WindowsAPICodePack

使用

using Microsoft.WindowsAPICodePack.Shell;
using Microsoft.WindowsAPICodePack.Shell.PropertySystem;

代码

IShellProperty prop = ShellObject.FromParsingName("C:").Properties.GetProperty("System.Volume.BitLockerProtection");
int? bitLockerProtectionStatus = (prop as ShellProperty<int?>).Value;

if (bitLockerProtectionStatus.HasValue && (bitLockerProtectionStatus == 1 || bitLockerProtectionStatus == 3 || bitLockerProtectionStatus == 5))
   Console.WriteLine("ON");
else
   Console.WriteLine("OFF");

下一步解锁:https://social.msdn.microsoft.com/Forums/en-US/26c44d82-7aa3-4d18-a963-b86eb617a609/unlock-bit-locker-programmatically - Daniel Fisher lennybacon
2
当我在调试时,这个程序可以正常运行,但是当我在Windows服务中运行时就会失败。无论服务运行在哪个用户下:本地系统、本地服务或管理员账户,都无法正常运行。你有什么想法是什么问题或解决方法吗? - juicebyjustin
感谢您的出色回答。不过有一个小问题。在我的 Windows 10(2004)PC 上,一个被 BitLocker 保护且仍处于锁定状态的驱动器返回“bitLockerProtectionStatus”为6。 - Paul Williams
有人能提供一个不同值的含义列表以及可以在哪里找到这样的信息吗?我怀疑1、3、5表示各种保护级别,例如整个驱动器或不到整个驱动器等。然而,我找不到任何关于每个值的含义甚至可以返回多少值的文档。 - CodeWhore
@CodeWhore,请查看此答案 https://dev59.com/Hn_aa4cB1Zd3GeqP-f7D#64328877 - slypete

0
以下 COM 方法结合反射可在 .NET 6(以及可能的旧版本)中使用,无需任何外部库。虽然 COM 不是最受支持的路径,但它是一个很好的选择。
        var netFwMgrType = Type.GetTypeFromProgID("Shell.Application", false);
        var manager = Activator.CreateInstance(netFwMgrType);
        var c = manager.GetType().InvokeMember("NameSpace", BindingFlags.InvokeMethod, null, manager, new object[] { "C:" });
        var self = c.GetType().InvokeMember("Self", BindingFlags.GetProperty, null, c, new object[] { });
        var result = self.GetType().InvokeMember("ExtendedProperty", BindingFlags.InvokeMethod, null, self, new object[] { "System.Volume.BitLockerProtection" });

根据您的项目构建方式,您可能需要将此内容添加到您的csproj文件中。

<BuiltInComInteropSupport>true</BuiltInComInteropSupport>

由于某些原因,以上方法无法在LOCAL_SYSTEM帐户上运行。因此,当您拥有管理员特权时,以下是使用WMI的操作方法。

尽管问题明确要求不使用管理员权限,但我认为这是一个很好的地方来分享这段代码。这需要.NET System.Management库。

var result = new ManagementObjectSearcher(@"root\cimv2\security\MicrosoftVolumeEncryption", "SELECT * FROM Win32_Encryptablevolume")
                .Get().OfType<ManagementObject>()
                .Where(obj => obj.GetPropertyValue("DriveLetter").ToString() == "C:")
                .Select(obj => obj.GetPropertyValue("ConversionStatus"))
                .Cast<uint>()

请注意,这种方法返回的代码与其他方法不同。在此处记录:https://learn.microsoft.com/en-us/windows/win32/secprov/getconversionstatus-win32-encryptablevolume

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接