/*
* sbd - shadowinteger's backdoor
* Copyright (C) 2004 Michel Blomgren <michel.blomgren@tigerteam.se>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* See the COPYING file for more information.
*/
#ifdef WIN32
char *WSAstrerror(DWORD my_wsagetlasterror) {
switch (my_wsagetlasterror) {
case WSABASEERR:
return "WSABASEERR";
case WSAEINTR:
return "WSAEINTR";
case WSAEBADF:
return "WSAEBADF";
case WSAEACCES:
return "WSAEACCES";
case WSAEFAULT:
return "WSAEFAULT";
case WSAEINVAL:
return "WSAEINVAL";
case WSAEMFILE:
return "WSAEMFILE";
case WSAEWOULDBLOCK:
return "WSAEWOULDBLOCK";
case WSAEINPROGRESS:
return "WSAEINPROGRESS";
case WSAEALREADY:
return "WSAEALREADY";
case WSAENOTSOCK:
return "WSAENOTSOCK";
case WSAEDESTADDRREQ:
return "WSAEDESTADDRREQ";
case WSAEMSGSIZE:
return "WSAEMSGSIZE";
case WSAEPROTOTYPE:
return "WSAEPROTOTYPE";
case WSAENOPROTOOPT:
return "WSAENOPROTOOPT";
case WSAEPROTONOSUPPORT:
return "WSAEPROTONOSUPPORT";
case WSAESOCKTNOSUPPORT:
return "WSAESOCKTNOSUPPORT";
case WSAEOPNOTSUPP:
return "WSAEOPNOTSUPP";
case WSAEPFNOSUPPORT:
return "WSAEPFNOSUPPORT";
case WSAEAFNOSUPPORT:
return "WSAEAFNOSUPPORT";
case WSAEADDRINUSE:
return "WSAEADDRINUSE";
case WSAEADDRNOTAVAIL:
return "WSAEADDRNOTAVAIL";
case WSAENETDOWN:
return "WSAENETDOWN";
case WSAENETUNREACH:
return "WSAENETUNREACH";
case WSAENETRESET:
return "WSAENETRESET";
case WSAECONNABORTED:
return "WSAECONNABORTED";
case WSAECONNRESET:
return "WSAECONNRESET";
case WSAENOBUFS:
return "WSAENOBUFS";
case WSAEISCONN:
return "WSAEISCONN";
case WSAENOTCONN:
return "WSAENOTCONN";
case WSAESHUTDOWN:
return "WSAESHUTDOWN";
case WSAETOOMANYREFS:
return "WSAETOOMANYREFS";
case WSAETIMEDOUT:
return "WSAETIMEDOUT";
case WSAECONNREFUSED:
return "WSAECONNREFUSED";
case WSAELOOP:
return "WSAELOOP";
case WSAENAMETOOLONG:
return "WSAENAMETOOLONG";
case WSAEHOSTDOWN:
return "WSAEHOSTDOWN";
case WSAEHOSTUNREACH:
return "WSAEHOSTUNREACH";
case WSAENOTEMPTY:
return "WSAENOTEMPTY";
case WSAEPROCLIM:
return "WSAEPROCLIM";
case WSAEUSERS:
return "WSAEUSERS";
case WSAEDQUOT:
return "WSAEDQUOT";
case WSAESTALE:
return "WSAESTALE";
case WSAEREMOTE:
return "WSAEREMOTE";
case WSAEDISCON:
return "WSAEDISCON";
case WSASYSNOTREADY:
return "WSASYSNOTREADY";
case WSAVERNOTSUPPORTED:
return "WSAVERNOTSUPPORTED";
case WSANOTINITIALISED:
return "WSANOTINITIALISED";
case WSAHOST_NOT_FOUND:
return "WSAHOST_NOT_FOUND";
case WSATRY_AGAIN:
return "WSATRY_AGAIN";
case WSANO_RECOVERY:
return "WSANO_RECOVERY";
case WSANO_DATA:
return "WSANO_DATA";
default:
return "Unknown winsock error";
}
}
#endif
#if defined WIN32 && defined WINMAIN && defined STEALTH
/*nop*/
#else
/* get RCS id */
unsigned char *get_revision(unsigned char *string) {
/*
* input string is an RCS Id keyword
*/
char Id_string[] = "$Id: ";
char *idstart;
static unsigned char revision[16];
int i, x, column_counter;
if (!(idstart = strstr(string, Id_string))) {
return NULL;
}
idstart += strlen(Id_string);
column_counter = 1;
for (i = 0, x = 0; x < (sizeof(revision)-1); i++) {
if (idstart[i] == 0)
return NULL;
if (column_counter < 2) {
if (idstart[i] == 0x20)
column_counter++;
} else { /* column 2 is the rcs revision number */
if (((idstart[i] < '0') || (idstart[i] > '9')) && (idstart[i] != '.'))
break;
revision[x] = idstart[i];
x++;
}
}
revision[x] = 0;
return revision;
}
#endif
#if defined WIN32 && defined WINMAIN
/*
ParseCommandLine() was derived from some forum (forgot which) :\
author is unknown to me!
*/
void ParseCommandLine (LPSTR lpCmdLine) {
argc = 1;
if (!(argv[0] = strdup("smb.exe"))) {
#ifndef STEALTH
MessageBox(NULL, "strdup() failed!", "error!", MB_OK | MB_ICONERROR);
#endif
exit(1);
}
while (*lpCmdLine && (argc < MAX_NUM_ARGVS)) {
while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126))) {
lpCmdLine++;
}
if (*lpCmdLine) {
argv[argc] = lpCmdLine;
argc++;
while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126))) {
lpCmdLine++;
}
if (*lpCmdLine) {
*lpCmdLine = 0;
lpCmdLine++;
}
}
}
}
#ifndef STEALTH
/* return "on" or "off" if an int is 1 or 0 respectively */
char *on_or_off(int boolean) {
if (boolean)
return "on";
else
return "off";
}
void message_box_usage(void) {
char buf[2048];
snprintf(buf, sizeof(buf),
"sbd %s Copyright (C) 2004 Michel Blomgren <michel.blomgren@tigerteam.se>\n"
"\n"
"connect (tcp): sbdbg.exe [-options] host port\n"
"listen (tcp): sbdbg.exe -l -p port [-options]\n"
"-l : listen for incoming connection\n"
"-p : choose port to listen on, or source port to connect from\n"
"-a : choose address to listen on or connect out from\n"
"-e exe : program to execute after connect, e.g.: -e cmd.exe\n"
"-r n : infinitely reconnect, pause for n seconds between connects, use -r0 with -l\n"
"-c on|off : turn on/off AES-128 encryption. default: -c %s\n"
"-k secret : override hardcoded passphrase for the -c option\n"
"-q : be quiet, don't show MessageBoxes\n"
"-n : numeric-only IP addresses, don't do DNS resolution.\n"
"-V : show a MessageBox with version info\n"
"\n"
"win32 specific options:\n"
"-D on|off : turn on/off whether to detach from the console. default is: -D %s\n"
"-X on|off : turn on/off conversion of LF/CR to CR+LF (only for -e). default is: -X %s\n"
"-1 on|off : turn on/off whether to run only one instance of sbd or not. default is: -1 %s\n",
get_revision(rcsid),
on_or_off(use_encryption),
on_or_off(daemonize),
on_or_off(convert_to_crlf),
on_or_off(only_one_instance));
if (!quiet)
MessageBox(NULL, buf, "sbd usage", MB_OK);
return;
}
/* error MessageBox */
void errbox(char *msg) {
MessageBox(NULL, msg, "sbd", MB_OK | MB_ICONERROR);
return;
}
void displayAmbitiousErrbox(char *prefix, DWORD err) {
LPVOID lpMsgBuf;
char msg[256];
if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL )) {
/* handle error */
return;
}
snprintf(msg, sizeof(msg), "%s%u: %s",
prefix, (unsigned int)err, (char *)lpMsgBuf);
errbox(msg);
LocalFree(lpMsgBuf);
}
/* info MessageBox */
void infobox(char *msg) {
MessageBox(NULL, msg, "sbd", MB_OK | MB_ICONINFORMATION);
return;
}
/* winsock error MessageBox */
void wsaerrbox(char *msg, DWORD wsaerr) {
char buf[256];
snprintf(buf, sizeof(buf), "%s: %s", msg, WSAstrerror(wsaerr));
MessageBox(NULL, buf, "sbd", MB_OK | MB_ICONERROR);
return;
}
/* display version info MessageBox */
void verbox(void) {
char buf1[1024];
char buf2[16];
snprintf(buf1, sizeof(buf1), "sbd %s Copyright (C) 2004 Michel Blomgren <michel.blomgren@tigerteam.se>\n"
"%s\n"
"http://tigerteam.se\n"
"sbd is distributed under the GNU General Public License v2",
get_revision(rcsid), rcsid);
snprintf(buf2, sizeof(buf2), "sbd %s", get_revision(rcsid));
MessageBox(NULL, buf1, buf2, MB_OK | MB_ICONINFORMATION);
return;
}
/*
a non-blocking MessageBox.
this is implemented by creating a thread (quite lame approach, I know, but
it's what I got) :\
*/
typedef struct {
char *msg;
int thread_lock;
} mbstruct, *pmbstruct;
static VOID messagebox_thread(LPVOID Parameter) {
pmbstruct mbs = Parameter;
char buf[512];
strncpy(buf, mbs->msg, sizeof(buf));
mbs->thread_lock = 0;
MessageBox(NULL, buf, "sbd", MB_OK);
ExitThread(0);
}
void forkmsgbox(char *msg, int length) {
char *omsg;
pmbstruct m;
DWORD ThreadId;
HANDLE h;
if (!length)
return;
/* shorten length */
if (length > 500)
length = 500;
if (!(omsg = malloc(length+1)))
return;
memcpy(omsg, msg, length);
omsg[length] = 0;
if (!(m = (pmbstruct) malloc(sizeof(mbstruct)))) {
free(omsg);
return;
}
m->msg = omsg;
m->thread_lock = 1;
h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) messagebox_thread,
(LPVOID) m, 0, &ThreadId);
if (h) {
CloseHandle(h);
while (m->thread_lock == 1) {
Sleep(50);
continue;
}
Sleep(50);
}
free(m);
free(omsg);
return;
}
#endif
#else
/* for unix and win32 console app */
/*
* print_banner() prints version and copyright info
*/
void print_version(void) {
printf("sbd %s Copyright (C) 2004 Michel Blomgren <michel.blomgren@tigerteam.se>\n"
"%s\n"
"\n"
"This program is free software; you can redistribute it and/or modify it under\n"
"the terms of the GNU General Public License as published by the Free Software\n"
"Foundation; either version 2 of the License, or (at your option) any later\n"
"version.\n",
get_revision(rcsid), rcsid);
return;
}
/* return "on" or "off" if an int is 1 or 0 respectively */
char *on_or_off(int boolean) {
if (boolean)
return "on";
else
return "off";
}
/*
* usage() prints sbd syntax/usage info
*/
void usage(void) {
print_version();
printf(
"\n"
"connect (tcp): sbd [-options] host port\n"
"listen (tcp): sbd -l -p port [-options]\n"
"options:\n"
" -l listen for incoming connection\n"
" -p n choose port to listen on, or source port to connect out from\n"
" -a address choose an address to listen on or connect out from\n"
" -e prog program to execute after connect (e.g. -e cmd.exe or -e bash)\n"
" -r n infinitely respawn/reconnect, pause for n seconds between\n"
" connection attempts. -r0 can be used to re-listen after\n"
" disconnect (just like a regular daemon)\n"
" -c on|off encryption on/off. specify whether you want to use the built-in\n"
" AES-CBC-128 + HMAC-SHA1 encryption implementation (by\n"
" Christophe Devine - http://www.cr0.net:8040/) or not\n"
" default is: -c %s\n"
" -k secret override default phrase to use for encryption (secret must be\n"
" shared between client and server)\n"
" -q hush, quiet, don't print anything (overrides -v)\n"
" -v be verbose\n"
" -n toggle numeric-only IP addresses (don't do DNS resolution). if\n"
" you specify -n twice, original state will be active (i.e. -n\n"
" works like a on/off switch)\n"
" -m toggle monitoring (snooping) on/off (only used with the -e\n"
" option). snooping can also be turned on by specifying -vv (-v\n"
" two times)\n"
" -P prefix add prefix (+ a hardcoded separator) to all outbound data.\n"
" this option is mostly only useful for sbd in \"chat mode\" (to\n"
" prefix lines you send with your nickname)\n"
" -H on|off highlight incoming data with a hardcoded (color) escape\n"
" sequence (for e.g. chatting). default is: -H %s\n"
" -V print version banner and exit (include that output in your\n"
" bug report and send bug report to michel.blomgren@tigerteam.se)\n"
#ifdef WIN32
"win32 specific options:\n"
" -D on|off detach from console (FreeConsole()) (on=yes or off=no)\n"
" default is: -D %s\n"
" -X on|off when using the -e option, translate incoming bare LFs or CRs\n"
" to CR+LF (this must be on if you're executing command.com on\n"
" Win9x). default is: -X %s\n"
" -1 on|off whether to make sbd run only one instance of itself or not.\n"
" instance check is implemented using CreateSemaphore() (with an\n"
" initcount and maxcount of 1) and WaitForSingleObject(). if\n"
" WaitForSingleObject() returns WAIT_TIMEOUT we assume there's\n"
" already an instance running. default is: -1 %s\n"
"note: when receiving files under win32, always use something like this:\n"
"C:\\>sbd -lvp 1234 < NUL > outfile.ext\n",
on_or_off(use_encryption),
on_or_off(highlight_incoming),
on_or_off(daemonize),
on_or_off(convert_to_crlf),
on_or_off(only_one_instance));
#else
"unix-like OS specific options:\n"
" -s invoke a shell, nothing else. if sbd is setuid 0, it'll invoke\n"
" a root shell\n"
" -w n \"immobility timeout\" in seconds for idle read/write operations\n"
" and program execution (the -e option)\n"
" -D on|off fork and run in background (daemonize). default: -D %s\n",
on_or_off(use_encryption),
on_or_off(highlight_incoming),
on_or_off(daemonize));
#endif
return;
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1