Skip to content

IA32_LSTAR MSR write interception (syscall MSR hook)

Guest'in IA32_LSTAR (MSR 0xC0000082) yazmalarını VMCS MSR bitmap üzerinden trap'leyerek hypervisor'ın syscall entry point'inin kurulduğunu görmesi — kernel base'i anchor'lamak ve syscall dispatch'i guest dışından izlemek için kullanılır.

Mechanism

Note

x86-64'te SYSCALL instruction'ı kontrolü IA32_LSTAR (0xC0000082) içinde tutulan adrese aktarır; Windows'ta bu KiSystemCall64/syscall dispatcher'dır. "use MSR bitmaps" primary processor-based VM-execution control'ünü enable eden ve MSR bitmap içinde 0xC0000082 için write-bit'i set eden bir VMX hypervisor, guest o MSR'a her yazdığında bir WRMSR VM-exit (basic exit reason 32) zorlar. Değer guest tarafından RDX:RAX içinde, index ise RCX içinde sağlandığından, host syscall entry point'ini OS'un onu kurduğu tam anda gözlemler — guest cooperation'ı ve in-guest hook gerekmez.

Bu, inline patch değil, VM-exit tabanlı bir intercept'tir. Host değeri kaydedebilir, olduğu gibi değiştirmeden geçirebilir (transparent observation) veya farklı bir entry ile değiştirebilir (MSR-level syscall hook). Windows early boot sırasında IA32_LSTAR'ı güvenilir biçimde yazar; bu da exit'i ntoskrnl.exe'yi locate etmek için güvenilir bir anchor yapar.

Walkthrough

VMCS setup ve handler akışı (Intel SDM Vol. 3C; Rayanfam "Hypervisor From Scratch Part 8"; secret club introspection write-up'ı):

  1. MSR bitmap'leri enable et. Primary processor-based controls içinde use MSR bitmaps bit'ini set et ve bitmap adresini VMCS field 0x2004 (VMCS_CTRL_MSR_BITMAP_ADDRESS) içinde programla. 4 KB'lık bitmap dört adet 1024-byte region'a sahiptir: read-low / read-high / write-low / write-high.
IA32_LSTAR = 0xC0000082  -> "high" range (0xC0000000–0xC0001FFF)
index within high range  = 0xC0000082 - 0xC0000000 = 0x82
set bit 0x82 in the WRITE-HIGH region -> WRMSR to LSTAR causes a VM-exit

!!! warning Bit'i clear etmek o MSR için hiçbir exit olmaması demektir — guest ona natively erişir. Yalnızca trap'lemek istediğin bit'leri set et; tüm MSR'ları trap'lemek çok daha gürültülü ve yavaştır.

  1. Exit reason 32'yi (WRMSR) handle et. Dispatcher'da index için RCX'i oku ve 64-bit değeri RDX:RAX'tan yeniden oluştur:
case EXIT_REASON_MSR_WRITE: { // 32
    uint32_t msr = guest_rcx();
    uint64_t val = ((uint64_t)guest_rdx() << 32) | (uint32_t)guest_rax();
    if (msr == 0xC0000082) {
        lstar_value = val;            // syscall entry just installed
        record_kernel_anchor(val);    // e.g. scan back for 'MZ'
    }
    __writemsr(msr, val);             // perform the write on the guest's behalf
    advance_guest_rip();              // skip the WRMSR
}
  1. Kernel base'i çöz. secret club write-up'ına göre, MZ PE header'ını bulmak için IA32_LSTAR değerinden geriye doğru memory'yi tara; bu da ntoskrnl.exe'nin virtual ve physical base'ini verir. Sonrasında intercept kaldırılabilir (bitmap bit'ini clear et) ki steady-state syscall'lar natively çalışsın.

Beklenen observable: early boot sırasında 0xC0000082'ye yönelik dispatcher adresini taşıyan tam olarak bir (veya per-CPU birkaç) WRMSR exit; sonrasında, unhook edilmediyse, o MSR için başka exit olmaz.

Detection

  • Bir guest RDMSR IA32_LSTAR yapıp yazdığı değerle karşılaştırabilir; host sessizce farklı bir entry koyduysa read'in sonucu sapar (host ayrıca RDMSR'ı — exit reason 31 — trap'leyip dönüşü spoof etmiyorsa).
  • Timing: her syscall-MSR write bir exit'e yol açıyorsa, boot-time write'ları hafifçe yavaşlar, ama bu nadiren ölçülebilir.

Mitigation

  • Transparent introspection için her zaman gerçek write'ı gerçekleştir ve eğer RDMSR'ı da trap'liyorsan guest'in beklediği değeri döndür (Windows'taki PatchGuard uyuşmayan bir IA32_LSTAR'ı flag'ler).
  • Kötü niyetli MSR-level redirection'ı önlemek için trusted hypervisor MSR bitmap'in sahibi olmalı ve substitution'ları audit etmeli; nested guest'lerde L1 bitmap'ler L0 tarafından sadakatle compose edilmelidir.

References