在做 StartCTF 的 Misc 题的时候装不上爆破的工具,于是换了一条思路。既然是微软的东西,自然可以 C# 一把梭写一个爆破小工具,于是找到 Win32_EncryptableVolume
文档顺带查了一些资料就开干了。
准备工作
参考文档
既然是要跟 WMI provider 打交道,WMI CRUD 是必不可少的,于是找了个轮子。
Microsoft Docs
https://docs.microsoft.com/en-us/windows/win32/secprov/win32-encryptablevolume
Stack Overflow 参考
https://stackoverflow.com/questions/56360904/bitlocker-values
确认服务开启
WMI Performance Adapter(wmiApSrv)、BitLocker Drive Encryption Service(BDESVC) 需要保持正在运行的状态。
挂载磁盘
将 vhdx 虚拟磁盘文件挂载到计算机中。
按照文档构建
确定 helper scope
从文档的 Requirements 查阅可知 Win32_EncryptableVolume
位于 Root\CIMV2\Security\MicrosoftVolumeEncryption
。于是连接至 WMI 时需要将 scope 对应着更改。
1 | WMIHelper helper = new WMIHelper("Root\\CIMV2\\Security\\MicrosoftVolumeEncryption"); |
构建类
ORMi 提供了 [WMIClass()]
的 attribute 用来给类指定别名,[WMIProperty()]
用来给属性指定别名。在未指定别名时,名称需要与文档中保持一致。
1 | [ ] |
写方法
文档中提供了几种用于解锁的方法。
1 | UnlockWithAdSid : 使用 Active Directory security identifier (SID) 获取 key |
这里采用的是 UnlockWithPassphrase
方法朴素地使用驱动器密码去解锁 BitLocker。
1 | uint32 GetLockStatus( |
文档里对于参数和返回值给出了托管对象格式,但是并不太浅显,调试之后发现 [out]
被塞进了一个 ExpandoObject
,而文档中标识的传入 [in]
则是直接以 Object 的形式传入。
因为方法的返回值为一个 ExpandoObject
,因此需要使用一个类来接收值。同时需要配合 ORMi,使用 WMIMethod.ExecuteMethod
来调用对应的方法。这里主要需要的是判断磁盘当前 lock 状态以及使用密码解锁的方法,对照着文档将其还原。
1 | public LockStatus GetLockStatus(){ |
主要逻辑
第一步实例化了一个 WMIHelper
,这里可以使用它的 Query
方法去查询出所有的 EncryptableVolume
得到一个 List。然后遍历之后使用 GetLockStatus()
去查询状态,当状态为 Locked 的时候就读取字典调用解锁方法尝试解锁直到 ReturnValue
为 S_OK 的时候 即解锁成功,当解锁不成功时将得到返回值 FVE_E_FAILED_AUTHENTICATION。
1 | public static void Main(string[] args){ |
记
这篇文章写得不是很细,因为文档上记载了很多不一样的方法以及操作,微软的文档写得巨细靡遗的同时又极度严谨。因为感觉做的时候资料不是太多,所以写出来希望能提供一些正确且有意义的参考。除此之外,工具装不上就自己写一个既定作用的这件事还是蛮好玩的,虽然效率应该是比不上某装了蛮久没装上的工具。