获取设备加密支持信息

Get device encryption support information

我想在我的程序中检测设备加密支持。此信息在 System Information 程序中可用。请查看下面的屏幕截图:

检测设备加密支持的 Win API 函数有哪些 used/available? System Information 程序使用什么来检测它?我只是需要一些信息。

TL;DR:它使用了 fveapi.dll 中未记录的函数(Windows Bitlocker Drive Encryption API)。它似乎只依赖于 TPM 功能。


请注意,我只花了大约 15 分钟,但我怀疑我错过了一些重要的东西,尽管这可能是可能的。

一点逆向工程

在搜索栏中输入 system information,看到它生成了 msinfo32.exe。将二进制文件放入反汇编程序中。它使用 MUI 文件,所以我必须在 MUI 文件中搜索字符串,而不是可执行文件。

搜索 Device Encryption Support 导致字符串 ID 951 (0x3b7)

STRINGTABLE
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
{
  951,  "Device Encryption Support|%s"

在反汇编程序中搜索内容会导致一个名为的函数:

DeviceEncryptionDataPoints(struct CWMIHelper *, struct CPtrList *)

前面提到的字符串加载几乎就在开头:

.text:00000001400141E9                 mov     edx, 3B7h
.text:00000001400141EE                 lea     rcx, [rsp+2C8h+var_280]
.text:00000001400141F3
.text:00000001400141F3 loc_1400141F3:
.text:00000001400141F3 ;   try {
.text:00000001400141F3                 call    cs:__imp_?LoadStringW@CString@@QEAAHI@Z ; CString::LoadStringW(uint)

所以我们绝对是在正确的功能。

它加载 fveapi.dll 模块:

.text:0000000140014269                 xor     edx, edx        ; hFile
.text:000000014001426B                 mov     r8d, 800h       ; dwFlags
.text:0000000140014271                 lea     rcx, LibFileName ; "fveapi.dll"
.text:0000000140014278                 call    cs:__imp_LoadLibraryExW

获取 FveQueryDeviceEncryptionSupport 上的指针:

.text:00000001400142AB                 lea     rdx, aFvequerydevice ; "FveQueryDeviceEncryptionSupport"
.text:00000001400142B2                 mov     rcx, rdi        ; hModule
.text:00000001400142B5                 call    cs:__imp_GetProcAddress

并立即调用该函数(这是一个受保护的 CFG 调用,但它在这里):

.text:00000001400142CA                 mov     [rsp+2C8h+var_254], rbx
.text:00000001400142CF                 mov     [rsp+2C8h+var_260], 14h
.text:00000001400142D7                 mov     [rsp+2C8h+var_25C], 1
.text:00000001400142DF                 mov     [rsp+2C8h+var_258], 1
.text:00000001400142E7                 lea     rcx, [rsp+2C8h+var_260]
.text:00000001400142EC                 call    cs:__guard_dispatch_icall_fptr

Return值

如果函数失败:

.text:00000001400142EC                 call    cs:__guard_dispatch_icall_fptr
.text:00000001400142F2                 mov     esi, eax
.text:00000001400142F4                 test    eax, eax
.text:00000001400142F6                 js      loc_1400143F0 ; check failure

我们降落在这里:

.text:00000001400143F7                 mov     edx, 2FFh
.text:00000001400143FC                 lea     rcx, [rsp+2C8h+var_288]
.text:0000000140014401                 call    cs:__imp_?LoadStringW@CString@@QEAAHI@Z ; CString::LoadStringW(uint)

字符串 0x2FF (767) 是:

 767,   "Elevation Required to View"

如果调用成功,代码将检查其中一个参数,该参数肯定是 out 参数:

.text:00000001400142EC                 call    cs:__guard_dispatch_icall_fptr
.text:00000001400142F2                 mov     esi, eax
.text:00000001400142F4                 test    eax, eax
.text:00000001400142F6                 js      loc_1400143F0
.text:00000001400142FC                 cmp     dword ptr [rsp+2C8h+var_254], ebx ; rbx = 0
.text:0000000140014300                 jnz     short loc_14001431D
.text:0000000140014302                 mov     edx, 3B8h
.text:0000000140014307                 lea     rcx, [rsp+2C8h+var_288]
.text:000000014001430C                 call    cs:__imp_?LoadStringW@CString@@QEAAHI@Z ; CString::LoadStringW(uint)

如果为 0,则使用字符串 0x3b8 (952):

  952,  "Meets prerequisites"

否则调用各种故障函数。

失败

万一失败,调用UpdateDeviceEncryptionStateFailureString函数:

.text:0000000140014325                 lea     r9, [rsp+2C8h+var_294] ; int *
.text:000000014001432A                 lea     r8, [rsp+2C8h+var_290] ; int *
.text:000000014001432F                 mov     edx, 3C1h       ; unsigned int
.text:0000000140014334                 lea     rcx, [rsp+2C8h+var_288] ; struct CString *
.text:0000000140014339                 call    ?UpdateDeviceEncryptionStateFailureString@@YAXPEAVCString@@IPEAH1@Z ; UpdateDeviceEncryptionStateFailureString(CString *,uint,int *,int *)

它的主要目标是从资源文件中获取一些字符串。

最突出的是 0x3b9:

.text:0000000140013A37                 mov     edx, 3B9h
.text:0000000140013A3C                 mov     rcx, rbx
.text:0000000140013A3F                 call    cs:__imp_?LoadStringW@CString@@QEAAHI@Z ; CString::LoadStringW(uint)
  953,  "Reasons for failed automatic device encryption"

我的情况就是这样,因为我没有 TPM。

其他功能

DeviceEncryptionDataPoints 调用的所有其他函数(至少为了获得所需的结果)都来自 fveapi.dll

一个函数里有很多东西叫做PerformIndividualHardwareTests(HINSTANCE hModule, struct CString *, int *, int *):

.text:0000000140013AEF                 lea     rdx, aNgscbcheckisao ; "NgscbCheckIsAOACDevice"
.text:0000000140013AF6                 mov     [rbp+var_1F], 0
.text:0000000140013AFA                 mov     rdi, r9
.text:0000000140013AFD                 mov     [rbp+var_20], 0
.text:0000000140013B01                 mov     rsi, r8
.text:0000000140013B04                 mov     [rbp+var_1E], 0
.text:0000000140013B08                 mov     rbx, rcx
.text:0000000140013B0B                 call    cs:__imp_GetProcAddress
.text:0000000140013B12                 nop     dword ptr [rax+rax+00h]
.text:0000000140013B17                 mov     r12, rax
.text:0000000140013B1A                 test    rax, rax
.text:0000000140013B1D                 jz      loc_140013CB9
.text:0000000140013B23                 lea     rdx, aNgscbcheckishs ; "NgscbCheckIsHSTIVerified"
.text:0000000140013B2A                 mov     rcx, rbx        ; hModule
.text:0000000140013B2D                 call    cs:__imp_GetProcAddress
.text:0000000140013B34                 nop     dword ptr [rax+rax+00h]
.text:0000000140013B39                 mov     r15, rax
.text:0000000140013B3C                 test    rax, rax
.text:0000000140013B3F                 jz      loc_140013CB9
.text:0000000140013B45                 lea     rdx, aNgscbcheckhsti ; "NgscbCheckHSTIPrerequisitesVerified"
.text:0000000140013B4C                 mov     rcx, rbx        ; hModule
.text:0000000140013B4F                 call    cs:__imp_GetProcAddress
.text:0000000140013B56                 nop     dword ptr [rax+rax+00h]
.text:0000000140013B5B                 mov     r13, rax
.text:0000000140013B5E                 test    rax, rax
.text:0000000140013B61                 jz      loc_140013CB9
.text:0000000140013B67                 lea     rdx, aNgscbcheckdmas ; "NgscbCheckDmaSecurity"
.text:0000000140013B6E                 mov     rcx, rbx        ; hModule
.text:0000000140013B71                 call    cs:__imp_GetProcAddress

还检查了一个注册表项 SYSTEM\CurrentControlSet\Control\BitLocker\AutoDE\HSTI:

.text:0000000140013C10                 lea     r8, ?NGSCB_AUTODE_HSTI_REQUIRED@@3QBGB ; "HSTIVerificationRequired"
.text:0000000140013C17                 mov     [rsp+60h+pcbData], rax ; pcbData
.text:0000000140013C1C                 lea     rdx, ?NGSCB_AUTODE_HSTI_PREREQS@@3QBGB ; "SYSTEM\CurrentControlSet\Control\Bit"...
.text:0000000140013C23                 lea     rax, [rbp+var_1C]
.text:0000000140013C27                 mov     r9d, 10h        ; dwFlags
.text:0000000140013C2D                 mov     [rsp+60h+pvData], rax ; pvData
.text:0000000140013C32                 mov     rcx, 0FFFFFFFF80000002h ; hkey
.text:0000000140013C39                 and     [rsp+60h+var_40], 0
.text:0000000140013C3F                 call    cs:__imp_RegGetValueW

和一些其他功能(NgscbCheckPreventDeviceEncryptionNgscbGetWinReConfigurationFveCheckTpmCapability、...),再次,全部来自 fveapi.dll 模块。

所以基本上检查都是基于这个 DLL 中的函数。似乎其中 none 个已记录在案(据我快速搜索所见)。

我在 DeviceEncryptionDataPoints 调用方(基本上是 main() 函数)中没有找到任何东西,因为下一个调用是处理检查管理程序功能。