Compatibilidade do driver com integridade de memória e VBS

A integridade da memória é um recurso de VBS (segurança baseada em virtualização) disponível em Windows 10, Windows 11 e Windows Server 2016 e posteriores. A integridade da memória e o VBS melhoram o modelo de ameaça do Windows e fornecem proteções mais fortes contra malware que tenta explorar o kernel do Windows. A VBS usa o hipervisor do Windows para criar um ambiente virtual isolado que se torna a raiz de confiança do sistema operacional que pressupõe que o kernel pode ser comprometido. A integridade da memória é um componente crítico que protege e protege o Windows executando a integridade do código do modo kernel no ambiente virtual isolado do VBS. A integridade da memória também restringe as alocações de memória do kernel que podem ser usadas para comprometer o sistema, garantindo que as páginas de memória do kernel só sejam executadas depois de passar em verificações de integridade de código dentro do ambiente de runtime seguro e as próprias páginas executáveis nunca sejam graváveis.

Observação

Às vezes, a integridade da memória é conhecida como HVCI (integridade de código protegida por hipervisor) ou integridade de código imposta pelo hipervisor e foi originalmente lançada como parte do Device Guard. O Device Guard não é mais usado, exceto para localizar a integridade da memória e as configurações de VBS no Política de Grupo ou no Registro do Windows.

A integridade da memória é ativada por padrão em limpo instalações de Windows 10 no modo S e Windows 11 em hardware compatível, conforme descrito na habilitação de integridade da memória. Em outros sistemas que não atendem aos requisitos de habilitação automática de integridade de memória, os clientes podem aceitar o uso de qualquer um dos métodos descritos em como habilitar a integridade da memória.

Compatibilidade de aplicativos

Embora a compatibilidade com a integridade da memória tenha sido um requisito para todos os drivers desde a Atualização de Aniversário do Windows 10 (1607), alguns aplicativos e drivers de dispositivo de hardware ainda podem ser incompatíveis. Essa incompatibilidade pode causar mau funcionamento de dispositivos ou softwares e, em casos raros, pode resultar em uma falha de inicialização (tela azul). Esses problemas podem ocorrer depois que a proteção de integridade de memória tiver sido ativada ou durante o próprio processo de habilitação. Se você for um desenvolvedor de aplicativos e quiser validar se seus drivers e pacotes de software são compatíveis com a integridade da memória, siga estas etapas.

Alguns exemplos em que observamos incompatibilidades com a integridade da memória incluem:

  • Soluções anti-cheat com jogos
  • Métodos de entrada de terceiros
  • Proteção de senha bancária de terceiros

Trabalhamos duro para atenuar as experiências afetadas, portanto, se existir uma incompatibilidade para um driver crítico de inicialização, a proteção de integridade da memória será silenciosamente desativada se ela tiver sido habilitada automaticamente. Se você encontrar incompatibilidades com outros aplicativos, recomendamos que você marcar atualizações para o aplicativo específico e a versão que encontrar o problema antes de desativar a proteção de integridade da memória.

Como criar drivers compatíveis

Como páginas e seções de memória nunca podem ser graváveis e executáveis, a primeira etapa é garantir uma separação clara de dados e código e não tentar modificar diretamente as páginas de código.

  • Aceitar o NX por padrão
  • Usar APIs/sinalizadores do NX para alocação de memória – NonPagedPoolNx
  • Não use seções que sejam graváveis e executáveis
  • Não tente modificar diretamente a memória do sistema executável
  • Não usar código dinâmico no kernel
  • Não carregue arquivos de dados como executáveis
  • O Alinhamento da Seção deve ser um múltiplo de 0x1000 (PAGE_SIZE). Por exemplo, DRIVER_ALIGNMENT=0x1000

Use a versão mais recente do WDK e do Visual Studio para produzir drivers compatíveis ao usar as configurações padrão.

Como verificar a compatibilidade do driver com a integridade da memória

Há três etapas para verificar a compatibilidade do driver:

  1. Use o Verificador de Driver (consulte a seção abaixo) com as verificações de compatibilidade de integridade de código habilitadas.
  2. Teste o driver em um sistema com integridade de memória habilitada.
  3. Execute o Teste de Preparação de Integridade de Código do HyperVisor no Windows HLK.

Verificações de compatibilidade do Verificador de Driver

O Verificador de Driver tem um sinalizador de opção de Integridade de Código (0x02000000) para habilitar verificações extras que validam a conformidade com a integridade da memória. Para habilitar isso na linha de comando, use o seguinte comando:

verifier.exe /flags 0x02000000 /driver <driver.sys>

Para escolher essa opção se estiver usando a GUI do verificador, escolha Criar configurações personalizadas (para desenvolvedores de código), escolha Avançar e escolha Verificações de integridade de código.

Para êxito, não há saída. O abaixo é um exemplo para uma saída de falha.

Driver Verifier: Enabled for DvCi.sys, flags 0x2000000, build 16299, key o4Dbg8OVJqaBYlqWQ2QvRH

\*\*\*\*\*\*\*\*\*\*\* Verifier Detected a Code Integrity Issue \*\*\*\*\*\*\*\*\*\*\*\*

\*\* The caller 0xFFFFF8094B9852F0 specified an executable page protection 0x40.

\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

\*\*\* Verifier assertion failed \*\*\*

(B)reak, (I)gnore, (W)arn only, (R)emove assert? B

Testar o driver com a integridade da memória habilitada

Embora o Windows ative a integridade da memória por padrão para a maioria dos sistemas, há vários motivos que podem impedir que isso aconteça. Para ativar a integridade da memória, consulte Como ativar a integridade da memória. Em seguida, teste a funcionalidade do driver. Exerça todos os caminhos de código no driver para garantir que o driver não execute operações em runtime incompatíveis com a integridade da memória.

Teste de HLK (Desktop e Servidor)

O teste de HLK Teste de Preparação de Integridade de Código do HiperVisor deve ser aprovado para que os drivers sejam aprovados para assinatura da Microsoft. Drivers compatíveis com integridade de memória são necessários para as edições Desktop e Server. O teste HLK é um teste básico gravado para garantir que os drivers compatíveis com integridade de memória sejam carregados e executados corretamente pelo sistema operacional.

Embora simplesmente passar no teste de HLK seja suficiente para uma assinatura da Microsoft para o driver, é altamente recomendável um teste funcional completo com a integridade da memória habilitada. Por exemplo, pode haver alocações de memória codificadas incorretamente violando proteções NX que causam falhas que não seriam capturadas pelo teste. O autor do driver deve testar completamente o driver enquanto mantém a integridade da memória habilitada.

Durante o desenvolvimento do driver e durante o teste de HLK, a integridade da memória pode precisar ser desabilitada, pois pode impedir o carregamento do driver.

O teste de preparação de integridade de código do hipervisor HLK é necessário como parte do AQ do Windows Server Assurance e os sinalizadores para habilitar verificações de integridade de código também são definidos ao habilitar o verificador de driver durante outros testes de HLK.

Perguntas frequentes

E os drivers existentes? Preciso recriar esses drivers para fazê-los trabalhar com Windows 10?

Depende. Muitos drivers já serão compatíveis. Se estiver usando configurações padrão com as versões antigas do WDK e do Visual Studio, um problema conhecido é que a seção INIT está marcada como RWX. No Windows 10, no entanto, o W será removido automaticamente, portanto, se esse for o único problema, o driver será compatível.

Como fazer verificar se a integridade da memória está habilitada?

O método mais simples é executar o aplicativo Informações do Sistema (msinfo32). Procure a seguinte linha: "Serviços de segurança baseados em virtualização em execução". Ele deve relatar: "Integridade de código imposta pelo hipervisor". Também há uma interface WMI para verificar o uso de ferramentas de gerenciamento, consulte Validar recursos de integridade de memória e VBS habilitados.

A integridade da memória também pode ser verificada no aplicativo Segurança do Windows em Configurações>Atualizar & Segurança>Segurança do Windows>Dispositivosdeisolamento> do núcleo de segurança > do dispositivoIntegridade da memória. Para obter mais informações, consulte KB4096339.

Posso verificar se a integridade da memória está habilitada programaticamente do kernel para alterar o comportamento do driver?

Sim, você pode usar NtQuerySystemInformation: https://msdn.microsoft.com/library/windows/desktop/ms724509(v=vs.85).aspx

A estrutura SYSTEM_CODEINTEGRITY_INFORMATION tem um valor 0x400 exposto, indicando que a integridade da memória está ativada.

Como fazer corrigir problemas de compatibilidade?

Além da verificação dupla de que não há páginas W+X e as seções de driver estão alinhadas corretamente, conforme mencionado acima, o problema mais provável será a alocação de memória inadequada. Informações sobre os avisos de Análise de Código relacionados à alocação de memória emitida estão disponíveis no MSDN na página a seguir:

Análise de código para avisos de drivers

Os links msdn a seguir mostram alguns exemplos de APIs comumente usadas que fazem com que a memória executável seja alocada, juntamente com algumas correções de exemplo:

Use a tabela a seguir para interpretar a saída para determinar quais alterações de código de driver são necessárias para resolve os diferentes tipos de incompatibilidades de HVCI.

Aviso Resolução
Executar tipo de pool O chamador especificou um tipo de pool executável. Chamando uma função de alocação de memória que solicita memória executável. Verifique se todos os tipos de pool contêm um sinalizador NX não executável.
Executar Proteção de Página O chamador especificou uma proteção de página executável. Especifique uma máscara de proteção de página "sem execução".
Executar mapeamento de página O chamador especificou um mapeamento de MDL (lista de descritores de memória executável). Verifique se a máscara usada contém MdlMappingNoExecute. Para obter mais informações, consulte MmGetSystemAddressForMdlSafe
Seção Execute-Write A imagem contém uma seção executável e gravável.
Falhas de alinhamento de seção A imagem contém uma seção que não está alinhada à página. O Alinhamento da Seção deve ser um múltiplo de 0x1000 (PAGE_SIZE). Por exemplo, DRIVER_ALIGNMENT=0x1000
Relocs sem suporte No Windows 10 versão 1507 até a versão 1607, devido ao uso da ASLR (Address Space Layout Randomization), um problema pode surgir com alinhamento de endereço e realocação de memória. O sistema operacional precisa realocar o endereço de onde o vinculador definiu seu endereço base padrão para o local real atribuído pela ASLR. Essa realocação não pode ultrapassar um limite de página. Por exemplo, considere um valor de endereço de 64 bits que começa no deslocamento 0x3FFC em uma página. Seu valor de endereço se sobrepõe à próxima página no deslocamento 0x0003. Não há suporte para esse tipo de relocs sobrepostos antes de Windows 10 versão 1703.

Essa situação pode ocorrer quando um inicializador de variável de tipo de struct global tem um ponteiro desalinhado para outro global, disposto de tal forma que o vinculador não pode mover a variável para evitar a realocação. O vinculador tentará mover a variável, mas há situações em que ela pode não ser capaz de fazer isso, por exemplo, com grandes structs desalinhados ou grandes matrizes de structs desalinhados. Quando apropriado, os módulos devem ser montados usando a opção /Gy (COMDAT) para permitir que o vinculador alinhe o código do módulo o máximo possível.

#include <pshpack1.h>

typedef struct _BAD_STRUCT {
      USHORT Value;
      CONST CHAR *String;
} BAD_STRUCT, * PBAD_STRUCT;

#include <poppack.h>

#define BAD_INITIALIZER0 { 0, "BAD_STRING" },
#define BAD_INITIALIZER1 \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0

#define BAD_INITIALIZER2 \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1

#define BAD_INITIALIZER3 \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2

#define BAD_INITIALIZER4 \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3

BAD_STRUCT MayHaveStraddleRelocations[4096] = { // as a global variable
      BAD_INITIALIZER4
};

Há outras situações que envolvem o uso do código assembler, em que esse problema também pode ocorrer.

IAT na Seção Executável A tabela de endereços de importação (IAT) não deve ser uma seção executável da memória.

Esse problema ocorre quando o IAT está localizado em uma seção somente RX (Leitura e Execução) da memória. Isso significa que o sistema operacional não poderá gravar no IAT para definir os endereços corretos para onde a DLL referenciada.

Uma maneira de isso ocorrer é ao usar a opção /MERGE (Combinar Seções) na vinculação de código. Por exemplo, se .rdata (dados inicializados somente leitura) for mesclado com dados .text (código executável), é possível que o IAT possa acabar em uma seção executável da memória.

Quais APIs são potencialmente afetadas?

A seguinte lista de APIs que não estão reservadas para uso do sistema pode ser afetada:

   
Nome da API Descrição
ExAllocatePool https://msdn.microsoft.com/library/windows/hardware/ff544501(v=vs.85).aspx
ExAllocatePoolWithQuota https://msdn.microsoft.com/library/windows/hardware/ff544506(v=vs.85).aspx
ExAllocatePoolWithQuotaTag https://msdn.microsoft.com/library/windows/hardware/ff544513(v=vs.85).aspx
ExAllocatePoolWithTag https://msdn.microsoft.com/library/windows/hardware/ff544520(v=vs.85).aspx
ExAllocatePoolWithTagPriority https://msdn.microsoft.com/library/windows/hardware/ff544523(v=vs.85).aspx
ExInitializeNPagedLookasideList https://msdn.microsoft.com/library/windows/hardware/ff545301(v=vs.85).aspx
ExInitializeLookasideListEx https://msdn.microsoft.com/library/windows/hardware/ff545298(v=vs.85).aspx
MmAllocateContiguousMemory https://msdn.microsoft.com/library/windows/hardware/ff554460(v=vs.85).aspx
MmAllocateContiguousMemorySpecifyCache https://msdn.microsoft.com/library/windows/hardware/ff554464(v=vs.85).aspx
MmAllocateContiguousMemorySpecifyCacheNode https://msdn.microsoft.com/library/windows/hardware/ff554464(v=vs.85).aspx
MmAllocateContiguousNodeMemory https://msdn.microsoft.com/library/windows/hardware/jj602795(v=vs.85).aspx
MmCopyMemory https://msdn.microsoft.com/library/windows/hardware/dn342884(v=vs.85).aspx
MmMapIoSpace https://msdn.microsoft.com/library/windows/hardware/ff554618(v=vs.85).aspx
MmMapLockedPages https://msdn.microsoft.com/library/windows/hardware/ff554622(v=vs.85).aspx
MmMapLockedPagesSpecifyCache https://msdn.microsoft.com/library/windows/hardware/ff554629(v=vs.85).aspx
MmProtectMdlSystemAddress https://msdn.microsoft.com/library/windows/hardware/ff554670(v=vs.85).aspx
ZwAllocateVirtualMemory https://msdn.microsoft.com/library/windows/hardware/ff566416(v=vs.85).aspx
ZwCreateSection https://msdn.microsoft.com/library/windows/hardware/ff566428(v=vs.85).aspx
ZwMapViewOfSection https://msdn.microsoft.com/library/windows/hardware/ff566481(v=vs.85).aspx
NtCreateSection https://msdn.microsoft.com/library/windows/hardware/ff556473(v=vs.85).aspx
NtMapViewOfSection https://msdn.microsoft.com/library/windows/hardware/ff556551(v=vs.85).aspx
StorPortGetDataInBufferSystemAddress https://msdn.microsoft.com/library/windows/hardware/jj553720(v=vs.85).aspx
StorPortGetSystemAddress https://msdn.microsoft.com/library/windows/hardware/ff567100(v=vs.85).aspx
DxgkCbMapMemory https://msdn.microsoft.com/library/windows/hardware/ff559533(v=vs.85).aspx
IMiniportDMus::NewStream https://msdn.microsoft.com/library/windows/hardware/ff536701(v=vs.85).aspx
FltAllocatePoolAlignedWithTag https://msdn.microsoft.com/library/windows/hardware/ff541762(v=vs.85).aspx
FltAllocateContext https://msdn.microsoft.com/library/windows/hardware/ff541710(v=vs.85).aspx
ChangerClassAllocatePool https://msdn.microsoft.com/library/windows/hardware/ff551402(v=vs.85).aspx
IMiniportMidi::NewStream https://msdn.microsoft.com/library/windows/hardware/ff536710(v=vs.85).aspx
IMiniportWaveCyclic::NewStream https://msdn.microsoft.com/library/windows/hardware/ff536723(v=vs.85).aspx
IPortWavePci::NewMasterDmaChannel https://msdn.microsoft.com/library/windows/hardware/ff536916(v=vs.85).aspx
IMiniportWavePci::NewStream https://msdn.microsoft.com/library/windows/hardware/ff536735(v=vs.85).aspx
PcNewDmaChannel https://msdn.microsoft.com/library/windows/hardware/ff537712(v=vs.85).aspx
PcNewResourceList https://msdn.microsoft.com/library/windows/hardware/ff537717(v=vs.85).aspx
PcNewResourceSublist https://msdn.microsoft.com/library/windows/hardware/ff537718(v=vs.85).aspx
VideoPortAllocatePool https://msdn.microsoft.com/library/windows/hardware/ff570180(v=vs.85).aspx
ClfsCreateMarshallingArea https://msdn.microsoft.com/library/windows/hardware/ff541520(v=vs.85).aspx
WdfLookasideListCreate https://msdn.microsoft.com/library/windows/hardware/ff548694(v=vs.85).aspx
WdfMemoryCreate https://msdn.microsoft.com/library/windows/hardware/ff548706(v=vs.85).aspx
WdfDeviceAllocAndQueryProperty https://msdn.microsoft.com/library/windows/hardware/ff545882(v=vs.85).aspx
WdfDeviceAllocAndQueryPropertyEx https://msdn.microsoft.com/library/windows/hardware/dn265599(v=vs.85).aspx
WdfFdoInitAllocAndQueryProperty https://msdn.microsoft.com/library/windows/hardware/ff547239(v=vs.85).aspx
WdfFdoInitAllocAndQueryPropertyEx https://msdn.microsoft.com/library/windows/hardware/dn265612(v=vs.85).aspx
WdfIoTargetAllocAndQueryTargetProperty https://msdn.microsoft.com/library/windows/hardware/ff548585(v=vs.85).aspx
WdfRegistryQueryMemory https://msdn.microsoft.com/library/windows/hardware/ff549920(v=vs.85).aspx
NdisAllocateMemory https://msdn.microsoft.com/library/windows/hardware/ff550762(v=vs.85).aspx