#include <stdio.h>
unsigned char random[] = //randomness
unsigned char shellcode[] = //shellcode in hex
int main(void)
{
((void (*) ())shellcode) ();
}
Che cosa ((void (*) ()) shellcode) (); fare?
Usa objdump e gdb e diventa piuttosto chiaro cosa sta succedendo con quel ridicolo pezzo di codice.
Un programma è una sequenza di binari. Una rappresentazione equivalente per il file binario che il processore esegue sono valori esadecimali. La rappresentazione esadecimale è del tutto equivalente, semplicemente un'altra rappresentazione. Quindi, quando un gruppo di valori esadecimali viene inserito nell'indirizzo a cui appartiene lo shellcode, quando un'istruzione dice di puntare all'inizio di esso, il comp fa e inizia l'elaborazione del binario a quell'indirizzo.
Guarda in gdb per vedere cosa fa la funzione di fantasia.
$gdb -q holac
....
0x56555560 <+0>: lea 0x4(%esp),%ecx
0x56555564 <+4>: and $0xfffffff0,%esp
0x56555567 <+7>: pushl -0x4(%ecx)
0x5655556a <+10>: push %ebp
0x5655556b <+11>: mov %esp,%ebp
0x5655556d <+13>: push %ecx
0x5655556e <+14>: sub $0x4,%esp
0x56555571 <+17>: call 0x56555591 <__x86.get_pc_thunk.ax>
0x56555576 <+22>: add $0x1a62,%eax
0x5655557b <+27>: lea 0x30(%eax),%eax
=> 0x56555581 <+33>: call *%eax
0x56555583 <+35>: mov $0x0,%eax
0x56555588 <+40>: add $0x4,%esp
0x5655558b <+43>: pop %ecx
0x5655558c <+44>: pop %ebp
0x5655558d <+45>: lea -0x4(%ecx),%esp
0x56555590 <+48>: ret
(gdb) print/x $eax
$1 = 0x56557008
Qui vediamo il mio shellcode dall'aspetto molto malizioso
(gdb) x/20x $eax
0x56557008 <shellcode>: 0xddccbbaa 0xbbeeeeff 0xbbbbbbaa 0x00000000
0x56557018: 0x00000000 0x00000000 0x00000000 0x00000000
0x56557028: 0x00000000 0x00000000 0x00000000 0x00000000
0x56557038: 0x00000000 0x00000000 0x00000000 0x00000000
0x56557048: 0x00000000 0x00000000 0x00000000 0x00000000
Vedi, chiamerà il valore a cui eax punta quando arriva a 0x56555581, che significa semplicemente spostare il puntatore dell'istruzione verso l'indirizzo eax. Non sa che hai collegato le istruzioni direttamente a quell'indirizzo, e non importa da dove vengano le istruzioni, andrà allegramente lungo l'esecuzione.
(gdb) print/x $eip //breaked at the call, eip still points to call
$2 = 0x56555581
(gdb) stepi
0x56557008 in shellcode ()
(gdb) print/x $eip //now eip (instruction pointer) points to start of shellcode
$3 = 0x56557008