BorderGame
Tecniche ShellCoding - Versione stampabile

+- BorderGame (https://www.bordergame.it)
+-- Forum: Console e Tecnologia (/Forum-Console-e-Tecnologia)
+--- Forum: Hacking (/Forum-Hacking)
+--- Discussione: Tecniche ShellCoding (/Thread-Tecniche-ShellCoding)



Tecniche ShellCoding - Lawliet - 04-12-2011 01:40 PM

Introduzione

Questo documento presuppone una conoscenza delle tecniche di shellcoding di base, e l'assemblaggio x86, non starò a ripeterle tali in questo documento. Spero di insegnare alcune delle tecniche meno shellcoding noto che ho raccolto, il che vi permetterà di scrivere shellcodes più piccoli e meglio. Non pretendo di aver inventato una di queste tecniche, ad eccezione di quello che utilizza l'istruzione div.



La molteplicità delle mul

Questa tecnica è stata originariamente sviluppata da Sorbo di darkircop.net. L'istruzione mul può, in superficie, sembra banale, ed è ovvio scopo. Tuttavia, di fronte alla difficile sfida di contrazione tuo shellcode, si rivela essere molto utile. In primo luogo alcune informazioni di base sulla istruzione mul stesso.

mul esegue una moltiplicazione senza segno di due interi. Ci vuole un solo operando, l'altro è implicitamente indicato dal registro% eax. Quindi, una istruzione mul comune potrebbe essere simile a questa:

movl $ 0x0a,% eax
mul $ 0x0a

Ciò moltiplicare il valore memorizzato in% eax dal operando di mul, che in questo caso sarebbe 10 * 10. Il risultato viene poi implicitamente memorizzati in EDX: EAX. Il risultato viene memorizzato in un arco di due registri perché ha il potenziale per essere notevolmente più grande rispetto al valore precedente, che potrebbe superare la capacità di un registro unico (questo è anche il modo fluttuante punti sono conservati in alcuni casi, come un interessante nota a margine) .

Così, ora arriva il sempre importante questione. Come possiamo usare questi attributi a nostro vantaggio quando si scrive shellcode? Bene, pensiamo per un secondo, l'istruzione richiede solo un operando, quindi, dal momento che è un'istruzione molto comune, genererà solo due byte nel nostro shellcode finale. Si moltiplica tutto ciò che è passato dal valore memorizzato in% eax, e memorizza il valore in% edx sia e% eax, completamente sovrascrivendo il contenuto di entrambi i registri, a prescindere dal fatto che sia necessario farlo, in modo da memorizzare il risultato della moltiplicazione. Mettiamo sui nostri cappelli matematico per un secondo, e considerare questo, qual è l'unico risultato possibile di una moltiplicazione per 0? La risposta, come avrete intuito, è 0. Penso che sia giunto il momento per qualche esempio di codice, quindi eccola:

xorl% ecx, ecx%
% ecx mul

Che cosa è questo shellcode facendo? Beh, 0% è il registro ecx xor utilizzando l'istruzione, così ora sappiamo che ecx% è pari a 0. Poi fa un ecx mul%, che come abbiamo appena appreso, lo moltiplica la operando per il valore in% eax, e procede poi per memorizzare il risultato di questa moltiplicazione in EDX: EAX. Quindi, a prescindere dal contenuto precedente% eax è,% eax deve ora essere 0. Ma non è tutto,% edx è 0'd ormai troppo, perché, anche se non si verifica un overflow, sovrascrive ancora il% edx registri con il bit del segno (più a sinistra bit) di% eax. Con questa tecnica siamo in grado di azzerare tre registri in soli tre byte, mentre con qualsiasi altro metodo (che io sappia) ci sarebbero voluti almeno sei.


Il div istruzione

Div è molto simile a mul, nel senso che ci vuole solo un operando e divide implicitamente l'operando per il valore in% eax. Inoltre, come, mul memorizza il risultato della divisione in% eax. Anche in questo caso, chiederemo il lato matematico del nostro cervello per capire come possiamo trarre vantaggio da questa istruzione. Ma prima, cerchiamo di pensare a ciò che è normalmente memorizzato nel registro% eax. L'% eax registro contiene il valore di ritorno di funzioni e / o chiamate di sistema. La maggior parte delle chiamate di sistema che vengono utilizzati in shellcoding tornerà -1 (in caso di fallimento) o un valore positivo di qualche tipo, solo raramente tornano 0 (anche se si verifica). Quindi, se sappiamo che dopo una chiamata di sistema viene eseguita,% eax avrà un valore diverso da zero, e che l'istruzione divl% eax dividerà% eax da sé, e quindi memorizzare il risultato in% eax, possiamo dire che l'esecuzione l'istruzione divl% eax dopo una chiamata di sistema metterà il valore 1 in% eax. Allora ... come è applicabile a questo shellcoding? Bene, la loro è un'altra cosa importante che eax% viene utilizzato per, ed è quello di passare la syscall specifico che si desidera chiamare a int $ 0x80. Si dà il caso che la chiamata di sistema che corrisponde al valore 1 è exit (). Ora per esempio:


xorl% ebx,% ebx
% ebx mul
spingere% edx
pushl $ 0x3268732f
pushl $ 0x6e69622f
mov% esp,% ebx
spingere% edx
push ebx%
mov% esp,% ecx
MOVB $ 0xb,% al # execve () syscall, non restituisce affatto a meno che non fallisce, nel qual caso restituisce -1
int $ 0x80

divl% eax # -1 / -1 = 1
int $ 0x80

Ora, abbiamo un 3 funzione di uscita di byte, dove come prima era di 5 byte. Tuttavia, vi è una cattura, cosa succede se una chiamata di sistema torna 0? Bene in una situazione strana in cui questo potrebbe accadere, si potrebbe fare molte cose diverse, come% eax inc, dec% eax non, nulla% eax che renderanno% eax diverso da zero. Alcuni dicono che l'uscita non sono importanti in shellcode, poiché il codice viene eseguito indipendentemente dal fatto che non esce pulito. Hanno ragione anche se si ha realmente bisogno di salvare 3 byte per soddisfare le vostre shellcode in qualche parte, la exit () non vale la pena. Tuttavia, quando il codice viene completato, tenterà di eseguire tutto ciò che era dopo l'ultima istruzione, che molto probabilmente produrre un ILL SIG (istruzione illegale) che è un errore piuttosto strano, e verranno registrati dal sistema. Quindi, un exit () semplicemente aggiunge un ulteriore livello di stealth per il tuo sfruttare, in modo che anche se non riesce o non può cancellare tutti i registri, almeno questa parte della vostra presenza sarà chiaro.



Sbloccare il potere della Leal

L'istruzione Leal è un'istruzione spesso trascurato in shellcode, anche se è molto utile. Considerate questo breve pezzo di shellcode.

xorl% ecx, ecx%
Leal 0x10 (% ecx),% eax

Questo caricherà il valore 17 in eax, e chiaro tutti i bit di estranei eax. Questo si verifica perché l'istruzione Leal carica una variabile del tipo lungo nella sua vita operando desitination. Nel suo normale utilizzo, questo carico l'indirizzo di una variabile in un registro, creando così una sorta di puntatore. Tuttavia, poiché ecx è 0'd e 0 17 = 17, si carica il valore 17 in eax invece di qualsiasi tipo di effettivo indirizzo. In una shellcode normale avremmo fatto qualcosa del genere, per ottenere la stessa cosa:

xorl% eax,% eax
MOVB $ 0x10,% eax

Posso sentirti dire, ma che lo shellcode è un byte più corta della Leal, e hai proprio ragione. Tuttavia, in un vero e proprio shellcode si può già avere a 0 su un registro ecx come (o qualsiasi altro registro), quindi l'istruzione xorl nello shellcode Leal non viene conteggiato. Ecco un esempio:

xorl% eax,% eax
xorl% ebx,% ebx
MOVB $ 0x17,% al
int $ 0x80

xorl% ebx,% ebx
Leal 0x17 (% ebx),% al
int $ 0x80

Entrambi questi setuid chiamata shellcodes (0), ma lo si fa in 7 byte mentre l'altro lo fa in 8. Ancora una volta, ti sento dire, ma questo è solo un byte non fa che molta differenza, e hai ragione, qui non fa molta differenza (tranne in shellcode dimensioni pissing concorsi = p) , ma se applicato a shellcodes molto più grandi, che hanno molte chiamate di funzione e la necessità di fare cose come questa di frequente, si può risparmiare un bel po 'di spazio.