Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Bagian ini menjelaskan cara menerapkan kode yang kompatibel dengan integritas memori.
Nota
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 dalam Kebijakan Grup atau registri Windows.
Untuk menerapkan kode yang kompatibel, pastikan kode driver Anda melakukan hal berikut:
- Mengaktifkan NX secara default
- Menggunakan NX API/flag 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:
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 ketidaksesuaian integritas memori.
| 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 tipe pool memiliki flag NX yang tidak dapat dieksekusi. |
Lakukan 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 Penjajaran Segmen |
Gambar berisi bagian yang tidak sejajar dengan halaman. Perataan Seksi harus merupakan kelipatan dari 0x1000 (PAGE_SIZE). Misalnya DRIVER_ALIGNMENT=0x1000 |
IAT di Bagian yang Dapat Dieksekusi |
Tabel alamat impor (IAT), seharusnya bukan bagian memori yang dapat dieksekusi. Masalah ini terjadi ketika IAT terletak di bagian memori baca dan eksekusi (RX) saja. Ini berarti bahwa OS tidak akan dapat menulis ke IAT untuk mengatur alamat yang benar di mana DLL yang direferensikan berada. Salah satu cara yang dapat terjadi adalah ketika menggunakan opsi /MERGE (Gabungkan Bagian) dalam penautan kode. Misalnya jika .rdata (Data inisialisasi baca-saja) digabungkan dengan data .text (Kode yang dapat dieksekusi), ada kemungkinan bahwa IAT mungkin berakhir di bagian memori yang dapat dieksekusi. |
Relokasi yang Tidak Didukung
Di 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 tempat linker mengatur alamat dasar defaultnya ke lokasi aktual yang ditetapkan ASLR. Pemindahan ini tidak dapat melintasi batas halaman. Misalnya, pertimbangkan nilai alamat 64-bit yang dimulai pada offset 0x3FFC di halaman. Nilai alamat bergeser ke halaman berikutnya pada offset 0x0003. Jenis relokasi yang tumpang tindih ini tidak didukung sebelum Windows 10, versi 1703.
Situasi ini dapat terjadi ketika penginisialisasi variabel bertipe struct global memiliki penunjuk yang tidak sejajar ke global lain, yang ditata sedemikian rupa sehingga linker tidak dapat memindahkan variabel untuk menghindari relokasi yang melintasi batas. 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 struktur 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