Nutro da tempo un debole per tutto il mondo che ruota attorno alle tecniche di anti-reversing, specie se applicate agli shellcode.
In questo campo c’è poco e le motivazioni sono diverse, in primis il fatto che i check anti-debug occupano memoria nello shellcode e quando si fa shellcoding la dimensione in byte è un fattore cruciale. Shellcode di grandi dimensioni possono richiedere multi-stage, egghunting e altre tecniche, impattando la scelta del giusto payload da adottare in fase di exploit e complicando, talvolta, l’exploitation.
Un po’ di tempo fa mi sono imbattuto nello shellcode, scritto nel lontanissimo 2006 da izik e che lo stesso autore spiegava come segue:
(linux/x86) anti-debug trick (INT 3h trap) + execve("/bin/sh", ["/bin/sh", NULL], NULL) - 39 bytes The idea behind a shellcode w/ an anti-debugging trick embedded in it, is if for any reason the IDS would try to x86-emulate the shellcode it would *glitch* and fail. This also protectes the shellcode from running within a debugger environment such as gdb and strace. How this works? the shellcode registers for the SIGTRAP signal (aka. Breakpoint Interrupt) and use it to call the actual payload (e.g. _evil_code) while a greedy debugger or a confused x86-emu won't pass the signal handler to the shellcode, it would end up doing _exit() instead execuve() - izik
Cercando in giro non c’era una riscrittura della tecnica su Linux x64 così mi sono detto, perché non scriverne uno io prendendo spunto dal codice di izik?
Sfida bella e interessante la tecnica usata, che fa uso dell’exception handling per far gestire al debugger un finto breakpoint (via SIGTRAP) in modo che vada a fare lo skip dello shellcode, che rimane in mano all’handler (sorpassato dal debugger perché specializzato nel gestire le eccezioni INT3) e non viene eseguito. Nel caso dell’esecuzione fuori dal debugger invece la SIGTRAP viene catturata dall’handler impostato dallo shellcode con conseguente innesco della execve.
Bene, ottimi i presupposti, ed imbattersi in qualcosa che ancora non esiste è sempre intrigante.
Quindi ho proceduto nel seguente modo:
- Ho analizzato nel dettaglio lo shellcode x86 di izik;
- Ho cercato la documentazione relativa all’implementazione dei Signal per capire il funzionamento;
Linux x86: sighandler_t signal(int signum, sighandler_t handler); Linux x64: int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
- Ho capito, a quel punto, quale fosse il problema e cosa avrei dovuto fare per poter scrivere lo shellcode:
- Cambiare i registri utilizzati (Linux a 64 bit usa ovviamente un assembly differente confronto alla versione a 32 bit);
- Cambiare le syscall e i relativi parametri;
- Inizializzare correttamente le due strutture *act e *oldact per poter effettuare correttamente la chiamata, task non banale tenendo a mente di scrivere uno shellcode e quindi considerando tutta una serie di altri fattori come dimensione, caratteri NUL, ecc;
- Modificare in parte la struttura base del codice di izik per adattarlo alle nuove caratteristiche richieste.
La struttura struct sigaction, che ricopre un ruolo fondamentale nel nuovo shellcode è definita come segue:
struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); };
In casi come questo, il mio approccio preferito è quello di prendere un codice di esempio della funzionalità, compilarlo e fare Reverse Engineering sul codice assembly dell’eseguibile ottenuto, per capire come il compilatore ha trasformato il mio codice ad alto livello. Solo a quel punto, nel caso in cui io voglia farne uno shellcode, inizio a riscrivere il codice per cercare di limitare uso di memoria e per renderlo Position Independent e NUL free.
Dopo alcuni tentativi sono riuscito a scrivere un POC funzionante per Linux x64.
Potete trovare lo shellcode su Packet Storm Security oppure a pagina 2 di questo articolo.
Il codice è sufficientemente commentato per permettere facile comprensione delle operazioni effettuate.
Per oggi è tutto, ma se avete domande o considerazioni potete commentare o scrivermi all’indirizzo email che trovate nella sezione About. 🙂
-bdev-