#include <stdio.h>
unsigned char random[] = //randomness
unsigned char shellcode[] = //shellcode in hex
int main(void)
{
((void (*) ())shellcode) ();
}
¿Qué hace ((void (*) ()) shellcode) (); hacer?
Usa objdump y gdb y queda bastante claro lo que está pasando con ese ridículo código.
Un programa es una secuencia de binario. Una representación equivalente para el binario que ejecuta el procesador son valores hexadecimales. La representación hexadecimal es completamente equivalente, simplemente otra representación. Entonces, cuando se colocan muchos valores hexadecimales en la dirección en la que vive Shellcode, cuando una instrucción dice que apunte al inicio, la compilación lo hace y comienza a procesar el binario en esa dirección.
Mira en gdb para ver qué hace la función de fantasía.
$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
Aquí vemos mi código de shell de aspecto muy malicioso
(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
Vea, llamará al valor al que apunta eax cuando llegue a 0x56555581, lo que significa simplemente mover el puntero de instrucción a la dirección que contiene eax. No sabe que conectó las instrucciones en esa dirección directamente, y no le importa de dónde vinieron, se ejecutará alegremente a lo largo de la ejecución.
(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