Menerapkan kode yang kompatibel dengan integritas memori

Bagian ini menjelaskan cara menerapkan kode yang kompatibel dengan integritas memori.

Catatan

Integritas memori terkadang disebut sebagai integritas kode yang dilindungi hypervisor (HVCI) atau integritas kode yang diberlakukan hypervisor, dan awalnya dirilis sebagai bagian dari Device Guard. Device Guard tidak lagi digunakan kecuali untuk menemukan integritas memori dan pengaturan VBS di Kebijakan Grup atau registri Windows.

Untuk menerapkan kode yang kompatibel, pastikan kode driver Anda melakukan hal berikut:

  • Ikut serta ke NX secara default
  • Menggunakan API/bendera NX untuk alokasi memori (NonPagedPoolNx)
  • Tidak menggunakan bagian yang dapat ditulis dan dapat dieksekusi
  • Tidak mencoba mengubah memori sistem yang dapat dieksekusi secara langsung
  • Tidak menggunakan kode dinamis dalam kernel
  • Tidak memuat file data sebagai file yang dapat dieksekusi
  • Perataan bagian adalah kelipatan 0x1000 (PAGE_SIZE). Misalnya DRIVER_ALIGNMENT=0x1000

Daftar DDI berikut yang tidak dicadangkan untuk penggunaan sistem dapat terpengaruh:

Nama DDI
ExAllocatePool
ExAllocatePoolWithQuota
ExAllocatePoolWithQuotaTag
ExAllocatePoolWithTag
ExAllocatePoolWithTagPriority
ExInitializeNPagedLookasideList
ExInitializeLookasideListEx
MmAllocateContiguousMemory
MmAllocateContiguousMemorySpecifyCache
MmAllocateContiguousMemorySpecifyCacheNode
MmAllocateContiguousNodeMemory
MmCopyMemory
MmMapIoSpace
MmMapLockedPages
MmMapLockedPagesSpecifyCache
MmProtectMdlSystemAddress
ZwAllocateVirtualMemory
ZwCreateSection
ZwMapViewOfSection
NtCreateSection
NtMapViewOfSection
ClfsCreateMarshallingArea
NDIS
NdisAllocateMemoryWithTagPriority
Penyimpanan
StorPortGetDataInBufferSystemAddress
StorPortGetSystemAddress
ChangerClassAllocatePool
Tampilan
DxgkCbMapMemory
VideoPortAllocatePool
Audio Miniport
IMiniportDMus::NewStream
IMiniportMidi::NewStream
IMiniportWaveCyclic::NewStream
IPortWavepci::NewMasterDmaChannel
IMiniportWavePci::NewStream
Kelas Port Audio
PcNewDmaChannel
PcNewResourceList
PcNewResourceSublist
IFS
FltAllocatePoolAlignedWithTag
FltAllocateContext
WDF
WdfLookasideListCreate
WdfMemoryCreate
WdfDeviceAllocAndQueryProperty
WdfDeviceAllocAndQueryPropertyEx
WdfFdoInitAllocAndQueryProperty
WdfFdoInitAllocAndQueryPropertyEx
WdfIoTargetAllocAndQueryTargetProperty
WdfRegistryQueryMemory

Gunakan pengujian integritas kode di HLK untuk menguji kompatibilitas driver integritas memori

Untuk informasi selengkapnya tentang pengujian keamanan dasar-dasar sistem terkait, lihat Uji Kesiapan Integritas Kode HyperVisor dan Integritas memori dan VBS.

Untuk informasi selengkapnya tentang pengujian dasar-dasar perangkat terkait, lihat Pengujian Device.DevFund.

Gunakan tabel berikut untuk menginterpretasikan output dan menentukan perubahan kode driver apa yang diperlukan untuk memperbaiki berbagai jenis integritas memori yang tidak kompatibel.

Peringatan Penebusan

Tipe Kumpulan Eksekusi

Pemanggil menentukan jenis kumpulan yang dapat dieksekusi. Memanggil fungsi alokasi memori yang meminta memori yang dapat dieksekusi.

Pastikan bahwa semua jenis kumpulan berisi bendera NX yang tidak dapat dieksekusi.

Jalankan Perlindungan Halaman

Pemanggil menentukan perlindungan halaman yang dapat dieksekusi.

Tentukan masker perlindungan halaman "tanpa eksekusi".

Jalankan Pemetaan Halaman

Pemanggil menentukan pemetaan daftar deskriptor memori (MDL) yang dapat dieksekusi.

Pastikan bahwa masker yang digunakan berisi MdlMappingNoExecute. Untuk informasi selengkapnya, lihat MmGetSystemAddressForMdlSafe

Bagian Execute-Write

Gambar berisi bagian yang dapat dieksekusi dan dapat ditulis.

Kegagalan Perataan Bagian

Gambar berisi bagian yang tidak diratakan halaman.

Perataan Bagian harus berupa kelipatan 0x1000 (PAGE_SIZE). Misalnya DRIVER_ALIGNMENT=0x1000

IAT di Bagian yang Dapat Dieksekusi

Tabel alamat impor (IAT), tidak boleh menjadi bagian memori yang dapat dieksekusi.

Masalah ini terjadi ketika IAT, terletak di bagian memori hanya Baca dan Jalankan (RX). Ini berarti bahwa OS tidak akan dapat menulis ke IAT untuk mengatur alamat yang benar tempat DLL yang direferensikan.

Salah satu cara ini dapat terjadi adalah saat menggunakan opsi /MERGE (Gabungkan Bagian) dalam penautan kode. Misalnya jika .rdata (Data yang diinisialisasi baca-saja) digabungkan dengan data .text (Kode yang dapat dieksekusi), ada kemungkinan bahwa IAT mungkin berakhir di bagian memori yang dapat dieksekusi.


Relokasi tidak didukung

Dalam Windows 10, versi 1507 hingga Windows 10, versi 1607, karena penggunaan Address Space Layout Randomization (ASLR) masalah dapat muncul dengan penyelarasan alamat dan relokasi memori. Sistem operasi perlu merelokasi alamat dari mana linker mengatur alamat dasar defaultnya ke lokasi aktual yang ditetapkan ASLR. Relokasi ini tidak dapat mengalihkan batas halaman. Misalnya, pertimbangkan nilai alamat 64-bit yang dimulai pada 0x3FFC offset di halaman. Nilai alamat ini tumpang tindih ke halaman berikutnya pada 0x0003 offset. Jenis relokasi yang tumpang tindih ini tidak didukung sebelum Windows 10, versi 1703.

Situasi ini dapat terjadi ketika penginisialisasi variabel jenis struct global memiliki penunjuk yang tidak sejajar ke global lain, ditata sedih sehingga linker tidak dapat memindahkan variabel untuk menghindari relokasi terdampar. Linker akan mencoba memindahkan variabel, tetapi ada situasi di mana mungkin tidak dapat melakukannya (misalnya dengan struktur besar yang tidak sejajar atau array besar dari struct yang tidak sejajar). Jika sesuai, modul harus dirakit menggunakan opsi /Gy (COMDAT) untuk memungkinkan linker menyelaraskan kode modul sebanyak mungkin.

#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
};

Ada situasi lain yang melibatkan penggunaan kode perakitan, di mana masalah ini juga dapat terjadi.


Integritas kode Driver Verifier

Gunakan bendera opsi integritas kode Driver Verifier (0x02000000) untuk mengaktifkan pemeriksaan tambahan yang memvalidasi kepatuhan dengan fitur ini. Untuk mengaktifkan ini dari baris perintah, gunakan perintah berikut.

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

Untuk memilih opsi ini jika menggunakan GUI pemverifikasi, pilih Buat pengaturan kustom (untuk pengembang kode), pilih Berikutnya, lalu pilih Pemeriksaan integritas kode.

Anda dapat menggunakan opsi baris perintah /kueri pemverifikasi untuk menampilkan informasi pemverifikasi driver saat ini.

verifier /query

Lihat juga

Daftar periksa keamanan driver