Sottochiave protetta CI
In quest’ultima sezione vedremo come i valori sotto RegKey CI\Protected
sono protetti dal sistema operativo. Questo è fondamentale per la funzionalità perché essere in grado di controllare VerifiedAndReputablePolicyStateMinValueSeen
ci consentirebbe di modificare lo stato SAC tra i riavvii.
Durante CiInitializePolicy
la prima funzione che verrà chiamata è CipCheckLicensing
. Questa routine sarà la prima ad aprire la sottochiave \\CurrentControlSet\\Control\\CI\\Protected
: questa volta viene aperta per verificare il Licensed
valore ma non è rilevante.
Una volta che l’elemento della configurazione ha ottenuto un handle per la Protected
sottochiave, utilizzerà uno dei metodi forniti dal kernel durante l’inizializzazione nella SeCiPrivateApis
tabella. In particolare il metodo SepZwLockRegistryKey
. Questo metodo raggiungerà NtLockRegistryKey
(in tutta la Zw
versione). NtLockRegistryKey
utilizzerà l’Handle della chiave per ottenere un riferimento all’Oggetto, gli oggetti chiave sono rappresentati con la CM_KEY_BODY
struttura. L’oggetto chiave verrà passato a CmLockKeyForWrite
, che otterrà la CM_KEY_CONTROL_BLOCK
chiamata e CmpGlobalLockKeyForWrite
. Vedi la seguente pila:
1: kd> k
# Child-SP RetAddr Call Site
00 fffff882`b2a06500 fffff805`3f7a6189 nt!CmpGlobalLockKeyForWrite+0xbe
01 fffff882`b2a06540 fffff805`3f7a6020 nt!CmLockKeyForWrite+0x11d
02 fffff882`b2a06590 fffff805`3f432465 nt!NtLockRegistryKey+0x70
03 fffff882`b2a065e0 fffff805`3f424380 nt!KiSystemServiceCopyEnd+0x25
04 fffff882`b2a06778 fffff805`3f86cab9 nt!KiServiceLinkage
05 fffff882`b2a06780 fffff805`43ff4e87 nt!SepZwLockRegistryKey+0x9
06 fffff882`b2a067b0 fffff805`43ff24bf CI!CipCheckLicensing+0x1fb
07 fffff882`b2a068a0 fffff805`3fb5766c CI!CiInitializePolicy+0x4f
08 fffff882`b2a069d0 fffff805`3fb2a59b nt!SeCodeIntegrityInitializePolicy+0x70
09 fffff882`b2a06a00 fffff805`3f825d43 nt!Phase1InitializationDiscard+0xb0f
0a fffff882`b2a06bb0 fffff805`3f2c3977 nt!Phase1Initialization+0x23
0b fffff882`b2a06bf0 fffff805`3f423bb4 nt!PspSystemThreadStartup+0x57
0c fffff882`b2a06c40 00000000`00000000 nt!KiStartSystemThread+0x34
All’interno CmpGlobalLockKeyForWrite
dell’ExtFlag CM_KCB_READ_ONLY_KEY (0x80)
verrà impostato il KCB per questo oggetto Key. Questo è interessante perché la protezione è a livello di Object Manager. Osservando NtSetValueKey
possiamo vedere come vengono controllati i KCB ExtFlags per vedere se l’oggetto è ReadOnly per negare o meno l’operazione. Ciò non applicherà né i privilegi dell’utente né la modalità precedente. Vedere l’immagine seguente per vederlo in azione quando si tenta di manipolare VerifiedAndReputablePolicyStateMinValueSeen
– Nota:RegNtSetValueKey
verrà chiamato il callback CM , RegNtPostSetValueKey
non lo sarà.

Naturalmente, winload
è in grado di modificare questo valore poiché il kernel non è in esecuzione a questo punto. Se cerchiamo all’interno i System32
binari che fanno riferimento alla stringa VerifiedAndReputablePolicyStateMinValueSeen
troveremo solo:
- winload.exe
- windload.efi
- tcbloader.dll
Personalmente penso che questa sia una soluzione semplice per proteggere la chiave. Questo era già in atto per proteggere il Licensed
valore, quindi probabilmente non è stato necessario aggiungere codice per questo. Ma mi chiedo perché MS non abbia scelto di memorizzare questo valore in uno spazio come TPM NV Storage. Non così risolverebbe tutto. Ma sento che RegKey è più facile da manipolare: ad esempio, usare WinRE per aprire l’editor del registro, quindi caricare l’hive del SISTEMA OS sarebbe un modo plausibile per modificare il valore VerifiedAndReputablePolicyStateMinValueSeen
. Di sicuro, se qualcuno riesce a caricare WinRE e cambiarlo hai problemi più grossi