
Utilità da riga di comando di Windows per leggere, scrivere ed eseguire codice in modalità kernel dal contesto di Amministratore utilizzando una tecnica di reindirizzamento dell'esecuzione tramite validazione dei font, consentendo debug avanzato del kernel e risoluzione dei problemi di sistema.
r0ak è un'utilità da riga di comando per Windows che consente di leggere, scrivere ed eseguire codice in modalità kernel (con alcune limitazioni) dal prompt dei comandi, senza richiedere altro che privilegi di Amministratore.
r0ak v1.0.0 -- Ring 0 Army Knife
http://www.github.com/ionescu007/r0ak
Copyright (c) 2018 Alex Ionescu [@aionescu]
http://www.windows-internals.com
USAGE: r0ak.exe
[--execute <Address | module.ext!function> <Argument>]
[--write <Address | module.ext!function> <Value>]
[--read <Address | module.ext!function> <Size>]

Il kernel di Windows è un ambiente ricco in cui centinaia di driver vengono eseguiti su un sistema tipico, e dove sono presenti migliaia di variabili contenenti stato globale. Per la risoluzione avanzata dei problemi, gli esperti IT utilizzano solitamente strumenti come il Windows Debugger (WinDbg), gli strumenti SysInternals o scrivono i propri. Sfortunatamente, l'uso di questi strumenti sta diventando sempre più difficile e sono essi stessi limitati dal proprio accesso alle API di Windows e alle funzionalità esposte.
Alcune delle sfide odierne includono:
In un tale ambiente, era chiaro che uno strumento semplice, utilizzabile come cerotto/hotfix di emergenza e per risolvere rapidamente problemi a livello di kernel/sistema che potrebbero essere evidenti analizzando lo stato del kernel, potrebbe essere prezioso per la comunità.

r0ak funziona reindirizzando il flusso di esecuzione dei controlli di validazione dei font attendibili del gestore delle finestre quando si tenta di caricare un nuovo font, sostituendo la routine di confronto della tabella dei font attendibili con una funzione alternativa che pianifica un elemento di lavoro esecutivo (WORK_QUEUE_ITEM) memorizzato nel nodo di input. Quindi, il figlio destro della tabella dei font attendibili (che funge da nodo radice) viene sovrascritto con un buffer di scrittura di una named pipe (NP_DATA_ENTRY) in cui è memorizzato un elemento di lavoro personalizzato. La funzione di lavoro sottostante di questo elemento e il suo parametro verranno eventualmente eseguiti da un ExpWorkerThread dedicato a PASSIVE_LEVEL una volta che si tenta di caricare un font e la routine di confronto viene eseguita, ricevendo come input il nodo padre basato sulla named pipe. Un evento di traccia ETW (Event Tracing for Windows) in tempo reale viene utilizzato per ricevere una notifica asincrona che l'elemento di lavoro ha terminato l'esecuzione, rendendo sicuro smantellare le strutture, liberare i buffer in modalità kernel e ripristinare il funzionamento normale.
Quando si utilizza l'opzione --execute, questa funzione e parametro vengono forniti dall'utente.
Quando si utilizza --write, viene utilizzato un gadget personalizzato per modificare valori arbitrari a 32 bit in qualsiasi punto della memoria del kernel.
Quando si utilizza --read, il gadget di scrittura viene utilizzato per modificare il puntatore e la dimensione del buffer HSTI del sistema (N.B.: Questo è un comportamento distruttivo in termini di qualsiasi altra applicazione che richiederà i dati HSTI. Poiché questo è un comportamento opzionale di Windows e questo strumento è destinato al debug/sperimentazione di emergenza, questa perdita di dati è stata considerata accettabile). Quindi, l'API di interrogazione HSTI viene utilizzata per copiare i dati nello spazio degli indirizzi in modalità utente dello strumento e viene mostrato un dump esadecimale.
Poiché vengono utilizzate solo funzionalità Windows integrate, firmate da Microsoft, e tutte le funzioni chiamate fanno parte della bitmap KCFG, non vi è alcuna violazione di alcun controllo di sicurezza e non sono richiesti flag di debug o l'uso di driver di terze parti mal scritti.
No. Poiché questo strumento — e la tecnica sottostante — richiedono un token privilegiato a livello SYSTEM, ottenibile solo da un utente che esegue un account Amministratore, non vengono bypassati confini di sicurezza per ottenere l'effetto. Il comportamento e l'utilità dello strumento sono possibili solo grazie al contesto di sicurezza elevato/privilegiato dell'account Amministratore su Windows, ed è inteso come un comportamento di progettazione.
Certo! È importante segnalare sempre i problemi di sicurezza a Microsoft anche quando non sembra esserci violazione dei confini privilegiati — i loro team di ricercatori e sviluppatori potrebbero trovare nuovi vettori e modi per raggiungere determinati percorsi di codice a cui un ricercatore esterno potrebbe non aver pensato.
Pertanto, nel novembre 2014, è stato presentato un caso di sicurezza al Microsoft Security Research Centre (MSRC) che ha risposto: "[…] non rientra nell'ambito di un problema di sicurezza che affronteremmo tramite il nostro veicolo tradizionale di bollettini di sicurezza. […] presuppone privilegi di amministratore — un luogo in cui, a livello architetturale, non definiamo attualmente un confine di sicurezza difendibile. Pertanto, non perseguiremo la correzione di questo problema."
Inoltre, nell'aprile 2015 alla conferenza Infiltrate, è stata presentata una presentazione intitolata Insection : AWEsomely Exploiting Shared Memory Objects che dettagliava questo problema, anche a sviluppatori Microsoft presenti, i quali hanno concordato che questo era attualmente fuori dall'ambito dei confini di sicurezza architetturale di Windows. Questo perché esistono letteralmente dozzine — se non di più — di altri modi in cui un Amministratore può leggere/scrivere/eseguire memoria in Ring 0. Questo strumento consente semplicemente una facile commodificazione di uno di questi vettori, a scopo di debug e risoluzione dei problemi di sistema.
Impacchettare questo codice come libreria richiederebbe di rimuovere attentamente tutta l'interazione di parsing della riga di comando e l'output standard, a quel punto, senza riscritture importanti, il 'kit':
Gli aggressori interessati a utilizzare questo particolare approccio — rispetto a molti altri più cross-compatibili e senza la necessità di diritti SYSTEM — hanno probabilmente già adattato il proprio codice basandosi sul Proof-of-Concept dell'aprile 2015 — più di 3 anni fa.
A causa dell'utilizzo del Motore dei Simboli di Windows, è necessario avere installato il Windows Software Development Kit (SDK) o il Windows Driver Kit (WDK) con gli Strumenti di Debug per Windows. Lo strumento cercherà automaticamente il percorso di installazione e utilizzerà i file DbgHelp.dll e SymSrv.dll presenti in quella directory. Poiché questi file non sono ridistribuibili, non possono essere inclusi nella release dello strumento.
In alternativa, se si ottengono queste librerie autonomamente, è possibile modificare il codice sorgente per utilizzarle.
L'uso dei simboli richiede una connessione Internet, a meno che non siano stati precaricati localmente. Inoltre, è necessario impostare la variabile _NT_SYMBOL_PATH che punti a un server di simboli appropriato e a una posizione cache.
Si presuppone che un esperto IT o altro risolutore di problemi che apparentemente ha bisogno di leggere/scrivere/eseguire memoria del kernel (e ha conoscenza delle variabili del kernel appropriate da accedere) sia già più che intimamente familiare con i requisiti di configurazione sopra menzionati. Si prega di non aprire issue chiedendo cosa sia l'SDK o come impostare una variabile d'ambiente.
Qualche driver ha perso pool del kernel? Perché non chiamare ntoskrnl.exe!ExFreePool e passare l'indirizzo del kernel che sta perdendo? Riguardo a un riferimento a un oggetto? Chiamate ntoskrnl.exe!ObfDereferenceObject e fatevelo pulire.
Volete scaricare il log DbgPrint del kernel? Perché non scaricare il buffer circolare interno in ntoskrnl.exe!KdPrintCircularBuffer
Vi state chiedendo quanto sono grandi gli stack del kernel sulla vostra macchina? Provate a guardare ntoskrnl.exe!KeKernelStackSize
Volete scaricare la tabella delle system call per cercare hook? Stampate ntoskrnl.exe!KiServiceTable
Questi sono solo alcuni esempi: tutti gli indirizzi Ring 0 sono accettati, sia con la sintassi module!symbol che passando direttamente il puntatore al kernel se noto. Il Motore dei Simboli di Windows viene utilizzato per cercarli.
Lo strumento richiede alcune variabili e funzioni del kernel note per esistere solo nelle versioni moderne di Windows 10 ed è progettato per funzionare solo su sistemi a 64 bit. Queste limitazioni sono dovute al fatto che su sistemi più vecchi (o sistemi x86), questi requisiti di sicurezza più severi non esistono e, quindi, è possibile utilizzare approcci più tradizionali. Questo è uno strumento personale che metto a disposizione e non ho avuto bisogno di questi sistemi più vecchi, in cui avrei potuto utilizzare un semplice driver. Detto questo, questo repository accetta pull request, se qualcuno è interessato a eseguire il porting.
In secondo luogo, a causa dei casi d'uso e delle mie esigenze, si applicano le seguenti restrizioni:
Ovviamente, queste limitazioni potrebbero essere risolte scegliendo programmaticamente un approccio diverso, ma si adattano alle esigenze di uno strumento a riga di comando e ai miei casi d'uso. Ancora una volta, le pull request sono accettate se altri desiderano contribuire con le proprie aggiunte.
Nota che tutta l'esecuzione (inclusa l'esecuzione dei comandi --read e --write) avviene nel contesto di un Thread di Lavoro di Sistema a PASSIVE_LEVEL. Pertanto, gli indirizzi in modalità utente non devono essere passati come parametri/argomenti.
Le pull request sono benvenute. Per modifiche importanti, si prega di aprire prima un issue per discutere cosa si desidera modificare.
Copyright 2018 Alex Ionescu. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY ALEX IONESCU ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALEX IONESCU
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those of the authors and
should not be interpreted as representing official policies, either expressed or implied, of Alex Ionescu.