【问题标题】:Get device encryption support information获取设备加密支持信息
【发布时间】:2021-08-10 18:42:42
【问题描述】:

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

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

【问题讨论】:

    标签: c++ windows winapi


    【解决方案1】:

    TL;DR:它使用来自fveapi.dll(Windows Bitlocker 驱动器加密 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"
    

    在反汇编器中搜索contant会得到一个名为:

    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
    

    返回值

    如果函数失败:

    .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 中的函数。似乎它们都没有记录(据我快速搜索所见)。

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

    【讨论】:

      猜你喜欢
      • 2013-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多