utilizzando ndisasm
, i dati nell'array sh
possono essere disassemblati nel seguente codice macchina 64bit x86 valido:
00000000 EB0B jmp short 0xd
00000002 5F pop rdi
00000003 4831D2 xor rdx,rdx
00000006 52 push rdx
00000007 5E pop rsi
00000008 6A3B push byte +0x3b
0000000A 58 pop rax
0000000B 0F05 syscall
0000000D E8F0FFFFFF call qword 0x2
00000012 '/bin/sh'
Sembra semplice shellcode indipendente dalla posizione per eseguire un syscall del kernel per eseguire /bin/sh
.
La prima istruzione salta in avanti all'istruzione poco prima della stringa /bin/sh
, che a sua volta restituisce un call
alla seconda istruzione. L'indirizzo di ritorno viene quindi estratto dallo stack nel registro rdi
.
Questo è un trucco per ottenere l'indirizzo memeory della stringa /bin/sh
, poiché lo shellcode non sa dove si trova in memoria quando viene eseguito.
Il registro rdx
viene quindi impostato su 0 e inviato allo stack e reinserito nel registro rsi
. Il byte 0x3b viene quindi pusato nello stack e restituito al registro rax
.
Ora siamo configurati come segue:
- rdi = puntatore alla stringa
/bin/sh
- rdx = 0
- rsi = 0
- rax = 0x3b
A questo punto, passiamo il controllo al kernel con syscall
, dove l'argomento 0x3b
in rax
indica a execve () il percorso del file che è al puntatore rdi
Se lo traduciamo in C, in pratica funziona:
execve('/bin/sh', NULL, NULL);