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);