From 9d0eb168bff92cbc00887eb9ed05691f9bc117c0 Mon Sep 17 00:00:00 2001 From: Diego Casorran Date: Thu, 21 Apr 2011 02:56:07 +0200 Subject: [PATCH] Initial Commit --- doexec.c | 462 +++++++++ doexec.o | Bin 0 -> 288 bytes generic.h | 237 +++++ getopt.c | 756 +++++++++++++++ getopt.h | 133 +++ getopt.o | Bin 0 -> 6528 bytes hobbit.txt | 946 ++++++++++++++++++ license.txt | 340 +++++++ makefile | 21 + makewin.cmd | 43 + nc.exe | Bin 0 -> 40448 bytes netcat.c | 2092 ++++++++++++++++++++++++++++++++++++++++ netcat.o | Bin 0 -> 42323 bytes readme.rodneybeede.txt | 17 + readme.txt | 155 +++ 15 files changed, 5202 insertions(+) create mode 100755 doexec.c create mode 100755 doexec.o create mode 100755 generic.h create mode 100755 getopt.c create mode 100755 getopt.h create mode 100755 getopt.o create mode 100755 hobbit.txt create mode 100755 license.txt create mode 100755 makefile create mode 100755 makewin.cmd create mode 100755 nc.exe create mode 100755 netcat.c create mode 100755 netcat.o create mode 100755 readme.rodneybeede.txt create mode 100755 readme.txt diff --git a/doexec.c b/doexec.c new file mode 100755 index 0000000..e0c5cf0 --- /dev/null +++ b/doexec.c @@ -0,0 +1,462 @@ +// for license see license.txt + +// Modified 12/27/2004 by Chris Wysopal +// fixed vulnerability found by hat-squad + +// portions Copyright (C) 1994 Nathaniel W. Mishkin +// code taken from rlogind.exe + +#include +#include +#include + +#ifdef GAPING_SECURITY_HOLE + + +#define BUFFER_SIZE 200 + +extern char * pr00gie; +void holler(char * str, char * p1, char * p2, char * p3, char * p4, char * p5, char * p6); +char smbuff[20]; +// +// Structure used to describe each session +// +typedef struct { + + // + // These fields are filled in at session creation time + // + HANDLE ReadPipeHandle; // Handle to shell stdout pipe + HANDLE WritePipeHandle; // Handle to shell stdin pipe + HANDLE ProcessHandle; // Handle to shell process + + // + // + // These fields are filled in at session connect time and are only + // valid when the session is connected + // + SOCKET ClientSocket; + HANDLE ReadShellThreadHandle; // Handle to session shell-read thread + HANDLE WriteShellThreadHandle; // Handle to session shell-read thread + +} SESSION_DATA, *PSESSION_DATA; + + +// +// Private prototypes +// + +static HANDLE +StartShell( + HANDLE StdinPipeHandle, + HANDLE StdoutPipeHandle + ); + +static VOID +SessionReadShellThreadFn( + LPVOID Parameter + ); + +static VOID +SessionWriteShellThreadFn( + LPVOID Parameter + ); + + + +// ********************************************************************** +// +// CreateSession +// +// Creates a new session. Involves creating the shell process and establishing +// pipes for communication with it. +// +// Returns a handle to the session or NULL on failure. +// + +static PSESSION_DATA +CreateSession( + VOID + ) +{ + PSESSION_DATA Session = NULL; + BOOL Result; + SECURITY_ATTRIBUTES SecurityAttributes; + HANDLE ShellStdinPipe = NULL; + HANDLE ShellStdoutPipe = NULL; + + // + // Allocate space for the session data + // + Session = (PSESSION_DATA) malloc(sizeof(SESSION_DATA)); + if (Session == NULL) { + return(NULL); + } + + // + // Reset fields in preparation for failure + // + Session->ReadPipeHandle = NULL; + Session->WritePipeHandle = NULL; + + + // + // Create the I/O pipes for the shell + // + SecurityAttributes.nLength = sizeof(SecurityAttributes); + SecurityAttributes.lpSecurityDescriptor = NULL; // Use default ACL + SecurityAttributes.bInheritHandle = TRUE; // Shell will inherit handles + + Result = CreatePipe(&Session->ReadPipeHandle, &ShellStdoutPipe, + &SecurityAttributes, 0); + if (!Result) { + holler("Failed to create shell stdout pipe, error = %s", + itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); + goto Failure; + } + Result = CreatePipe(&ShellStdinPipe, &Session->WritePipeHandle, + &SecurityAttributes, 0); + + if (!Result) { + holler("Failed to create shell stdin pipe, error = %s", + itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); + goto Failure; + } + // + // Start the shell + // + Session->ProcessHandle = StartShell(ShellStdinPipe, ShellStdoutPipe); + + // + // We're finished with our copy of the shell pipe handles + // Closing the runtime handles will close the pipe handles for us. + // + CloseHandle(ShellStdinPipe); + CloseHandle(ShellStdoutPipe); + + // + // Check result of shell start + // + if (Session->ProcessHandle == NULL) { + holler("Failed to execute shell", NULL, + NULL, NULL, NULL, NULL, NULL); + + goto Failure; + } + + // + // The session is not connected, initialize variables to indicate that + // + Session->ClientSocket = INVALID_SOCKET; + + // + // Success, return the session pointer as a handle + // + return(Session); + +Failure: + + // + // We get here for any failure case. + // Free up any resources and exit + // + + if (ShellStdinPipe != NULL) + CloseHandle(ShellStdinPipe); + if (ShellStdoutPipe != NULL) + CloseHandle(ShellStdoutPipe); + if (Session->ReadPipeHandle != NULL) + CloseHandle(Session->ReadPipeHandle); + if (Session->WritePipeHandle != NULL) + CloseHandle(Session->WritePipeHandle); + + free(Session); + + return(NULL); +} + + + +BOOL +doexec( + SOCKET ClientSocket + ) +{ + PSESSION_DATA Session = CreateSession(); + SECURITY_ATTRIBUTES SecurityAttributes; + DWORD ThreadId; + HANDLE HandleArray[3]; + int i; + + SecurityAttributes.nLength = sizeof(SecurityAttributes); + SecurityAttributes.lpSecurityDescriptor = NULL; // Use default ACL + SecurityAttributes.bInheritHandle = FALSE; // No inheritance + + // + // Store the client socket handle in the session structure so the thread + // can get at it. This also signals that the session is connected. + // + Session->ClientSocket = ClientSocket; + + // + // Create the session threads + // + Session->ReadShellThreadHandle = + CreateThread(&SecurityAttributes, 0, + (LPTHREAD_START_ROUTINE) SessionReadShellThreadFn, + (LPVOID) Session, 0, &ThreadId); + + if (Session->ReadShellThreadHandle == NULL) { + holler("Failed to create ReadShell session thread, error = %s", + itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); + + // + // Reset the client pipe handle to indicate this session is disconnected + // + Session->ClientSocket = INVALID_SOCKET; + return(FALSE); + } + + Session->WriteShellThreadHandle = + CreateThread(&SecurityAttributes, 0, + (LPTHREAD_START_ROUTINE) SessionWriteShellThreadFn, + (LPVOID) Session, 0, &ThreadId); + + if (Session->WriteShellThreadHandle == NULL) { + holler("Failed to create ReadShell session thread, error = %s", + itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); + + // + // Reset the client pipe handle to indicate this session is disconnected + // + Session->ClientSocket = INVALID_SOCKET; + + TerminateThread(Session->WriteShellThreadHandle, 0); + return(FALSE); + } + + // + // Wait for either thread or the shell process to finish + // + + HandleArray[0] = Session->ReadShellThreadHandle; + HandleArray[1] = Session->WriteShellThreadHandle; + HandleArray[2] = Session->ProcessHandle; + + + i = WaitForMultipleObjects(3, HandleArray, FALSE, 0xffffffff); + + + switch (i) { + case WAIT_OBJECT_0 + 0: + TerminateThread(Session->WriteShellThreadHandle, 0); + TerminateProcess(Session->ProcessHandle, 1); + break; + + case WAIT_OBJECT_0 + 1: + TerminateThread(Session->ReadShellThreadHandle, 0); + TerminateProcess(Session->ProcessHandle, 1); + break; + case WAIT_OBJECT_0 + 2: + TerminateThread(Session->WriteShellThreadHandle, 0); + TerminateThread(Session->ReadShellThreadHandle, 0); + break; + + default: + holler("WaitForMultipleObjects error: %s", + itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); + + break; + } + + + // Close my handles to the threads, the shell process, and the shell pipes + shutdown(Session->ClientSocket, SD_BOTH); + closesocket(Session->ClientSocket); + + DisconnectNamedPipe(Session->ReadPipeHandle); + CloseHandle(Session->ReadPipeHandle); + + DisconnectNamedPipe(Session->WritePipeHandle); + CloseHandle(Session->WritePipeHandle); + + + CloseHandle(Session->ReadShellThreadHandle); + CloseHandle(Session->WriteShellThreadHandle); + + CloseHandle(Session->ProcessHandle); + + free(Session); + + return(TRUE); +} + + +// ********************************************************************** +// +// StartShell +// +// Execs the shell with the specified handle as stdin, stdout/err +// +// Returns process handle or NULL on failure +// + +static HANDLE +StartShell( + HANDLE ShellStdinPipeHandle, + HANDLE ShellStdoutPipeHandle + ) +{ + PROCESS_INFORMATION ProcessInformation; + STARTUPINFO si; + HANDLE ProcessHandle = NULL; + + // + // Initialize process startup info + // + si.cb = sizeof(STARTUPINFO); + si.lpReserved = NULL; + si.lpTitle = NULL; + si.lpDesktop = NULL; + si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L; + si.wShowWindow = SW_HIDE; + si.lpReserved2 = NULL; + si.cbReserved2 = 0; + + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + + si.hStdInput = ShellStdinPipeHandle; + si.hStdOutput = ShellStdoutPipeHandle; + + DuplicateHandle(GetCurrentProcess(), ShellStdoutPipeHandle, + GetCurrentProcess(), &si.hStdError, + DUPLICATE_SAME_ACCESS, TRUE, 0); + + if (CreateProcess(NULL, pr00gie, NULL, NULL, TRUE, 0, NULL, NULL, + &si, &ProcessInformation)) + { + ProcessHandle = ProcessInformation.hProcess; + CloseHandle(ProcessInformation.hThread); + } + else + holler("Failed to execute shell, error = %s", + itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); + + + return(ProcessHandle); +} + + +// ********************************************************************** +// SessionReadShellThreadFn +// +// The read thread procedure. Reads from the pipe connected to the shell +// process, writes to the socket. +// + +static VOID +SessionReadShellThreadFn( + LPVOID Parameter + ) +{ + PSESSION_DATA Session = Parameter; + BYTE Buffer[BUFFER_SIZE]; + BYTE Buffer2[BUFFER_SIZE*2+30]; + DWORD BytesRead; + + // this bogus peek is here because win32 won't let me close the pipe if it is + // in waiting for input on a read. + while (PeekNamedPipe(Session->ReadPipeHandle, Buffer, sizeof(Buffer), + &BytesRead, NULL, NULL)) + { + DWORD BufferCnt, BytesToWrite; + BYTE PrevChar = 0; + + if (BytesRead > 0) + { + ReadFile(Session->ReadPipeHandle, Buffer, sizeof(Buffer), + &BytesRead, NULL); + } + else + { + Sleep(50); + continue; + } + + + + // + // Process the data we got from the shell: replace any naked LF's + // with CR-LF pairs. + // + for (BufferCnt = 0, BytesToWrite = 0; BufferCnt < BytesRead; BufferCnt++) { + if (Buffer[BufferCnt] == '\n' && PrevChar != '\r') + Buffer2[BytesToWrite++] = '\r'; + PrevChar = Buffer2[BytesToWrite++] = Buffer[BufferCnt]; + } + + if (send(Session->ClientSocket, Buffer2, BytesToWrite, 0) <= 0) + break; + } + + if (GetLastError() != ERROR_BROKEN_PIPE) + holler("SessionReadShellThreadFn exitted, error = %s", + itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); + + ExitThread(0); +} + + +// ********************************************************************** +// SessionWriteShellThreadFn +// +// The write thread procedure. Reads from socket, writes to pipe connected +// to shell process. + + +static VOID +SessionWriteShellThreadFn( + LPVOID Parameter + ) +{ + PSESSION_DATA Session = Parameter; + BYTE RecvBuffer[1]; + BYTE Buffer[BUFFER_SIZE]; + DWORD BytesWritten; + DWORD BufferCnt; + + BufferCnt = 0; + + // + // Loop, reading one byte at a time from the socket. + // + while (recv(Session->ClientSocket, RecvBuffer, sizeof(RecvBuffer), 0) != 0) { + + Buffer[BufferCnt++] = RecvBuffer[0]; + if (RecvBuffer[0] == '\r') + Buffer[BufferCnt++] = '\n'; + + + // Trap exit as it causes problems + if (strnicmp(Buffer, "exit\r\n", 6) == 0) + ExitThread(0); + + + // + // If we got a CR, it's time to send what we've buffered up down to the + // shell process. + // SECURITY FIX: CW 12/27/04 Add BufferCnt size check. If we hit end of buffer, flush it + if (RecvBuffer[0] == '\n' || RecvBuffer[0] == '\r' || BufferCnt > BUFFER_SIZE-1) { + if (! WriteFile(Session->WritePipeHandle, Buffer, BufferCnt, + &BytesWritten, NULL)) + { + break; + } + BufferCnt = 0; + } + } + + ExitThread(0); +} + +#endif \ No newline at end of file diff --git a/doexec.o b/doexec.o new file mode 100755 index 0000000000000000000000000000000000000000..c7f425c23a36d0d14f78a42f1240654f8ca0f1a8 GIT binary patch literal 288 zcmeZaWM%+?9w6obvsfARN>VFIz--)v0)s(v. + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if !defined (__STDC__) || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include + +#ifdef WIN32 +#include +#endif + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include +#endif /* GNU C library. */ + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* XXX 1003.2 says this must be 1 before any call. */ +int optind = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return EOF with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv (); + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +#if !defined (__STDC__) || !__STDC__ +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +#endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +static const char * +_getopt_initialize (optstring) + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (optind == 0) + optstring = _getopt_initialize (optstring); + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc + && (argv[optind][0] != '-' || argv[optind][1] == '\0')) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int)(nameend - nextchar) == (unsigned int)strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); + else + fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c); + } + optopt = c; + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: option requires an argument -- %c\n", + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == EOF) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/getopt.h b/getopt.h new file mode 100755 index 0000000..50ddb7f --- /dev/null +++ b/getopt.h @@ -0,0 +1,133 @@ +/* Declarations for getopt. + Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc. + +This file is part of the GNU C Library. Its master source is NOT part of +the C library, however. The master source lives in /gd/gnu/lib. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +#if defined (__STDC__) && __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if defined (__STDC__) && __STDC__ +#ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ +extern int getopt (); +#endif /* __GNU_LIBRARY__ */ +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/getopt.o b/getopt.o new file mode 100755 index 0000000000000000000000000000000000000000..c8ae73e5add116900378f8f3068e2c431fde61c9 GIT binary patch literal 6528 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". The executable "nc" should appear. +If there is no relevant SYSTYPE section, try "generic". If you create new +sections for generic.h and Makefile to support another platform, please follow +the given format and mail back the diffs. + +There are a couple of other settable #defines in netcat.c, which you can +include as DFLAGS="-DTHIS -DTHAT" to your "make" invocation without having to +edit the Makefile. See the following discussions for what they are and do. + +If you want to link against the resolver library on SunOS [recommended] and +you have BIND 4.9.x, you may need to change XLIBS=-lresolv in the Makefile to +XLIBS="-lresolv -l44bsd". + +Linux sys/time.h does not really support presetting of FD_SETSIZE; a harmless +warning is issued. + +Some systems may warn about pointer types for signal(). No problem, though. + +Exploration of features +======================= + +Where to begin? Netcat is at the same time so simple and versatile, it's like +trying to describe everything you can do with your Swiss Army knife. This will +go over the basics; you should also read the usage examples and notes later on +which may give you even more ideas about what this sort of tool is good for. + +If no command arguments are given at all, netcat asks for them, reads a line +from standard input, and breaks it up into arguments internally. This can be +useful when driving netcat from certain types of scripts, with the side effect +of hiding your command line arguments from "ps" displays. + +The host argument can be a name or IP address. If -n is specified, netcat +will only accept numeric IP addresses and do no DNS lookups for anything. If +-n is not given and -v is turned on, netcat will do a full forward and reverse +name and address lookup for the host, and warn you about the all-too-common +problem of mismatched names in the DNS. This often takes a little longer for +connection setup, but is useful to know about. There are circumstances under +which this can *save* time, such as when you want to know the name for some IP +address and also connect there. Netcat will just tell you all about it, saving +the manual steps of looking up the hostname yourself. Normally mismatch- +checking is case-insensitive per the DNS spec, but you can define ANAL at +compile time to make it case-sensitive -- sometimes useful for uncovering minor +errors in your own DNS files while poking around your networks. + +A port argument is required for outbound connections, and can be numeric or a +name as listed in /etc/services. If -n is specified, only numeric arguments +are valid. Special syntax and/or more than one port argument cause different +behavior -- see details below about port-scanning. + +The -v switch controls the verbosity level of messages sent to standard error. +You will probably want to run netcat most of the time with -v turned on, so you +can see info about the connections it is trying to make. You will probably +also want to give a smallish -w argument, which limits the time spent trying to +make a connection. I usually alias "nc" to "nc -v -w 3", which makes it +function just about the same for things I would otherwise use telnet to do. +The timeout is easily changed by a subsequent -w argument which overrides the +earlier one. Specifying -v more than once makes diagnostic output MORE +verbose. If -v is not specified at all, netcat silently does its work unless +some error happens, whereupon it describes the error and exits with a nonzero +status. Refused network connections are generally NOT considered to be errors, +unless you only asked for a single TCP port and it was refused. + +Note that -w also sets the network inactivity timeout. This does not have any +effect until standard input closes, but then if nothing further arrives from +the network in the next seconds, netcat tries to read the net once +more for good measure, and then closes and exits. There are a lot of network +services now that accept a small amount of input and return a large amount of +output, such as Gopher and Web servers, which is the main reason netcat was +written to "block" on the network staying open rather than standard input. +Handling the timeout this way gives uniform behavior with network servers that +*don't* close by themselves until told to. + +UDP connections are opened instead of TCP when -u is specified. These aren't +really "connections" per se since UDP is a connectionless protocol, although +netcat does internally use the "connected UDP socket" mechanism that most +kernels support. Although netcat claims that an outgoing UDP connection is +"open" immediately, no data is sent until something is read from standard +input. Only thereafter is it possible to determine whether there really is a +UDP server on the other end, and often you just can't tell. Most UDP protocols +use timeouts and retries to do their thing and in many cases won't bother +answering at all, so you should specify a timeout and hope for the best. You +will get more out of UDP connections if standard input is fed from a source +of data that looks like various kinds of server requests. + +To obtain a hex dump file of the data sent either way, use "-o logfile". The +dump lines begin with "<" or ">" to respectively indicate "from the net" or +"to the net", and contain the total count per direction, and hex and ascii +representations of the traffic. Capturing a hex dump naturally slows netcat +down a bit, so don't use it where speed is critical. + +Netcat can bind to any local port, subject to privilege restrictions and ports +that are already in use. It is also possible to use a specific local network +source address if it is that of a network interface on your machine. [Note: +this does not work correctly on all platforms.] Use "-p portarg" to grab a +specific local port, and "-s ip-addr" or "-s name" to have that be your source +IP address. This is often referred to as "anchoring the socket". Root users +can grab any unused source port including the "reserved" ones less than 1024. +Absence of -p will bind to whatever unused port the system gives you, just like +any other normal client connection, unless you use -r [see below]. + +Listen mode will cause netcat to wait for an inbound connection, and then the +same data transfer happens. Thus, you can do "nc -l -p 1234 < filename" and +when someone else connects to your port 1234, the file is sent to them whether +they wanted it or not. Listen mode is generally used along with a local port +argument -- this is required for UDP mode, while TCP mode can have the system +assign one and tell you what it is if -v is turned on. If you specify a target +host and optional port in listen mode, netcat will accept an inbound connection +only from that host and if you specify one, only from that foreign source port. +In verbose mode you'll be informed about the inbound connection, including what +address and port it came from, and since listening on "any" applies to several +possibilities, which address it came *to* on your end. If the system supports +IP socket options, netcat will attempt to retrieve any such options from an +inbound connection and print them out in hex. + +If netcat is compiled with -DGAPING_SECURITY_HOLE, the -e argument specifies +a program to exec after making or receiving a successful connection. In the +listening mode, this works similarly to "inetd" but only for a single instance. +Use with GREAT CARE. This piece of the code is normally not enabled; if you +know what you're doing, have fun. This hack also works in UDP mode. Note that +you can only supply -e with the name of the program, but no arguments. If you +want to launch something with an argument list, write a two-line wrapper script +or just use inetd like always. + +If netcat is compiled with -DTELNET, the -t argument enables it to respond +to telnet option negotiation [always in the negative, i.e. DONT or WONT]. +This allows it to connect to a telnetd and get past the initial negotiation +far enough to get a login prompt from the server. Since this feature has +the potential to modify the data stream, it is not enabled by default. You +have to understand why you might need this and turn on the #define yourself. + +Data from the network connection is always delivered to standard output as +efficiently as possible, using large 8K reads and writes. Standard input is +normally sent to the net the same way, but the -i switch specifies an "interval +time" which slows this down considerably. Standard input is still read in +large batches, but netcat then tries to find where line breaks exist and sends +one line every interval time. Note that if standard input is a terminal, data +is already read line by line, so unless you make the -i interval rather long, +what you type will go out at a fairly normal rate. -i is really designed +for use when you want to "measure out" what is read from files or pipes. + +Port-scanning is a popular method for exploring what's out there. Netcat +accepts its commands with options first, then the target host, and everything +thereafter is interpreted as port names or numbers, or ranges of ports in M-N +syntax. CAVEAT: some port names in /etc/services contain hyphens -- netcat +currently will not correctly parse those, so specify ranges using numbers if +you can. If more than one port is thus specified, netcat connects to *all* of +them, sending the same batch of data from standard input [up to 8K worth] to +each one that is successfully connected to. Specifying multiple ports also +suppresses diagnostic messages about refused connections, unless -v is +specified twice for "more verbosity". This way you normally get notified only +about genuinely open connections. Example: "nc -v -w 2 -z target 20-30" will +try connecting to every port between 20 and 30 [inclusive] at the target, and +will likely inform you about an FTP server, telnet server, and mailer along the +way. The -z switch prevents sending any data to a TCP connection and very +limited probe data to a UDP connection, and is thus useful as a fast scanning +mode just to see what ports the target is listening on. To limit scanning +speed if desired, -i will insert a delay between each port probe. There are +some pitfalls with regard to UDP scanning, described later, but in general it +works well. + +For each range of ports specified, scanning is normally done downward within +that range. If the -r switch is used, scanning hops randomly around within +that range and reports open ports as it finds them. [If you want them listed +in order regardless, pipe standard error through "sort"...] In addition, if +random mode is in effect, the local source ports are also randomized. This +prevents netcat from exhibiting any kind of regular pattern in its scanning. +You can exert fairly fine control over your scan by judicious use of -r and +selected port ranges to cover. If you use -r for a single connection, the +source port will have a random value above 8192, rather than the next one the +kernel would have assigned you. Note that selecting a specific local port +with -p overrides any local-port randomization. + +Many people are interested in testing network connectivity using IP source +routing, even if it's only to make sure their own firewalls are blocking +source-routed packets. On systems that support it, the -g switch can be used +multiple times [up to 8] to construct a loose-source-routed path for your +connection, and the -G argument positions the "hop pointer" within the list. +If your network allows source-routed traffic in and out, you can test +connectivity to your own services via remote points in the internet. Note that +although newer BSD-flavor telnets also have source-routing capability, it isn't +clearly documented and the command syntax is somewhat clumsy. Netcat's +handling of "-g" is modeled after "traceroute". + +Netcat tries its best to behave just like "cat". It currently does nothing to +terminal input modes, and does no end-of-line conversion. Standard input from +a terminal is read line by line with normal editing characters in effect. You +can freely suspend out of an interactive connection and resume. ^C or whatever +your interrupt character is will make netcat close the network connection and +exit. A switch to place the terminal in raw mode has been considered, but so +far has not been necessary. You can send raw binary data by reading it out of +a file or piping from another program, so more meaningful effort would be spent +writing an appropriate front-end driver. + +Netcat is not an "arbitrary packet generator", but the ability to talk to raw +sockets and/or nit/bpf/dlpi may appear at some point. Such things are clearly +useful; I refer you to Darren Reed's excellent ip_filter package, which now +includes a tool to construct and send raw packets with any contents you want. + +Example uses -- the light side +============================== + +Again, this is a very partial list of possibilities, but it may get you to +think up more applications for netcat. Driving netcat with simple shell or +expect scripts is an easy and flexible way to do fairly complex tasks, +especially if you're not into coding network tools in C. My coding isn't +particularly strong either [although undoubtedly better after writing this +thing!], so I tend to construct bare-metal tools like this that I can trivially +plug into other applications. Netcat doubles as a teaching tool -- one can +learn a great deal about more complex network protocols by trying to simulate +them through raw connections! + +An example of netcat as a backend for something else is the shell-script +Web browser, which simply asks for the relevant parts of a URL and pipes +"GET /what/ever" into a netcat connection to the server. I used to do this +with telnet, and had to use calculated sleep times and other stupidity to +kludge around telnet's limitations. Netcat guarantees that I get the whole +page, and since it transfers all the data unmodified, I can even pull down +binary image files and display them elsewhere later. Some folks may find the +idea of a shell-script web browser silly and strange, but it starts up and +gets me my info a hell of a lot faster than a GUI browser and doesn't hide +any contents of links and forms and such. This is included, as scripts/web, +along with several other web-related examples. + +Netcat is an obvious replacement for telnet as a tool for talking to daemons. +For example, it is easier to type "nc host 25", talk to someone's mailer, and +just ^C out than having to type ^]c or QUIT as telnet would require you to do. +You can quickly catalog the services on your network by telling netcat to +connect to well-known services and collect greetings, or at least scan for open +ports. You'll probably want to collect netcat's diagnostic messages in your +output files, so be sure to include standard error in the output using +`>& file' in *csh or `> file 2>&1' in bourne shell. + +A scanning example: "echo QUIT | nc -v -w 5 target 20-250 500-600 5990-7000" +will inform you about a target's various well-known TCP servers, including +r-services, X, IRC, and maybe a few you didn't expect. Sending in QUIT and +using the timeout will almost guarantee that you see some kind of greeting or +error from each service, which usually indicates what it is and what version. +[Beware of the "chargen" port, though...] SATAN uses exactly this technique to +collect host information, and indeed some of the ideas herein were taken from +the SATAN backend tools. If you script this up to try every host in your +subnet space and just let it run, you will not only see all the services, +you'll find out about hosts that aren't correctly listed in your DNS. Then you +can compare new snapshots against old snapshots to see changes. For going +after particular services, a more intrusive example is in scripts/probe. + +Netcat can be used as a simple data transfer agent, and it doesn't really +matter which end is the listener and which end is the client -- input at one +side arrives at the other side as output. It is helpful to start the listener +at the receiving side with no timeout specified, and then give the sending side +a small timeout. That way the listener stays listening until you contact it, +and after data stops flowing the client will time out, shut down, and take the +listener with it. Unless the intervening network is fraught with problems, +this should be completely reliable, and you can always increase the timeout. A +typical example of something "rsh" is often used for: on one side, + + nc -l -p 1234 | uncompress -c | tar xvfp - + +and then on the other side + + tar cfp - /some/dir | compress -c | nc -w 3 othermachine 1234 + +will transfer the contents of a directory from one machine to another, without +having to worry about .rhosts files, user accounts, or inetd configurations +at either end. Again, it matters not which is the listener or receiver; the +"tarring" machine could just as easily be running the listener instead. One +could conceivably use a scheme like this for backups, by having cron-jobs fire +up listeners and backup handlers [which can be restricted to specific addresses +and ports between each other] and pipe "dump" or "tar" on one machine to "dd +of=/dev/tapedrive" on another as usual. Since netcat returns a nonzero exit +status for a denied listener connection, scripts to handle such tasks could +easily log and reject connect attempts from third parties, and then retry. + +Another simple data-transfer example: shipping things to a PC that doesn't have +any network applications yet except a TCP stack and a web browser. Point the +browser at an arbitrary port on a Unix server by telling it to download +something like http://unixbox:4444/foo, and have a listener on the Unix side +ready to ship out a file when the connect comes in. The browser may pervert +binary data when told to save the URL, but you can dig the raw data out of +the on-disk cache. + +If you build netcat with GAPING_SECURITY_HOLE defined, you can use it as an +"inetd" substitute to test experimental network servers that would otherwise +run under "inetd". A script or program will have its input and output hooked +to the network the same way, perhaps sans some fancier signal handling. Given +that most network services do not bind to a particular local address, whether +they are under "inetd" or not, it is possible for netcat avoid the "address +already in use" error by binding to a specific address. This lets you [as +root, for low ports] place netcat "in the way" of a standard service, since +inbound connections are generally sent to such specifically-bound listeners +first and fall back to the ones bound to "any". This allows for a one-off +experimental simulation of some service, without having to screw around with +inetd.conf. Running with -v turned on and collecting a connection log from +standard error is recommended. + +Netcat as well can make an outbound connection and then run a program or script +on the originating end, with input and output connected to the same network +port. This "inverse inetd" capability could enhance the backup-server concept +described above or help facilitate things such as a "network dialback" concept. +The possibilities are many and varied here; if such things are intended as +security mechanisms, it may be best to modify netcat specifically for the +purpose instead of wrapping such functions in scripts. + +Speaking of inetd, netcat will function perfectly well *under* inetd as a TCP +connection redirector for inbound services, like a "plug-gw" without the +authentication step. This is very useful for doing stuff like redirecting +traffic through your firewall out to other places like web servers and mail +hubs, while posing no risk to the firewall machine itself. Put netcat behind +inetd and tcp_wrappers, perhaps thusly: + + www stream tcp nowait nobody /etc/tcpd /bin/nc -w 3 realwww 80 + +and you have a simple and effective "application relay" with access control +and logging. Note use of the wait time as a "safety" in case realwww isn't +reachable or the calling user aborts the connection -- otherwise the relay may +hang there forever. + +You can use netcat to generate huge amounts of useless network data for +various performance testing. For example, doing + + yes AAAAAAAAAAAAAAAAAAAAAA | nc -v -v -l -p 2222 > /dev/null + +on one side and then hitting it with + + yes BBBBBBBBBBBBBBBBBBBBBB | nc othermachine 2222 > /dev/null + +from another host will saturate your wires with A's and B's. The "very +verbose" switch usage will tell you how many of each were sent and received +after you interrupt either side. Using UDP mode produces tremendously MORE +trash per unit time in the form of fragmented 8 Kbyte mobygrams -- enough to +stress-test kernels and network interfaces. Firing random binary data into +various network servers may help expose bugs in their input handling, which +nowadays is a popular thing to explore. A simple example data-generator is +given in data/data.c included in this package, along with a small collection +of canned input files to generate various packet contents. This program is +documented in its beginning comments, but of interest here is using "%r" to +generate random bytes at well-chosen points in a data stream. If you can +crash your daemon, you likely have a security problem. + +The hex dump feature may be useful for debugging odd network protocols, +especially if you don't have any network monitoring equipment handy or aren't +root where you'd need to run "tcpdump" or something. Bind a listening netcat +to a local port, and have it run a script which in turn runs another netcat +to the real service and captures the hex dump to a log file. This sets up a +transparent relay between your local port and wherever the real service is. +Be sure that the script-run netcat does *not* use -v, or the extra info it +sends to standard error may confuse the protocol. Note also that you cannot +have the "listen/exec" netcat do the data capture, since once the connection +arrives it is no longer netcat that is running. + +Binding to an arbitrary local port allows you to simulate things like r-service +clients, if you are root locally. For example, feeding "^@root^@joe^@pwd^@" +[where ^@ is a null, and root/joe could be any other local/remote username +pair] into a "rsh" or "rlogin" server, FROM your port 1023 for example, +duplicates what the server expects to receive. Thus, you can test for insecure +.rhosts files around your network without having to create new user accounts on +your client machine. The program data/rservice.c can aid this process by +constructing the "rcmd" protocol bytes. Doing this also prevents "rshd" from +trying to create that separate standard-error socket and still gives you an +input path, as opposed to the usual action of "rsh -n". Using netcat for +things like this can be really useful sometimes, because rsh and rlogin +generally want a host *name* as an argument and won't accept IP addresses. If +your client-end DNS is hosed, as may be true when you're trying to extract +backup sets on to a dumb client, "netcat -n" wins where normal rsh/rlogin is +useless. + +If you are unsure that a remote syslogger is working, test it with netcat. +Make a UDP connection to port 514 and type in "<0>message", which should +correspond to "kern.emerg" and cause syslogd to scream into every file it has +open [and possibly all over users' terminals]. You can tame this down by +using a different number and use netcat inside routine scripts to send syslog +messages to places that aren't configured in syslog.conf. For example, +"echo '<38>message' | nc -w 1 -u loggerhost 514" should send to auth.notice +on loggerhost. The exact number may vary; check against your syslog.h first. + +Netcat provides several ways for you to test your own packet filters. If you +bind to a port normally protected against outside access and make a connection +to somewhere outside your own network, the return traffic will be coming to +your chosen port from the "outside" and should be blocked. TCP may get through +if your filter passes all "ack syn", but it shouldn't be even doing that to low +ports on your network. Remember to test with UDP traffic as well! If your +filter passes at least outbound source-routed IP packets, bouncing a connection +back to yourself via some gateway outside your network will create "incoming" +traffic with your source address, which should get dropped by a correctly +configured anti-spoofing filter. This is a "non-test" if you're also dropping +source-routing, but it's good to be able to test for that too. Any packet +filter worth its salt will be blocking source-routed packets in both +directions, but you never know what interesting quirks you might turn up by +playing around with source ports and addresses and watching the wires with a +network monitor. + +You can use netcat to protect your own workstation's X server against outside +access. X is stupid enough to listen for connections on "any" and never tell +you when new connections arrive, which is one reason it is so vulnerable. Once +you have all your various X windows up and running you can use netcat to bind +just to your ethernet address and listen to port 6000. Any new connections +from outside the machine will hit netcat instead your X server, and you get a +log of who's trying. You can either tell netcat to drop the connection, or +perhaps run another copy of itself to relay to your actual X server on +"localhost". This may not work for dedicated X terminals, but it may be +possible to authorize your X terminal only for its boot server, and run a relay +netcat over on the server that will in turn talk to your X terminal. Since +netcat only handles one listening connection per run, make sure that whatever +way you rig it causes another one to run and listen on 6000 soon afterward, or +your real X server will be reachable once again. A very minimal script just +to protect yourself could be + + while true ; do + nc -v -l -s -p 6000 localhost 2 + done + +which causes netcat to accept and then close any inbound connection to your +workstation's normal ethernet address, and another copy is immediately run by +the script. Send standard error to a file for a log of connection attempts. +If your system can't do the "specific bind" thing all is not lost; run your +X server on display ":1" or port 6001, and netcat can still function as a probe +alarm by listening on 6000. + +Does your shell-account provider allow personal Web pages, but not CGI scripts? +You can have netcat listen on a particular port to execute a program or script +of your choosing, and then just point to the port with a URL in your homepage. +The listener could even exist on a completely different machine, avoiding the +potential ire of the homepage-host administrators. Since the script will get +the raw browser query as input it won't look like a typical CGI script, and +since it's running under your UID you need to write it carefully. You may want +to write a netcat-based script as a wrapper that reads a query and sets up +environment variables for a regular CGI script. The possibilities for using +netcat and scripts to handle Web stuff are almost endless. Again, see the +examples under scripts/. + +Example uses -- the dark side +============================= + +Equal time is deserved here, since a versatile tool like this can be useful +to any Shade of Hat. I could use my Victorinox to either fix your car or +disassemble it, right? You can clearly use something like netcat to attack +or defend -- I don't try to govern anyone's social outlook, I just build tools. +Regardless of your intentions, you should still be aware of these threats to +your own systems. + +The first obvious thing is scanning someone *else's* network for vulnerable +services. Files containing preconstructed data, be it exploratory or +exploitive, can be fed in as standard input, including command-line arguments +to netcat itself to keep "ps" ignorant of your doings. The more random the +scanning, the less likelihood of detection by humans, scan-detectors, or +dynamic filtering, and with -i you'll wait longer but avoid loading down the +target's network. Some examples for crafting various standard UDP probes are +given in data/*.d. + +Some configurations of packet filters attempt to solve the FTP-data problem by +just allowing such connections from the outside. These come FROM port 20, TO +high TCP ports inside -- if you locally bind to port 20, you may find yourself +able to bypass filtering in some cases. Maybe not to low ports "inside", but +perhaps to TCP NFS servers, X servers, Prospero, ciscos that listen on 200x +and 400x... Similar bypassing may be possible for UDP [and maybe TCP too] if a +connection comes from port 53; a filter may assume it's a nameserver response. + +Using -e in conjunction with binding to a specific address can enable "server +takeover" by getting in ahead of the real ones, whereupon you can snarf data +sent in and feed your own back out. At the very least you can log a hex dump +of someone else's session. If you are root, you can certainly use -s and -e to +run various hacked daemons without having to touch inetd.conf or the real +daemons themselves. You may not always have the root access to deal with low +ports, but what if you are on a machine that also happens to be an NFS server? +You might be able to collect some interesting things from port 2049, including +local file handles. There are several other servers that run on high ports +that are likely candidates for takeover, including many of the RPC services on +some platforms [yppasswdd, anyone?]. Kerberos tickets, X cookies, and IRC +traffic also come to mind. RADIUS-based terminal servers connect incoming +users to shell-account machines on a high port, usually 1642 or thereabouts. +SOCKS servers run on 1080. Do "netstat -a" and get creative. + +There are some daemons that are well-written enough to bind separately to all +the local interfaces, possibly with an eye toward heading off this sort of +problem. Named from recent BIND releases, and NTP, are two that come to mind. +Netstat will show these listening on address.53 instead of *.53. You won't +be able to get in front of these on any of the real interface addresses, which +of course is especially interesting in the case of named, but these servers +sometimes forget about things like "alias" interface addresses or interfaces +that appear later on such as dynamic PPP links. There are some hacked web +servers and versions of "inetd" floating around that specifically bind as well, +based on a configuration file -- these generally *are* bound to alias addresses +to offer several different address-based services from one machine. + +Using -e to start a remote backdoor shell is another obvious sort of thing, +easier than constructing a file for inetd to listen on "ingreslock" or +something, and you can access-control it against other people by specifying a +client host and port. Experience with this truly demonstrates how fragile the +barrier between being "logged in" or not really is, and is further expressed by +scripts/bsh. If you're already behind a firewall, it may be easier to make an +*outbound* connection and then run a shell; a small wrapper script can +periodically try connecting to a known place and port, you can later listen +there until the inbound connection arrives, and there's your shell. Running +a shell via UDP has several interesting features, although be aware that once +"connected", the UDP stub sockets tend to show up in "netstat" just like TCP +connections and may not be quite as subtle as you wanted. Packets may also be +lost, so use TCP if you need reliable connections. But since UDP is +connectionless, a hookup of this sort will stick around almost forever, even if +you ^C out of netcat or do a reboot on your side, and you only need to remember +the ports you used on both ends to reestablish. And outbound UDP-plus-exec +connection creates the connected socket and starts the program immediately. On +a listening UDP connection, the socket is created once a first packet is +received. In either case, though, such a "connection" has the interesting side +effect that only your client-side IP address and [chosen?] source port will +thereafter be able to talk to it. Instant access control! A non-local third +party would have to do ALL of the following to take over such a session: + + forge UDP with your source address [trivial to do; see below] + guess the port numbers of BOTH ends, or sniff the wire for them + arrange to block ICMP or UDP return traffic between it and your real + source, so the session doesn't die with a network write error. + +The companion program data/rservice.c is helpful in scripting up any sort of +r-service username or password guessing attack. The arguments to "rservice" +are simply the strings that get null-terminated and passed over an "rcmd"-style +connection, with the assumption that the client does not need a separate +standard-error port. Brute-force password banging is best done via "rexec" if +it is available since it is less likely to log failed attempts. Thus, doing +"rservice joe joespass pwd | nc target exec" should return joe's home dir if +the password is right, or "Permission denied." Plug in a dictionary and go to +town. If you're attacking rsh/rlogin, remember to be root and bind to a port +between 512 and 1023 on your end, and pipe in "rservice joe joe pwd" and such. + +Netcat can prevent inadvertently sending extra information over a telnet +connection. Use "nc -t" in place of telnet, and daemons that try to ask for +things like USER and TERM environment variables will get no useful answers, as +they otherwise would from a more recent telnet program. Some telnetds actually +try to collect this stuff and then plug the USER variable into "login" so that +the caller is then just asked for a password! This mechanism could cause a +login attempt as YOUR real username to be logged over there if you use a +Borman-based telnet instead of "nc -t". + +Got an unused network interface configured in your kernel [e.g. SLIP], or +support for alias addresses? Ifconfig one to be any address you like, and bind +to it with -s to enable all sorts of shenanigans with bogus source addresses. +The interface probably has to be UP before this works; some SLIP versions +need a far-end address before this is true. Hammering on UDP services is then +a no-brainer. What you can do to an unfiltered syslog daemon should be fairly +obvious; trimming the conf file can help protect against it. Many routers out +there still blindly believe what they receive via RIP and other routing +protocols. Although most UDP echo and chargen servers check if an incoming +packet was sent from *another* "internal" UDP server, there are many that still +do not, any two of which [or many, for that matter] could keep each other +entertained for hours at the expense of bandwidth. And you can always make +someone wonder why she's being probed by nsa.gov. + +Your TCP spoofing possibilities are mostly limited to destinations you can +source-route to while locally bound to your phony address. Many sites block +source-routed packets these days for precisely this reason. If your kernel +does oddball things when sending source-routed packets, try moving the pointer +around with -G. You may also have to fiddle with the routing on your own +machine before you start receiving packets back. Warning: some machines still +send out traffic using the source address of the outbound interface, regardless +of your binding, especially in the case of localhost. Check first. If you can +open a connection but then get no data back from it, the target host is +probably killing the IP options on its end [this is an option inside TCP +wrappers and several other packages], which happens after the 3-way handshake +is completed. If you send some data and observe the "send-q" side of "netstat" +for that connection increasing but never getting sent, that's another symptom. +Beware: if Sendmail 8.7.x detects a source-routed SMTP connection, it extracts +the hop list and sticks it in the Received: header! + +SYN bombing [sometimes called "hosing"] can disable many TCP servers, and if +you hit one often enough, you can keep it unreachable for days. As is true of +many other denial-of-service attacks, there is currently no defense against it +except maybe at the human level. Making kernel SOMAXCONN considerably larger +than the default and the half-open timeout smaller can help, and indeed some +people running large high-performance web servers have *had* to do that just to +handle normal traffic. Taking out mailers and web servers is sociopathic, but +on the other hand it is sometimes useful to be able to, say, disable a site's +identd daemon for a few minutes. If someone realizes what is going on, +backtracing will still be difficult since the packets have a phony source +address, but calls to enough ISP NOCs might eventually pinpoint the source. +It is also trivial for a clueful ISP to watch for or even block outgoing +packets with obviously fake source addresses, but as we know many of them are +not clueful or willing to get involved in such hassles. Besides, outbound +packets with an [otherwise unreachable] source address in one of their net +blocks would look fairly legitimate. + +Notes +===== + +A discussion of various caveats, subtleties, and the design of the innards. + +As of version 1.07 you can construct a single file containing command arguments +and then some data to transfer. Netcat is now smart enough to pick out the +first line and build the argument list, and send any remaining data across the +net to one or multiple ports. The first release of netcat had trouble with +this -- it called fgets() for the command line argument, which behind the +scenes does a large read() from standard input, perhaps 4096 bytes or so, and +feeds that out to the fgets() library routine. By the time netcat 1.00 started +directly read()ing stdin for more data, 4096 bytes of it were gone. It now +uses raw read() everywhere and does the right thing whether reading from files, +pipes, or ttys. If you use this for multiple-port connections, the single +block of data will now be a maximum of 8K minus the first line. Improvements +have been made to the logic in sending the saved chunk to each new port. Note +that any command-line arguments hidden using this mechanism could still be +extracted from a core dump. + +When netcat receives an inbound UDP connection, it creates a "connected socket" +back to the source of the connection so that it can also send out data using +normal write(). Using this mechanism instead of recvfrom/sendto has several +advantages -- the read/write select loop is simplified, and ICMP errors can in +effect be received by non-root users. However, it has the subtle side effect +that if further UDP packets arrive from the caller but from different source +ports, the listener will not receive them. UDP listen mode on a multihomed +machine may have similar quirks unless you specifically bind to one of its +addresses. It is not clear that kernel support for UDP connected sockets +and/or my understanding of it is entirely complete here, so experiment... + +You should be aware of some subtleties concerning UDP scanning. If -z is on, +netcat attempts to send a single null byte to the target port, twice, with a +small time in between. You can either use the -w timeout, or netcat will try +to make a "sideline" TCP connection to the target to introduce a small time +delay equal to the round-trip time between you and the target. Note that if +you have a -w timeout and -i timeout set, BOTH take effect and you wait twice +as long. The TCP connection is to a normally refused port to minimize traffic, +but if you notice a UDP fast-scan taking somewhat longer than it should, it +could be that the target is actually listening on the TCP port. Either way, +any ICMP port-unreachable messages from the target should have arrived in the +meantime. The second single-byte UDP probe is then sent. Under BSD kernels, +the ICMP error is delivered to the "connected socket" and the second write +returns an error, which tells netcat that there is NOT a UDP service there. +While Linux seems to be a fortunate exception, under many SYSV derived kernels +the ICMP is not delivered, and netcat starts reporting that *all* the ports are +"open" -- clearly wrong. [Some systems may not even *have* the "udp connected +socket" concept, and netcat in its current form will not work for UDP at all.] +If -z is specified and only one UDP port is probed, netcat's exit status +reflects whether the connection was "open" or "refused" as with TCP. + +It may also be that UDP packets are being blocked by filters with no ICMP error +returns, in which case everything will time out and return "open". This all +sounds backwards, but that's how UDP works. If you're not sure, try "echo +w00gumz | nc -u -w 2 target 7" to see if you can reach its UDP echo port at +all. You should have no trouble using a BSD-flavor system to scan for UDP +around your own network, although flooding a target with the high activity that +-z generates will cause it to occasionally drop packets and indicate false +"opens". A more "correct" way to do this is collect and analyze the ICMP +errors, as does SATAN's "udp_scan" backend, but then again there's no guarantee +that the ICMP gets back to you either. Udp_scan also does the zero-byte +probes but is excruciatingly careful to calculate its own round-trip timing +average and dynamically set its own response timeouts along with decoding any +ICMP received. Netcat uses a much sleazier method which is nonetheless quite +effective. Cisco routers are known to have a "dead time" in between ICMP +responses about unreachable UDP ports, so a fast scan of a cisco will show +almost everything "open". If you are looking for a specific UDP service, you +can construct a file containing the right bytes to trigger a response from the +other end and send that as standard input. Netcat will read up to 8K of the +file and send the same data to every UDP port given. Note that you must use a +timeout in this case [as would any other UDP client application] since the +two-write probe only happens if -z is specified. + +Many telnet servers insist on a specific set of option negotiations before +presenting a login banner. On a raw connection you will see this as small +amount of binary gook. My attempts to create fixed input bytes to make a +telnetd happy worked some places but failed against newer BSD-flavor ones, +possibly due to timing problems, but there are a couple of much better +workarounds. First, compile with -DTELNET and use -t if you just want to get +past the option negotiation and talk to something on a telnet port. You will +still see the binary gook -- in fact you'll see a lot more of it as the options +are responded to behind the scenes. The telnet responder does NOT update the +total byte count, or show up in the hex dump -- it just responds negatively to +any options read from the incoming data stream. If you want to use a normal +full-blown telnet to get to something but also want some of netcat's features +involved like settable ports or timeouts, construct a tiny "foo" script: + + #! /bin/sh + exec nc -otheroptions targethost 23 + +and then do + + nc -l -p someport -e foo localhost & + telnet localhost someport + +and your telnet should connect transparently through the exec'ed netcat to +the target, using whatever options you supplied in the "foo" script. Don't +use -t inside the script, or you'll wind up sending *two* option responses. + +I've observed inconsistent behavior under some Linuxes [perhaps just older +ones?] when binding in listen mode. Sometimes netcat binds only to "localhost" +if invoked with no address or port arguments, and sometimes it is unable to +bind to a specific address for listening if something else is already listening +on "any". The former problem can be worked around by specifying "-s 0.0.0.0", +which will do the right thing despite netcat claiming that it's listening on +[127.0.0.1]. This is a known problem -- for example, there's a mention of it +in the makefile for SOCKS. On the flip side, binding to localhost and sending +packets to some other machine doesn't work as you'd expect -- they go out with +the source address of the sending interface instead. The Linux kernel contains +a specific check to ensure that packets from 127.0.0.1 are never sent to the +wire; other kernels may contain similar code. Linux, of course, *still* +doesn't support source-routing, but they claim that it and many other network +improvements are at least breathing hard. + +There are several possible errors associated with making TCP connections, but +to specifically see anything other than "refused", one must wait the full +kernel-defined timeout for a connection to fail. Netcat's mechanism of +wrapping an alarm timer around the connect prevents the *real* network error +from being returned -- "errno" at that point indicates "interrupted system +call" since the connect attempt was interrupted. Some old 4.3 BSD kernels +would actually return things like "host unreachable" immediately if that was +the case, but most newer kernels seem to wait the full timeout and *then* pass +back the real error. Go figure. In this case, I'd argue that the old way was +better, despite those same kernels generally being the ones that tear down +*established* TCP connections when ICMP-bombed. + +Incoming socket options are passed to applications by the kernel in the +kernel's own internal format. The socket-options structure for source-routing +contains the "first-hop" IP address first, followed by the rest of the real +options list. The kernel uses this as is when sending reply packets -- the +structure is therefore designed to be more useful to the kernel than to humans, +but the hex dump of it that netcat produces is still useful to have. + +Kernels treat source-routing options somewhat oddly, but it sort of makes sense +once one understands what's going on internally. The options list of addresses +must contain hop1, hop2, ..., destination. When a source-routed packet is sent +by the kernel [at least BSD], the actual destination address becomes irrelevant +because it is replaced with "hop1", "hop1" is removed from the options list, +and all the other addresses in the list are shifted up to fill the hole. Thus +the outbound packet is sent from your chosen source address to the first +*gateway*, and the options list now contains hop2, ..., destination. During +all this address shuffling, the kernel does NOT change the pointer value, which +is why it is useful to be able to set the pointer yourself -- you can construct +some really bizarre return paths, and send your traffic fairly directly to the +target but around some larger loop on the way back. Some Sun kernels seem to +never flip the source-route around if it contains less than three hops, never +reset the pointer anyway, and tries to send the packet [with options containing +a "completed" source route!!] directly back to the source. This is way broken, +of course. [Maybe ipforwarding has to be on? I haven't had an opportunity to +beat on it thoroughly yet.] + +"Credits" section: The original idea for netcat fell out of a long-standing +desire and fruitless search for a tool resembling it and having the same +features. After reading some other network code and realizing just how many +cool things about sockets could be controlled by the calling user, I started +on the basics and the rest fell together pretty quickly. Some port-scanning +ideas were taken from Venema/Farmer's SATAN tool kit, and Pluvius' "pscan" +utility. Healthy amounts of BSD kernel source were perused in an attempt to +dope out socket options and source-route handling; additional help was obtained +from Dave Borman's telnet sources. The select loop is loosely based on fairly +well-known code from "rsh" and Richard Stevens' "sock" program [which itself is +sort of a "netcat" with more obscure features], with some more paranoid +sanity-checking thrown in to guard against the distinct likelihood that there +are subtleties about such things I still don't understand. I found the +argument-hiding method cleanly implemented in Barrett's "deslogin"; reading the +line as input allows greater versatility and is much less prone to cause +bizarre problems than the more common trick of overwriting the argv array. +After the first release, several people contributed portability fixes; they are +credited in generic.h and the Makefile. Lauren Burka inspired the ascii art +for this revised document. Dean Gaudet at Wired supplied a precursor to +the hex-dump code, and mudge@l0pht.com originally experimented with and +supplied code for the telnet-options responder. Outbound "-e " resulted +from a need to quietly bypass a firewall installation. Other suggestions and +patches have rolled in for which I am always grateful, but there are only 26 +hours per day and a discussion of feature creep near the end of this document. + +Netcat was written with the Russian railroad in mind -- conservatively built +and solid, but it *will* get you there. While the coding style is fairly +"tight", I have attempted to present it cleanly [keeping *my* lines under 80 +characters, dammit] and put in plenty of comments as to why certain things +are done. Items I know to be questionable are clearly marked with "XXX". +Source code was made to be modified, but determining where to start is +difficult with some of the tangles of spaghetti code that are out there. +Here are some of the major points I feel are worth mentioning about netcat's +internal design, whether or not you agree with my approach. + +Except for generic.h, which changes to adapt more platforms, netcat is a single +source file. This has the distinct advantage of only having to include headers +once and not having to re-declare all my functions in a billion different +places. I have attempted to contain all the gross who's-got-what-.h-file +things in one small dumping ground. Functions are placed "dependencies-first", +such that when the compiler runs into the calls later, it already knows the +type and arguments and won't complain. No function prototyping -- not even the +__P(()) crock -- is used, since it is more portable and a file of this size is +easy enough to check manually. Each function has a standard-format comment +ahead of it, which is easily found using the regexp " :$". I freely use gotos. +Loops and if-clauses are made as small and non-nested as possible, and the ends +of same *marked* for clarity [I wish everyone would do this!!]. + +Large structures and buffers are all malloc()ed up on the fly, slightly larger +than the size asked for and zeroed out. This reduces the chances of damage +from those "end of the buffer" fencepost errors or runaway pointers escaping +off the end. These things are permanent per run, so nothing needs to be freed +until the program exits. + +File descriptor zero is always expected to be standard input, even if it is +closed. If a new network descriptor winds up being zero, a different one is +asked for which will be nonzero, and fd zero is simply left kicking around +for the rest of the run. Why? Because everything else assumes that stdin is +always zero and "netfd" is always positive. This may seem silly, but it was a +lot easier to code. The new fd is obtained directly as a new socket, because +trying to simply dup() a new fd broke subsequent socket-style use of the new fd +under Solaris' stupid streams handling in the socket library. + +The catch-all message and error handlers are implemented with an ample list of +phoney arguments to get around various problems with varargs. Varargs seems +like deliberate obfuscation in the first place, and using it would also +require use of vfprintf() which not all platforms support. The trailing +sleep in bail() is to allow output to flush, which is sometimes needed if +netcat is already on the other end of a network connection. + +The reader may notice that the section that does DNS lookups seems much +gnarlier and more confusing than other parts. This is NOT MY FAULT. The +sockaddr and hostent abstractions are an abortion that forces the coder to +deal with it. Then again, a lot of BSD kernel code looks like similar +struct-pointer hell. I try to straighten it out somewhat by defining my own +HINF structure, containing names, ascii-format IP addresses, and binary IP +addresses. I fill this structure exactly once per host argument, and squirrel +everything safely away and handy for whatever wants to reference it later. + +Where many other network apps use the FIONBIO ioctl to set non-blocking I/O +on network sockets, netcat uses straightforward blocking I/O everywhere. +This makes everything very lock-step, relying on the network and filesystem +layers to feed in data when needed. Data read in is completely written out +before any more is fetched. This may not be quite the right thing to do under +some OSes that don't do timed select() right, but this remains to be seen. + +The hexdump routine is written to be as fast as possible, which is why it does +so much work itself instead of just sprintf()ing everything together. Each +dump line is built into a single buffer and atomically written out using the +lowest level I/O calls. Further improvements could undoubtedly be made by +using writev() and eliminating all sprintf()s, but it seems to fly right along +as is. If both exec-a-prog mode and a hexdump file is asked for, the hexdump +flag is deliberately turned off to avoid creating random zero-length files. +Files are opened in "truncate" mode; if you want "append" mode instead, change +the open flags in main(). + +main() may look a bit hairy, but that's only because it has to go down the +argv list and handle multiple ports, random mode, and exit status. Efforts +have been made to place a minimum of code inside the getopt() loop. Any real +work is sent off to functions in what is hopefully a straightforward way. + +Obligatory vendor-bash: If "nc" had become a standard utility years ago, +the commercial vendors would have likely packaged it setuid root and with +-DGAPING_SECURITY_HOLE turned on but not documented. It is hoped that netcat +will aid people in finding and fixing the no-brainer holes of this sort that +keep appearing, by allowing easier experimentation with the "bare metal" of +the network layer. + +It could be argued that netcat already has too many features. I have tried +to avoid "feature creep" by limiting netcat's base functionality only to those +things which are truly relevant to making network connections and the everyday +associated DNS lossage we're used to. Option switches already have slightly +overloaded functionality. Random port mode is sort of pushing it. The +hex-dump feature went in later because it *is* genuinely useful. The +telnet-responder code *almost* verges on the gratuitous, especially since it +mucks with the data stream, and is left as an optional piece. Many people have +asked for example "how 'bout adding encryption?" and my response is that such +things should be separate entities that could pipe their data *through* netcat +instead of having their own networking code. I am therefore not completely +enthusiastic about adding any more features to this thing, although you are +still free to send along any mods you think are useful. + +Nonetheless, at this point I think of netcat as my tcp/ip swiss army knife, +and the numerous companion programs and scripts to go with it as duct tape. +Duct tape of course has a light side and a dark side and binds the universe +together, and if I wrap enough of it around what I'm trying to accomplish, +it *will* work. Alternatively, if netcat is a large hammer, there are many +network protocols that are increasingly looking like nails by now... + +_H* 960320 v1.10 RELEASE -- happy spring! diff --git a/license.txt b/license.txt new file mode 100755 index 0000000..5b6e7c6 --- /dev/null +++ b/license.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/makefile b/makefile new file mode 100755 index 0000000..fa324b7 --- /dev/null +++ b/makefile @@ -0,0 +1,21 @@ + +cc=cl +link=link + +cflags=/nologo /ML /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "TELNET" /D "GAPING_SECURITY_HOLE" /YX /FD /c +lflags=kernel32.lib user32.lib wsock32.lib winmm.lib /nologo /subsystem:console /incremental:yes /machine:I386 /out:nc.exe + +all: nc.exe + +getopt.obj: getopt.c + $(cc) $(cflags) getopt.c + +doexec.obj: doexec.c + $(cc) $(cflags) doexec.c + +netcat.obj: netcat.c + $(cc) $(cflags) netcat.c + + +nc.exe: getopt.obj doexec.obj netcat.obj + $(link) getopt.obj doexec.obj netcat.obj $(lflags) diff --git a/makewin.cmd b/makewin.cmd new file mode 100755 index 0000000..c8bf38c --- /dev/null +++ b/makewin.cmd @@ -0,0 +1,43 @@ +@REM Build script to compile Netcat on WIN32 using MinGW +@REM +@REM Rodney Beede (http://www.rodneybeede.com) +@REM +@REM 2009-09-02 +@REM +@REM Tested with gcc 3.4.5 and MinGW version 5.1.4 +@REM +@REM [[ diegocr ]] +@REM +@REM 2010-12-14 +@REM +@REM Tested with gcc 4.5.0 and MinGW version 3.1.8(?) +@REM Added more compiler options and strip usage +@echo off + +SET PROGRAM=nc.exe +SET PCOPY=COPY /Y %PROGRAM% c:\windows\system32 + +SET COMPILER=c:\MinGW\bin\gcc.exe +SET STRIP=c:\MinGW\bin\strip.exe +SET LIB_DIR=c:\MinGW\lib + +@REM not needed? SET CFLAGS=-c -DWIN32 -DNDEBUG -D_CONSOLE -DTELNET +SET XFLAGS=-O3 -march=i686 +SET CFLAGS=-c %XFLAGS% -DTELNET +SET LFLAGS=%XFLAGS% + +del *.o +del nc.exe + +"%COMPILER%" %CFLAGS% getopt.c + +"%COMPILER%" %CFLAGS% doexec.c + +"%COMPILER%" %CFLAGS% netcat.c + +@REM Note that the -l libraries MUST come at the very end or linking will fail +"%COMPILER%" getopt.o doexec.o netcat.o -o %PROGRAM% %LFLAGS% -Wl,-L"%LIB_DIR%",-lkernel32,-luser32,-lwinmm,-lws2_32 +"%STRIP%" -s %PROGRAM% +%PCOPY% + +echo Operation Completed diff --git a/nc.exe b/nc.exe new file mode 100755 index 0000000000000000000000000000000000000000..eebfbaa65630fa45e584cf80caa11769d010f711 GIT binary patch literal 40448 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 +#else +#include /* xxx: or does it live in sys/ ?? */ +#endif + +/* have to do this *before* including types.h. xxx: Linux still has it wrong */ +#ifdef FD_SETSIZE /* should be in types.h, butcha never know. */ +#undef FD_SETSIZE /* if we ever need more than 16 active */ +#endif /* fd's, something is horribly wrong! */ +#ifdef WIN32 +#define FD_SETSIZE 64 /* WIN32 does this as an array not a bitfield and it likes 64 */ +#else +#define FD_SETSIZE 16 /* <-- this'll give us a long anyways, wtf */ +#endif +#include /* *now* do it. Sigh, this is broken */ + + +#ifdef WIN32 +#undef HAVE_RANDOM +#undef IP_OPTIONS +#undef SO_REUSEPORT +#include +#endif + + +#ifdef HAVE_RANDOM +#define SRAND srandom +#define RAND random +#else +#define SRAND srand +#define RAND rand +#endif /* HAVE_RANDOM */ + +/* xxx: these are rsh leftovers, move to new generic.h */ +/* will we even need any nonblocking shit? Doubt it. */ +/* get FIONBIO from sys/filio.h, so what if it is a compatibility feature */ +/* #include */ +/* +#include +#include +*/ + +/* includes: */ + +#ifdef WIN32 +#include "getopt.h" +// #define sleep _sleep +#define sleep(_x) Sleep((_x)*1000) // sleep is now deprecated [diegocr] +#define strcasecmp strcmpi +#define EADDRINUSE WSAEADDRINUSE +#define ETIMEDOUT WSAETIMEDOUT +#define ECONNREFUSED WSAECONNREFUSED +#endif + +#ifndef WIN32 +#include /* timeval, time_t */ +#else +#include +#endif + +#include /* jmp_buf et al */ + +#ifndef WIN32 +#include /* basics, SO_ and AF_ defs, sockaddr, ... */ +#include /* sockaddr_in, htons, in_addr */ +#include /* misc crud that netinet/ip.h references */ +#include /* IPOPT_LSRR, header stuff */ +#include /* hostent, gethostby*, getservby* */ +#include /* inet_ntoa */ +#else +#include +#include +#include +//#include +#endif + +#include +#include /* strcpy, strchr, yadda yadda */ +#include +#include + +/* handy stuff: */ +#define SA struct sockaddr /* socket overgeneralization braindeath */ +#define SAI struct sockaddr_in /* ... whoever came up with this model */ +#define IA struct in_addr /* ... should be taken out and shot, */ + /* ... not that TLI is any better. sigh.. */ +#define SLEAZE_PORT 31337 /* for UDP-scan RTT trick, change if ya want */ +#define USHORT unsigned short /* use these for options an' stuff */ +#define BIGSIZ 8192 /* big buffers */ +#define SMALLSIZ 256 /* small buffers, hostnames, etc */ + +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif +#ifdef MAXHOSTNAMELEN +#undef MAXHOSTNAMELEN /* might be too small on aix, so fix it */ +#endif +#define MAXHOSTNAMELEN 256 +struct host_poop { + char name[MAXHOSTNAMELEN]; /* dns name */ + char addrs[8][24]; /* ascii-format IP addresses */ + struct in_addr iaddrs[8]; /* real addresses: in_addr.s_addr: ulong */ +}; +#define HINF struct host_poop +struct port_poop { + char name [64]; /* name in /etc/services */ + char anum [8]; /* ascii-format number */ + USHORT num; /* real host-order number */ +}; +#define PINF struct port_poop + +/* globals: */ +jmp_buf jbuf; /* timer crud */ +int jval = 0; /* timer crud */ +int netfd = -1; +int ofd = 0; /* hexdump output fd */ +static char unknown[] = "(UNKNOWN)"; +static char p_tcp[] = "tcp"; /* for getservby* */ +static char p_udp[] = "udp"; + +#ifndef WIN32 +#ifdef HAVE_BIND +extern int h_errno; +#endif +#endif +int gatesidx = 0; /* LSRR hop count */ +int gatesptr = 4; /* initial LSRR pointer, settable */ +USHORT Single = 1; /* zero if scanning */ +unsigned int insaved = 0; /* stdin-buffer size for multi-mode */ +unsigned int wrote_out = 0; /* total stdout bytes */ +unsigned int wrote_net = 0; /* total net bytes */ +static char wrote_txt[] = " sent %d, rcvd %d"; +static char hexnibs[20] = "0123456789abcdef "; + +/* will malloc up the following globals: */ +struct timeval * timer1 = NULL; +struct timeval * timer2 = NULL; +SAI * lclend = NULL; /* sockaddr_in structs */ +SAI * remend = NULL; +HINF ** gates = NULL; /* LSRR hop hostpoop */ +char * optbuf = NULL; /* LSRR or sockopts */ +char * bigbuf_in; /* data buffers */ +char * bigbuf_net; +fd_set * ding1; /* for select loop */ +fd_set * ding2; +PINF * portpoop = NULL; /* for getportpoop / getservby* */ +unsigned char * stage = NULL; /* hexdump line buffer */ + +#ifdef WIN32 + char * setsockopt_c; +int nnetfd; +#endif + +/* global cmd flags: */ +USHORT o_alla = 0; +unsigned int o_interval = 0; +USHORT o_listen = 0; +USHORT o_nflag = 0; +USHORT o_wfile = 0; +USHORT o_random = 0; +USHORT o_udpmode = 0; +USHORT o_verbose = 0; +unsigned int o_wait = 0; +USHORT o_zero = 0; + +/* Debug macro: squirt whatever to stderr and sleep a bit so we can see it go + by. need to call like Debug ((stuff)) [with no ; ] so macro args match! + Beware: writes to stdOUT... */ +#ifdef DEBUG +#define Debug(x) printf x; printf ("\n"); fflush (stdout); sleep (1); +#else +#define Debug(x) /* nil... */ +#endif + +/* support routines -- the bulk of this thing. Placed in such an order that + we don't have to forward-declare anything: */ + +int helpme(); /* oop */ + +#ifdef WIN32 + +/* res_init + winsock needs to be initialized. Might as well do it as the res_init + call for Win32 */ + +void res_init() +{ +WORD wVersionRequested; +WSADATA wsaData; +int err; +wVersionRequested = MAKEWORD(1, 1); + +err = WSAStartup(wVersionRequested, &wsaData); + +if (err != 0) + /* Tell the user that we couldn't find a useable */ + /* winsock.dll. */ + return; + +/* Confirm that the Windows Sockets DLL supports 1.1.*/ +/* Note that if the DLL supports versions greater */ +/* than 1.1 in addition to 1.1, it will still return */ +/* 1.1 in wVersion since that is the version we */ +/* requested. */ + +if ( LOBYTE( wsaData.wVersion ) != 1 || + HIBYTE( wsaData.wVersion ) != 1 ) { + /* Tell the user that we couldn't find a useable */ + /* winsock.dll. */ + WSACleanup(); + return; + } + +} + + + + +/* winsockstr + Windows Sockets cannot report errors through perror() so we need to define + our own error strings to print. Someday all the string should be prettied up. + Prettied the errors I usually get */ +char * winsockstr(error) +int error; +{ + switch (error) + { + case WSAEINTR : return("INTR "); + case WSAEBADF : return("BADF "); + case WSAEACCES : return("ACCES "); + case WSAEFAULT : return("FAULT "); + case WSAEINVAL : return("INVAL "); + case WSAEMFILE : return("MFILE "); + case WSAEWOULDBLOCK : return("WOULDBLOCK "); + case WSAEINPROGRESS : return("INPROGRESS "); + case WSAEALREADY : return("ALREADY "); + case WSAENOTSOCK : return("NOTSOCK "); + case WSAEDESTADDRREQ : return("DESTADDRREQ "); + case WSAEMSGSIZE : return("MSGSIZE "); + case WSAEPROTOTYPE : return("PROTOTYPE "); + case WSAENOPROTOOPT : return("NOPROTOOPT "); + case WSAEPROTONOSUPPORT: return("PROTONOSUPPORT"); + case WSAESOCKTNOSUPPORT: return("SOCKTNOSUPPORT"); + case WSAEOPNOTSUPP : return("OPNOTSUPP "); + case WSAEPFNOSUPPORT : return("PFNOSUPPORT "); + case WSAEAFNOSUPPORT : return("AFNOSUPPORT "); + case WSAEADDRINUSE : return("ADDRINUSE "); + case WSAEADDRNOTAVAIL : return("ADDRNOTAVAIL "); + case WSAENETDOWN : return("NETDOWN "); + case WSAENETUNREACH : return("NETUNREACH "); + case WSAENETRESET : return("NETRESET "); + case WSAECONNABORTED : return("CONNABORTED "); + case WSAECONNRESET : return("CONNRESET "); + case WSAENOBUFS : return("NOBUFS "); + case WSAEISCONN : return("ISCONN "); + case WSAENOTCONN : return("NOTCONN "); + case WSAESHUTDOWN : return("SHUTDOWN "); + case WSAETOOMANYREFS : return("TOOMANYREFS "); + case WSAETIMEDOUT : return("TIMEDOUT "); + case WSAECONNREFUSED : return("connection refused"); + case WSAELOOP : return("LOOP "); + case WSAENAMETOOLONG : return("NAMETOOLONG "); + case WSAEHOSTDOWN : return("HOSTDOWN "); + case WSAEHOSTUNREACH : return("HOSTUNREACH "); + case WSAENOTEMPTY : return("NOTEMPTY "); + case WSAEPROCLIM : return("PROCLIM "); + case WSAEUSERS : return("USERS "); + case WSAEDQUOT : return("DQUOT "); + case WSAESTALE : return("STALE "); + case WSAEREMOTE : return("REMOTE "); + case WSAEDISCON : return("DISCON "); + case WSASYSNOTREADY : return("SYSNOTREADY "); + case WSAVERNOTSUPPORTED: return("VERNOTSUPPORTED"); + case WSANOTINITIALISED : return("NOTINITIALISED "); + case WSAHOST_NOT_FOUND : return("HOST_NOT_FOUND "); + case WSATRY_AGAIN : return("TRY_AGAIN "); + case WSANO_RECOVERY : return("NO_RECOVERY "); + case WSANO_DATA : return("NO_DATA "); + default : return("unknown socket error"); + } +} +#endif + + + + + +/* holler : + fake varargs -- need to do this way because we wind up calling through + more levels of indirection than vanilla varargs can handle, and not all + machines have vfprintf/vsyslog/whatever! 6 params oughta be enough. */ +void holler (str, p1, p2, p3, p4, p5, p6) + char * str; + char * p1, * p2, * p3, * p4, * p5, * p6; +{ + if (o_verbose) { + fprintf (stderr, str, p1, p2, p3, p4, p5, p6); +#ifdef WIN32 + if (h_errno) + fprintf (stderr, ": %s\n",winsockstr(h_errno)); +#else + if (errno) { /* this gives funny-looking messages, but */ + perror (" "); /* it's more portable than sys_errlist[]... */ + } /* xxx: do something better. */ +#endif + else + fprintf (stderr, "\n"); + fflush (stderr); + } +} /* holler */ + +/* bail : + error-exit handler, callable from anywhere */ +void bail (str, p1, p2, p3, p4, p5, p6) + char * str; + char * p1, * p2, * p3, * p4, * p5, * p6; +{ + o_verbose = 1; + holler (str, p1, p2, p3, p4, p5, p6); +#ifdef WIN32 + shutdown(netfd, 0x02); /* Kirby */ + closesocket (netfd); +#else + close (netfd); +#endif + sleep (1); + exit (1); +} /* bail */ + +/* catch : + no-brainer interrupt handler */ +void catch () +{ + errno = 0; + if (o_verbose > 1) /* normally we don't care */ + bail (wrote_txt, wrote_net, wrote_out); + + bail (" punt!"); +} + +/* timeout and other signal handling cruft */ +void tmtravel () +{ +#ifdef NTFIXTHIS + signal (SIGALRM, SIG_IGN); + alarm (0); +#endif + if (jval == 0) + bail ("spurious timer interrupt!"); + longjmp (jbuf, jval); +} + + + +UINT theTimer; + +/* arm : + set the timer. Zero secs arg means unarm */ +void arm (num, secs) + unsigned int num; + unsigned int secs; +{ + +#ifdef WIN32 + HANDLE stdhnd; + stdhnd = GetStdHandle(STD_OUTPUT_HANDLE); +#ifdef DEBUG + if (stdhnd != INVALID_HANDLE_VALUE) + printf("handle is %ld\n", stdhnd); + else + printf("failed to get stdhndl\n"); +#endif +#else +if (secs == 0) { /* reset */ + signal (SIGALRM, SIG_IGN); + alarm (0); + jval = 0; + } else { /* set */ + signal (SIGALRM, tmtravel); + alarm (secs); + jval = num; + } /* if secs */ +#endif /* WIN32 */ +} /* arm */ + +/* Hmalloc : + malloc up what I want, rounded up to *4, and pre-zeroed. Either succeeds + or bails out on its own, so that callers don't have to worry about it. */ +char * Hmalloc (size) + unsigned int size; +{ + unsigned int s = (size + 4) & 0xfffffffc; /* 4GB?! */ + char * p = malloc (s); + if (p != NULL) + memset (p, 0, s); + else + bail ("Hmalloc %d failed", s); + return (p); +} /* Hmalloc */ + +/* findline : + find the next newline in a buffer; return inclusive size of that "line", + or the entire buffer size, so the caller knows how much to then write(). + Not distinguishing \n vs \r\n for the nonce; it just works as is... */ +unsigned int findline (buf, siz) + char * buf; + unsigned int siz; +{ + register char * p; + register int x; + if (! buf) /* various sanity checks... */ + return (0); + if (siz > BIGSIZ) + return (0); + x = siz; + for (p = buf; x > 0; x--) { + if (*p == '\n') { + x = (int) (p - buf); + x++; /* 'sokay if it points just past the end! */ +Debug (("findline returning %d", x)) + return (x); + } + p++; + } /* for */ +Debug (("findline returning whole thing: %d", siz)) + return (siz); +} /* findline */ + +/* comparehosts : + cross-check the host_poop we have so far against new gethostby*() info, + and holler about mismatches. Perhaps gratuitous, but it can't hurt to + point out when someone's DNS is fukt. Returns 1 if mismatch, in case + someone else wants to do something about it. */ +int comparehosts (poop, hp) + HINF * poop; + struct hostent * hp; +{ + errno = 0; +#ifndef WIN32 + h_errno = 0; +#endif +/* The DNS spec is officially case-insensitive, but for those times when you + *really* wanna see any and all discrepancies, by all means define this. */ +#ifdef ANAL + if (strcmp (poop->name, hp->h_name) != 0) { /* case-sensitive */ +#else + if (strcasecmp (poop->name, hp->h_name) != 0) { /* normal */ +#endif + holler ("DNS fwd/rev mismatch: %s != %s", poop->name, hp->h_name); + return (1); + } + return (0); +/* ... do we need to do anything over and above that?? */ +} /* comparehosts */ + +/* gethostpoop : + resolve a host 8 ways from sunday; return a new host_poop struct with its + info. The argument can be a name or [ascii] IP address; it will try its + damndest to deal with it. "numeric" governs whether we do any DNS at all, + and we also check o_verbose for what's appropriate work to do. */ +HINF * gethostpoop (name, numeric) + char * name; + USHORT numeric; +{ + struct hostent * hostent; + struct in_addr iaddr; + register HINF * poop = NULL; + register int x; + +/* I really want to strangle the twit who dreamed up all these sockaddr and + hostent abstractions, and then forced them all to be incompatible with + each other so you *HAVE* to do all this ridiculous casting back and forth. + If that wasn't bad enough, all the doc insists on referring to local ports + and addresses as "names", which makes NO sense down at the bare metal. + + What an absolutely horrid paradigm, and to think of all the people who + have been wasting significant amounts of time fighting with this stupid + deliberate obfuscation over the last 10 years... then again, I like + languages wherein a pointer is a pointer, what you put there is your own + business, the compiler stays out of your face, and sheep are nervous. + Maybe that's why my C code reads like assembler half the time... */ + +/* If we want to see all the DNS stuff, do the following hair -- + if inet_addr, do reverse and forward with any warnings; otherwise try + to do forward and reverse with any warnings. In other words, as long + as we're here, do a complete DNS check on these clowns. Yes, it slows + things down a bit for a first run, but once it's cached, who cares? */ + + errno = 0; +#ifndef WIN32 + h_errno = 0; +#endif + if (name) + poop = (HINF *) Hmalloc (sizeof (HINF)); + if (! poop) + bail ("gethostpoop fuxored"); + strcpy (poop->name, unknown); /* preload it */ +/* see wzv:workarounds.c for dg/ux return-a-struct inet_addr lossage */ + iaddr.s_addr = inet_addr (name); + + if (iaddr.s_addr == INADDR_NONE) { /* here's the great split: names... */ + if (numeric) + bail ("Can't parse %s as an IP address", name); + hostent = gethostbyname (name); + if (! hostent) +/* failure to look up a name is fatal, since we can't do anything with it */ +/* XXX: h_errno only if BIND? look up how telnet deals with this */ + bail ("%s: forward host lookup failed: h_errno %d", name, h_errno); + strncpy (poop->name, hostent->h_name, sizeof (poop->name)); + for (x = 0; hostent->h_addr_list[x] && (x < 8); x++) { + memcpy (&poop->iaddrs[x], hostent->h_addr_list[x], sizeof (IA)); + strncpy (poop->addrs[x], inet_ntoa (poop->iaddrs[x]), + sizeof (poop->addrs[0])); + } /* for x -> addrs, part A */ + if (! o_verbose) /* if we didn't want to see the */ + return (poop); /* inverse stuff, we're done. */ +/* do inverse lookups in separate loop based on our collected forward addrs, + since gethostby* tends to crap into the same buffer over and over */ + for (x = 0; poop->iaddrs[x].s_addr && (x < 8); x++) { + hostent = gethostbyaddr ((char *)&poop->iaddrs[x], + sizeof (IA), AF_INET); + if ((! hostent) || (! hostent-> h_name)) + holler ("Warning: inverse host lookup failed for %s: h_errno %d", + poop->addrs[x], h_errno); + else + (void) comparehosts (poop, hostent); + } /* for x -> addrs, part B */ + + } else { /* not INADDR_NONE: numeric addresses... */ + memcpy (poop->iaddrs, &iaddr, sizeof (IA)); + strncpy (poop->addrs[0], inet_ntoa (iaddr), sizeof (poop->addrs)); + if (numeric) /* if numeric-only, we're done */ + return (poop); + if (! o_verbose) /* likewise if we don't want */ + return (poop); /* the full DNS hair */ + hostent = gethostbyaddr ((char *) &iaddr, sizeof (IA), AF_INET); +/* numeric or not, failure to look up a PTR is *not* considered fatal */ + if (! hostent) + holler ("%s: inverse host lookup failed: h_errno %d", name, h_errno); + else { + strncpy (poop->name, hostent->h_name, MAXHOSTNAMELEN - 2); + hostent = gethostbyname (poop->name); + if ((! hostent) || (! hostent->h_addr_list[0])) + holler ("Warning: forward host lookup failed for %s: h_errno %d", + poop->name, h_errno); + else + (void) comparehosts (poop, hostent); + } /* if hostent */ + } /* INADDR_NONE Great Split */ + +/* whatever-all went down previously, we should now have a host_poop struct + with at least one IP address in it. */ +#ifndef WIN32 + h_errno = 0; +#endif + return (poop); +} /* gethostpoop */ + +/* getportpoop : + Same general idea as gethostpoop -- look up a port in /etc/services, fill + in global port_poop, but return the actual port *number*. Pass ONE of: + pstring to resolve stuff like "23" or "exec"; + pnum to reverse-resolve something that's already a number. + If o_nflag is on, fill in what we can but skip the getservby??? stuff. + Might as well have consistent behavior here... */ +USHORT getportpoop (pstring, pnum) + char * pstring; + unsigned int pnum; +{ + struct servent * servent; +#ifndef WIN32 + register int x; + register int y; +#else + u_short x; + u_short y; +#endif + char * whichp = p_tcp; + if (o_udpmode) + whichp = p_udp; + portpoop->name[0] = '?'; /* fast preload */ + portpoop->name[1] = '\0'; + +/* case 1: reverse-lookup of a number; placed first since this case is much + more frequent if we're scanning */ + if (pnum) { + if (pstring) /* one or the other, pleeze */ + return (0); + x = pnum; + if (o_nflag) /* go faster, skip getservbyblah */ + goto gp_finish; + y = htons (x); /* gotta do this -- see Fig.1 below */ + servent = getservbyport (y, whichp); + if (servent) { + y = ntohs (servent->s_port); + if (x != y) /* "never happen" */ + holler ("Warning: port-bynum mismatch, %d != %d", x, y); + strncpy (portpoop->name, servent->s_name, sizeof (portpoop->name)); + } /* if servent */ + goto gp_finish; + } /* if pnum */ + +/* case 2: resolve a string, but we still give preference to numbers instead + of trying to resolve conflicts. None of the entries in *my* extensive + /etc/services begins with a digit, so this should "always work" unless + you're at 3com and have some company-internal services defined... */ + if (pstring) { + if (pnum) /* one or the other, pleeze */ + return (0); + x = atoi (pstring); + if (x) + return (getportpoop (NULL, x)); /* recurse for numeric-string-arg */ + if (o_nflag) /* can't use names! */ + return (0); + servent = getservbyname (pstring, whichp); + if (servent) { + strncpy (portpoop->name, servent->s_name, sizeof (portpoop->name)); + x = ntohs (servent->s_port); + goto gp_finish; + } /* if servent */ + } /* if pstring */ + + return (0); /* catches any problems so far */ + +/* Obligatory netdb.h-inspired rant: servent.s_port is supposed to be an int. + Despite this, we still have to treat it as a short when copying it around. + Not only that, but we have to convert it *back* into net order for + getservbyport to work. Manpages generally aren't clear on all this, but + there are plenty of examples in which it is just quietly done. More BSD + lossage... since everything getserv* ever deals with is local to our own + host, why bother with all this network-order/host-order crap at all?! + That should be saved for when we want to actually plug the port[s] into + some real network calls -- and guess what, we have to *re*-convert at that + point as well. Fuckheads. */ + +gp_finish: +/* Fall here whether or not we have a valid servent at this point, with + x containing our [host-order and therefore useful, dammit] port number */ + sprintf (portpoop->anum, "%d", x); /* always load any numeric specs! */ + portpoop->num = (x & 0xffff); /* ushort, remember... */ + return (portpoop->num); +} /* getportpoop */ + +/* nextport : + Come up with the next port to try, be it random or whatever. "block" is + a ptr to randports array, whose bytes [so far] carry these meanings: + 0 ignore + 1 to be tested + 2 tested [which is set as we find them here] + returns a USHORT random port, or 0 if all the t-b-t ones are used up. */ +USHORT nextport (block) + char * block; +{ + register unsigned int x; + register unsigned int y; + + y = 70000; /* high safety count for rnd-tries */ + while (y > 0) { + x = (RAND() & 0xffff); + if (block[x] == 1) { /* try to find a not-done one... */ + block[x] = 2; + break; + } + x = 0; /* bummer. */ + y--; + } /* while y */ + if (x) + return (x); + + y = 65535; /* no random one, try linear downsearch */ + while (y > 0) { /* if they're all used, we *must* be sure! */ + if (block[y] == 1) { + block[y] = 2; + break; + } + y--; + } /* while y */ + if (y) + return (y); /* at least one left */ + + return (0); /* no more left! */ +} /* nextport */ + +/* loadports : + set "to be tested" indications in BLOCK, from LO to HI. Almost too small + to be a separate routine, but makes main() a little cleaner... */ +void loadports (block, lo, hi) + char * block; + USHORT lo; + USHORT hi; +{ + USHORT x; + + if (! block) + bail ("loadports: no block?!"); + if ((! lo) || (! hi)) + bail ("loadports: bogus values %d, %d", lo, hi); + x = hi; + while (lo <= x) { + block[x] = 1; + x--; + } +} /* loadports */ + +#ifdef GAPING_SECURITY_HOLE +char * pr00gie = NULL; /* global ptr to -e arg */ +#ifdef WIN32 +BOOL doexec(SOCKET ClientSocket); // this is in doexec.c +#else + +/* doexec : + fiddle all the file descriptors around, and hand off to another prog. Sort + of like a one-off "poor man's inetd". This is the only section of code + that would be security-critical, which is why it's ifdefed out by default. + Use at your own hairy risk; if you leave shells lying around behind open + listening ports you deserve to lose!! */ +doexec (fd) + int fd; +{ + register char * p; + + dup2 (fd, 0); /* the precise order of fiddlage */ +#ifdef WIN32 + shutdown(fd, SD_BOTH); /* Kirby */ + closesocket (fd); +#else + close (fd); /* is apparently crucial; this is */ +#endif + dup2 (0, 1); /* swiped directly out of "inetd". */ + dup2 (0, 2); + p = strrchr (pr00gie, '/'); /* shorter argv[0] */ + if (p) + p++; + else + p = pr00gie; +Debug (("gonna exec %s as %s...", pr00gie, p)) + execl (pr00gie, p, NULL); + bail ("exec %s failed", pr00gie); /* this gets sent out. Hmm... */ +} /* doexec */ +#endif +#endif /* GAPING_SECURITY_HOLE */ + +/* doconnect : + do all the socket stuff, and return an fd for one of + an open outbound TCP connection + a UDP stub-socket thingie + with appropriate socket options set up if we wanted source-routing, or + an unconnected TCP or UDP socket to listen on. + Examines various global o_blah flags to figure out what-all to do. */ +int doconnect (rad, rp, lad, lp) + IA * rad; + USHORT rp; + IA * lad; + USHORT lp; +{ +#ifndef WIN32 + register int nnetfd; +#endif + register int rr; + int x, y; + + errno = 0; +#ifdef WIN32 + WSASetLastError(0); +#endif +/* grab a socket; set opts */ + if (o_udpmode) + nnetfd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); + else + nnetfd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (nnetfd < 0) + bail ("Can't get socket"); + if (nnetfd == 0) /* might *be* zero if stdin was closed! */ + nnetfd = dup (nnetfd); /* so fix it. Leave the old 0 hanging. */ +#ifdef WIN32 + rr = setsockopt (nnetfd, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)setsockopt_c, sizeof (setsockopt_c)); +#else + x = 1; + rr = setsockopt (nnetfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x)); +#endif + if (rr == -1) + holler ("nnetfd reuseaddr failed"); /* ??? */ +#ifdef SO_REUSEPORT /* doesnt exist everywhere... */ +#ifdef WIN32 + rr = setsockopt (nnetfd, SOL_SOCKET, SO_REUSEPORT, &c, sizeof (c)); +#else + rr = setsockopt (nnetfd, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x)); +#endif + if (rr == -1) + holler ("nnetfd reuseport failed"); /* ??? */ +#endif + +/* fill in all the right sockaddr crud */ + lclend->sin_family = AF_INET; + remend->sin_family = AF_INET; + +/* if lad/lp, do appropriate binding */ + if (lad) + memcpy (&lclend->sin_addr.s_addr, lad, sizeof (IA)); + if (lp) + lclend->sin_port = htons (lp); + rr = 0; + if (lad || lp) { + x = (int) lp; +/* try a few times for the local bind, a la ftp-data-port... */ + for (y = 4; y > 0; y--) { + rr = bind (nnetfd, (SA *)lclend, sizeof (SA)); + if (rr == 0) + break; + if (errno != EADDRINUSE) + break; + else { + holler ("retrying local %s:%d", inet_ntoa (lclend->sin_addr), lp); + sleep (1); + errno = 0; /* clear from sleep */ + } /* if EADDRINUSE */ + } /* for y counter */ + } /* if lad or lp */ + if (rr) + bail ("Can't grab %s:%d with bind", + inet_ntoa(lclend->sin_addr), lp); + + if (o_listen) + return (nnetfd); /* thanks, that's all for today */ + + memcpy (&remend->sin_addr.s_addr, rad, sizeof (IA)); + remend->sin_port = htons (rp); + +/* rough format of LSRR option and explanation of weirdness. +-Option comes after IP-hdr dest addr in packet, padded to *4, and ihl > 5. +-IHL is multiples of 4, i.e. real len = ip_hl << 2. +- type 131 1 ; 0x83: copied, option class 0, number 3 +- len 1 ; of *whole* option! +- pointer 1 ; nxt-hop-addr; 1-relative, not 0-relative +- addrlist... var ; 4 bytes per hop-addr +- pad-to-32 var ; ones, i.e. "NOP" +- +-If we want to route A -> B via hops C and D, we must add C, D, *and* B to the +-options list. Why? Because when we hand the kernel A -> B with list C, D, B +-the "send shuffle" inside the kernel changes it into A -> C with list D, B and +-the outbound packet gets sent to C. If B wasn't also in the hops list, the +-final destination would have been lost at this point. +- +-When C gets the packet, it changes it to A -> D with list C', B where C' is +-the interface address that C used to forward the packet. This "records" the +-route hop from B's point of view, i.e. which address points "toward" B. This +-is to make B better able to return the packets. The pointer gets bumped by 4, +-so that D does the right thing instead of trying to forward back to C. +- +-When B finally gets the packet, it sees that the pointer is at the end of the +-LSRR list and is thus "completed". B will then try to use the packet instead +-of forwarding it, i.e. deliver it up to some application. +- +-Note that by moving the pointer yourself, you could send the traffic directly +-to B but have it return via your preconstructed source-route. Playing with +-this and watching "tcpdump -v" is the best way to understand what's going on. +- +-Only works for TCP in BSD-flavor kernels. UDP is a loss; udp_input calls +-stripoptions() early on, and the code to save the srcrt is notdef'ed. +-Linux is also still a loss at 1.3.x it looks like; the lsrr code is { }... +-*/ + + +/* if any -g arguments were given, set up source-routing. We hit this after + the gates are all looked up and ready to rock, any -G pointer is set, + and gatesidx is now the *number* of hops */ + if (gatesidx) { /* if we wanted any srcrt hops ... */ +/* don't even bother compiling if we can't do IP options here! */ +/* #ifdef IP_OPTIONS */ +#ifndef WIN32 + if (! optbuf) { /* and don't already *have* a srcrt set */ + char * opp; /* then do all this setup hair */ + optbuf = Hmalloc (48); + opp = optbuf; + *opp++ = IPOPT_LSRR; /* option */ + *opp++ = (char) + (((gatesidx + 1) * sizeof (IA)) + 3) & 0xff; /* length */ + *opp++ = gatesptr; /* pointer */ +/* opp now points at first hop addr -- insert the intermediate gateways */ + for ( x = 0; x < gatesidx; x++) { + memcpy (opp, gates[x]->iaddrs, sizeof (IA)); + opp += sizeof (IA); + } +/* and tack the final destination on the end [needed!] */ + memcpy (opp, rad, sizeof (IA)); + opp += sizeof (IA); + *opp = IPOPT_NOP; /* alignment filler */ + } /* if empty optbuf */ +/* calculate length of whole option mess, which is (3 + [hops] + [final] + 1), + and apply it [have to do this every time through, of course] */ + x = ((gatesidx + 1) * sizeof (IA)) + 4; + rr = setsockopt (nnetfd, IPPROTO_IP, IP_OPTIONS, optbuf, x); + if (rr == -1) + bail ("srcrt setsockopt fuxored"); +#else /* IP_OPTIONS */ + holler ("Warning: source routing unavailable on this machine, ignoring"); +#endif /* IP_OPTIONS*/ + } /* if gatesidx */ + +/* wrap connect inside a timer, and hit it */ + arm (1, o_wait); + if (setjmp (jbuf) == 0) { + rr = connect (nnetfd, (SA *)remend, sizeof (SA)); + } else { /* setjmp: connect failed... */ + rr = -1; +#ifdef WIN32 + WSASetLastError(WSAETIMEDOUT); /* fake it */ +#else + errno = ETIMEDOUT; /* fake it */ +#endif + } + arm (0, 0); + if (rr == 0) + return (nnetfd); +#ifdef WIN32 + errno = h_errno; + shutdown(nnetfd, 0x02); /* Kirby */ + closesocket (nnetfd); + WSASetLastError(errno); /* don't want to lose connect error */ +#else + close (nnetfd); /* clean up junked socket FD!! */ +#endif + return (-1); +} /* doconnect */ + +/* dolisten : + just like doconnect, and in fact calls a hunk of doconnect, but listens for + incoming and returns an open connection *from* someplace. If we were + given host/port args, any connections from elsewhere are rejected. This + in conjunction with local-address binding should limit things nicely... */ +int dolisten (rad, rp, lad, lp) + IA * rad; + USHORT rp; + IA * lad; + USHORT lp; +{ + register int nnetfd; + register int rr; + HINF * whozis = NULL; + int x; + char * cp; + USHORT z; + errno = 0; + +/* Pass everything off to doconnect, who in o_listen mode just gets a socket */ + nnetfd = doconnect (rad, rp, lad, lp); + if (nnetfd <= 0) + return (-1); + if (o_udpmode) { /* apparently UDP can listen ON */ + if (! lp) /* "port 0", but that's not useful */ + bail ("UDP listen needs -p arg"); + } else { + rr = listen (nnetfd, 1); /* gotta listen() before we can get */ + if (rr < 0) /* our local random port. sheesh. */ + bail ("local listen fuxored"); + } + +/* I can't believe I have to do all this to get my own goddamn bound address + and port number. It should just get filled in during bind() or something. + All this is only useful if we didn't say -p for listening, since if we + said -p we *know* what port we're listening on. At any rate we won't bother + with it all unless we wanted to see it, although listening quietly on a + random unknown port is probably not very useful without "netstat". */ + if (o_verbose) { + x = sizeof (SA); /* how 'bout getsockNUM instead, pinheads?! */ + rr = getsockname (nnetfd, (SA *) lclend, &x); + if (rr < 0) + holler ("local getsockname failed"); + strcpy (bigbuf_net, "listening on ["); /* buffer reuse... */ + if (lclend->sin_addr.s_addr) + strcat (bigbuf_net, inet_ntoa (lclend->sin_addr)); + else + strcat (bigbuf_net, "any"); + strcat (bigbuf_net, "] %d ..."); + z = ntohs (lclend->sin_port); + holler (bigbuf_net, z); + } /* verbose -- whew!! */ + +/* UDP is a speeeeecial case -- we have to do I/O *and* get the calling + party's particulars all at once, listen() and accept() don't apply. + At least in the BSD universe, however, recvfrom/PEEK is enough to tell + us something came in, and we can set things up so straight read/write + actually does work after all. Yow. YMMV on strange platforms! */ + if (o_udpmode) { + x = sizeof (SA); /* retval for recvfrom */ + arm (2, o_wait); /* might as well timeout this, too */ + if (setjmp (jbuf) == 0) { /* do timeout for initial connect */ + rr = recvfrom /* and here we block... */ + (nnetfd, bigbuf_net, BIGSIZ, MSG_PEEK, (SA *) remend, &x); +Debug (("dolisten/recvfrom ding, rr = %d, netbuf %s ", rr, bigbuf_net)) + } else + goto dol_tmo; /* timeout */ + arm (0, 0); +/* I'm not completely clear on how this works -- BSD seems to make UDP + just magically work in a connect()ed context, but we'll undoubtedly run + into systems this deal doesn't work on. For now, we apparently have to + issue a connect() on our just-tickled socket so we can write() back. + Again, why the fuck doesn't it just get filled in and taken care of?! + This hack is anything but optimal. Basically, if you want your listener + to also be able to send data back, you need this connect() line, which + also has the side effect that now anything from a different source or even a + different port on the other end won't show up and will cause ICMP errors. + I guess that's what they meant by "connect". + Let's try to remember what the "U" is *really* for, eh? +*/ + rr = connect (nnetfd, (SA *)remend, sizeof (SA)); + goto whoisit; + } /* o_udpmode */ + +/* fall here for TCP */ + x = sizeof (SA); /* retval for accept */ + arm (2, o_wait); /* wrap this in a timer, too; 0 = forever */ + if (setjmp (jbuf) == 0) { + rr = accept (nnetfd, (SA *)remend, &x); + } else + goto dol_tmo; /* timeout */ + arm (0, 0); +#ifdef WIN32 + shutdown(nnetfd, 0x02); /* Kirby */ + closesocket (nnetfd); +#else + close (nnetfd); /* dump the old socket */ +#endif + nnetfd = rr; /* here's our new one */ + +whoisit: + if (rr < 0) + goto dol_err; /* bail out if any errors so far */ + +/* Various things that follow temporarily trash bigbuf_net, which might contain + a copy of any recvfrom()ed packet, but we'll read() another copy later. */ + +/* If we can, look for any IP options. Useful for testing the receiving end of + such things, and is a good exercise in dealing with it. We do this before + the connect message, to ensure that the connect msg is uniformly the LAST + thing to emerge after all the intervening crud. Doesn't work for UDP on + any machines I've tested, but feel free to surprise me. */ +/* #ifdef IP_OPTIONS */ +#ifndef WIN32 + if (! o_verbose) /* if we wont see it, we dont care */ + goto dol_noop; + optbuf = Hmalloc (40); + x = 40; + rr = getsockopt (nnetfd, IPPROTO_IP, IP_OPTIONS, optbuf, &x); + if (rr < 0) + holler ("getsockopt failed"); +Debug (("ipoptions ret len %d", x)) + if (x) { /* we've got options, lessee em... */ + unsigned char * q = (unsigned char *) optbuf; + char * p = bigbuf_net; /* local variables, yuk! */ + char * pp = &bigbuf_net[128]; /* get random space farther out... */ + memset (bigbuf_net, 0, 256); /* clear it all first */ + while (x > 0) { + sprintf (pp, "%2.2x ", *q); /* clumsy, but works: turn into hex */ + strcat (p, pp); /* and build the final string */ + q++; p++; + x--; + } + holler ("IP options: %s", bigbuf_net); + } /* if x, i.e. any options */ +dol_noop: +#endif /* IP_OPTIONS */ + +/* find out what address the connection was *to* on our end, in case we're + doing a listen-on-any on a multihomed machine. This allows one to + offer different services via different alias addresses, such as the + "virtual web site" hack. */ + memset (bigbuf_net, 0, 64); + cp = &bigbuf_net[32]; + x = sizeof (SA); + rr = getsockname (nnetfd, (SA *) lclend, &x); + if (rr < 0) + holler ("post-rcv getsockname failed"); + strcpy (cp, inet_ntoa (lclend->sin_addr)); + + +/* now check out who it is. We don't care about mismatched DNS names here, + but any ADDR and PORT we specified had better fucking well match the caller. + Converting from addr to inet_ntoa and back again is a bit of a kludge, but + gethostpoop wants a string and there's much gnarlier code out there already, + so I don't feel bad. + The *real* question is why BFD sockets wasn't designed to allow listens for + connections *from* specific hosts/ports, instead of requiring the caller to + accept the connection and then reject undesireable ones by closing. */ + z = ntohs (remend->sin_port); + strcpy (bigbuf_net, inet_ntoa (remend->sin_addr)); + whozis = gethostpoop (bigbuf_net, o_nflag); + errno = 0; + x = 0; /* use as a flag... */ + if (rad) + if (memcmp (rad, whozis->iaddrs, sizeof (SA))) + x = 1; + if (rp) + if (z != rp) + x = 1; + if (x) /* guilty! */ + bail ("invalid connection to [%s] from %s [%s] %d", + cp, whozis->name, whozis->addrs[0], z); + holler ("connect to [%s] from %s [%s] %d", /* oh, you're okay.. */ + cp, whozis->name, whozis->addrs[0], z); + + return (nnetfd); /* open! */ + +dol_tmo: + errno = ETIMEDOUT; /* fake it */ +dol_err: +#ifdef WIN32 + shutdown(nnetfd, 0x02); /* Kirby */ + closesocket (nnetfd); +#else + close (nnetfd); +#endif + return (-1); +} /* dolisten */ + +/* udptest : + fire a couple of packets at a UDP target port, just to see if it's really + there. On BSD kernels, ICMP host/port-unreachable errors get delivered to + our socket as ECONNREFUSED write errors. On SV kernels, we lose; we'll have + to collect and analyze raw ICMP ourselves a la satan's probe_udp_ports + backend. Guess where could swipe the appropriate code from... + + Use the time delay between writes if given, otherwise use the "tcp ping" + trick for getting the RTT. [I got that idea from pluvius, and warped it.] + Return either the original fd, or clean up and return -1. */ +udptest (fd, where) + int fd; + IA * where; +{ + register int rr; + +#ifdef WIN32 + rr = send (fd, bigbuf_in, 1, 0); +#else + rr = write (fd, bigbuf_in, 1); +#endif + if (rr != 1) + holler ("udptest first write failed?! errno %d", errno); + if (o_wait) + sleep (o_wait); + else { +/* use the tcp-ping trick: try connecting to a normally refused port, which + causes us to block for the time that SYN gets there and RST gets back. + Not completely reliable, but it *does* mostly work. */ + o_udpmode = 0; /* so doconnect does TCP this time */ +/* Set a temporary connect timeout, so packet filtration doesnt cause + us to hang forever, and hit it */ + o_wait = 5; /* XXX: enough to notice?? */ + rr = doconnect (where, SLEAZE_PORT, 0, 0); + if (rr > 0) +#ifdef WIN32 + shutdown(fd, 0x02); /* Kirby */ + closesocket (rr); +#else + close (rr); /* in case it *did* open */ +#endif + o_wait = 0; /* reset it */ + o_udpmode++; /* we *are* still doing UDP, right? */ + } /* if o_wait */ + errno = 0; /* clear from sleep */ +#ifdef WIN32 + rr = send (fd, bigbuf_in, 1, 0); +#else + rr = write (fd, bigbuf_in, 1); +#endif + if (rr == 1) /* if write error, no UDP listener */ + return (fd); +#ifdef WIN32 + shutdown(fd, 0x02); /* Kirby */ + closesocket (fd); +#else + close (fd); /* use it or lose it! */ +#endif + return (-1); +} /* udptest */ + +/* oprint : + Hexdump bytes shoveled either way to a running logfile, in the format: +D offset - - - - --- 16 bytes --- - - - - # .... ascii ..... + where "which" sets the direction indicator, D: + 0 -- sent to network, or ">" + 1 -- rcvd and printed to stdout, or "<" + and "buf" and "n" are data-block and length. If the current block generates + a partial line, so be it; we *want* that lockstep indication of who sent + what when. Adapted from dgaudet's original example -- but must be ripping + *fast*, since we don't want to be too disk-bound... */ +void oprint (which, buf, n) + int which; + char * buf; + int n; +{ + int bc; /* in buffer count */ + int obc; /* current "global" offset */ + int soc; /* stage write count */ + register unsigned char * p; /* main buf ptr; m.b. unsigned here */ + register unsigned char * op; /* out hexdump ptr */ + register unsigned char * a; /* out asc-dump ptr */ + register int x; + register unsigned int y; + + if (! ofd) + bail ("oprint called with no open fd?!"); + if (n == 0) + return; + + op = stage; + if (which) { + *op = '<'; + obc = wrote_out; /* use the globals! */ + } else { + *op = '>'; + obc = wrote_net; + } + op++; /* preload "direction" */ + *op = ' '; + p = (unsigned char *) buf; + bc = n; + stage[59] = '#'; /* preload separator */ + stage[60] = ' '; + + while (bc) { /* for chunk-o-data ... */ + x = 16; + soc = 78; /* len of whole formatted line */ + if (bc < x) { + soc = soc - 16 + bc; /* fiddle for however much is left */ + x = (bc * 3) + 11; /* 2 digits + space per, after D & offset */ + op = &stage[x]; + x = 16 - bc; + while (x) { + *op++ = ' '; /* preload filler spaces */ + *op++ = ' '; + *op++ = ' '; + x--; + } + x = bc; /* re-fix current linecount */ + } /* if bc < x */ + + bc -= x; /* fix wrt current line size */ + sprintf (&stage[2], "%8.8x ", obc); /* xxx: still slow? */ + obc += x; /* fix current offset */ + op = &stage[11]; /* where hex starts */ + a = &stage[61]; /* where ascii starts */ + + while (x) { /* for line of dump, however long ... */ + y = (int)(*p >> 4); /* hi half */ + *op = hexnibs[y]; + op++; + y = (int)(*p & 0x0f); /* lo half */ + *op = hexnibs[y]; + op++; + *op = ' '; + op++; + if ((*p > 31) && (*p < 127)) + *a = *p; /* printing */ + else + *a = '.'; /* nonprinting, loose def */ + a++; + p++; + x--; + } /* while x */ + *a = '\n'; /* finish the line */ + x = write (ofd, stage, soc); + if (x < 0) + bail ("ofd write err"); + } /* while bc */ +} /* oprint */ + +#ifdef TELNET +USHORT o_tn = 0; /* global -t option */ + +/* atelnet : + Answer anything that looks like telnet negotiation with don't/won't. + This doesn't modify any data buffers, update the global output count, + or show up in a hexdump -- it just shits into the outgoing stream. + Idea and codebase from Mudge@l0pht.com. */ +void atelnet (buf, size) + unsigned char * buf; /* has to be unsigned here! */ + unsigned int size; +{ + static unsigned char obuf [4]; /* tiny thing to build responses into */ + register int x; + register unsigned char y; + register unsigned char * p; + + y = 0; + p = buf; + x = size; + while (x > 0) { + if (*p != 255) /* IAC? */ + goto notiac; + obuf[0] = 255; + p++; x--; + if ((*p == 251) || (*p == 252)) /* WILL or WONT */ + y = 254; /* -> DONT */ + if ((*p == 253) || (*p == 254)) /* DO or DONT */ + y = 252; /* -> WONT */ + if (y) { + obuf[1] = y; + p++; x--; + obuf[2] = *p; /* copy actual option byte */ +#ifdef WIN32 + (void) send (netfd, obuf, 3, 0); /* one line, or the whole buffer */ +#else + (void) write (netfd, obuf, 3); +#endif +/* if one wanted to bump wrote_net or do a hexdump line, here's the place */ + y = 0; + } /* if y */ +notiac: + p++; x--; + } /* while x */ +} /* atelnet */ +#endif /* TELNET */ + + +/* readwrite : + handle stdin/stdout/network I/O. Bwahaha!! -- the select loop from hell. + In this instance, return what might become our exit status. */ +int readwrite (fd) +#ifdef WIN32 + unsigned int fd; +#else + int fd; +#endif +{ + register int rr; + register unsigned char * zp; /* stdin buf ptr */ // changed to unsigned! [diegocr] + register unsigned char * np; /* net-in buf ptr */ // changed to unsigned! [diegocr] + unsigned int rzleft; + unsigned int rnleft; + USHORT netretry; /* net-read retry counter */ + USHORT wretry; /* net-write sanity counter */ + USHORT wfirst; /* one-shot flag to skip first net read */ + +#ifdef WIN32 /* (weld) WIN32 must poll because of weak stdin handling so we need a + short timer */ + struct timeval timer3; + int istty; + time_t start, current; + int foo; + + timer3.tv_sec = 0; + timer3.tv_usec = 1000; + + /* save the time so we can bail when we reach timeout */ + time( &start ); + + + /* sets stdin and stdout to binary so no crlf translation if its a tty */ + if (!_isatty( 1 )) + _setmode( 1, _O_BINARY ); + + if ((istty = _isatty( 0 )) == FALSE) + _setmode( 0, _O_BINARY ); /* (weld) I think we want to do this */ + +#endif + +/* if you don't have all this FD_* macro hair in sys/types.h, you'll have to + either find it or do your own bit-bashing: *ding1 |= (1 << fd), etc... */ +#ifndef WIN32 /* fd is not implemented as a real file handle in WIN32 */ + if (fd > FD_SETSIZE) { + holler ("Preposterous fd value %d", fd); + return (1); + } +#endif + FD_SET (fd, ding1); /* global: the net is open */ + netretry = 2; + wfirst = 0; + rzleft = rnleft = 0; + if (insaved) { + rzleft = insaved; /* preload multi-mode fakeouts */ + zp = bigbuf_in; + + wfirst = 1; + if (Single) /* if not scanning, this is a one-off first */ + insaved = 0; /* buffer left over from argv construction, */ + else { + FD_CLR (0, ding1); /* OR we've already got our repeat chunk, */ + close (0); /* so we won't need any more stdin */ + } /* Single */ + } /* insaved */ + + if (o_interval) + sleep (o_interval); /* pause *before* sending stuff, too */ + errno = 0; /* clear from sleep */ +#ifdef WIN32 + WSASetLastError(0); +#endif + +/* and now the big ol' select shoveling loop ... */ + while (FD_ISSET (fd, ding1)) { /* i.e. till the *net* closes! */ + wretry = 8200; /* more than we'll ever hafta write */ + if (wfirst) { /* any saved stdin buffer? */ + wfirst = 0; /* clear flag for the duration */ + goto shovel; /* and go handle it first */ + } + *ding2 = *ding1; /* FD_COPY ain't portable... */ + +/* some systems, notably linux, crap into their select timers on return, so + we create a expendable copy and give *that* to select. *Fuck* me ... */ + if (timer1) + memcpy (timer2, timer1, sizeof (struct timeval)); +#ifdef WIN32 /* (weld)we must use our own small timeval to poll */ + rr = select (16, ding2, 0, 0, &timer3); /* here it is, kiddies */ +#else + rr = select (16, ding2, 0, 0, timer2); /* here it is, kiddies */ +#endif + if (rr < 0) { +#ifdef WIN32 + if (h_errno != WSAEINTR) { /* might have gotten ^Zed, etc ?*/ +#else + if (errno != EINTR) { /* might have gotten ^Zed, etc ?*/ +#endif + foo = h_errno; + holler ("select fuxored"); +#ifdef WIN32 + shutdown(fd, 0x02); /* Kirby */ + closesocket (fd); +#else + close (fd); +#endif + return (1); + } + } /* select fuckup */ +/* if we have a timeout AND stdin is closed AND we haven't heard anything + from the net during that time, assume it's dead and close it too. */ +#ifndef WIN32 /* (weld) need to write some code here */ + if (rr == 0) { + if (! FD_ISSET (0, ding1)) + netretry--; /* we actually try a coupla times. */ + if (! netretry) { + if (o_verbose > 1) /* normally we don't care */ + holler ("net timeout"); + close (fd); + return (0); /* not an error! */ + } + } /* select timeout */ +#else + if (rr == 0) { + time( ¤t ); + if ( o_wait > 0 && (current - start) > timer1->tv_sec) { + if (o_verbose > 1) /* normally we don't care */ + holler ("net timeout"); + shutdown(fd, 0x02); /* Kirby */ + closesocket (fd); + FD_ZERO(ding1); + WSASetLastError(0); + return (0); /* not an error! */ + } + } /* select timeout */ +#endif +/* xxx: should we check the exception fds too? The read fds seem to give + us the right info, and none of the examples I found bothered. */ + +/* Ding!! Something arrived, go check all the incoming hoppers, net first */ + if (FD_ISSET (fd, ding2)) { /* net: ding! */ +#ifdef WIN32 + // reset timer + time( &start ); + + rr = recv (fd, bigbuf_net, BIGSIZ, 0); +#else + rr = read (fd, bigbuf_net, BIGSIZ); +#endif + if (rr <= 0) { + FD_CLR (fd, ding1); /* net closed, we'll finish up... */ + rzleft = 0; /* can't write anymore: broken pipe */ + } else { + rnleft = rr; + np = bigbuf_net; +#ifdef TELNET + if (o_tn) + atelnet (np, rr); /* fake out telnet stuff */ +#endif /* TELNET */ + } /* if rr */ +Debug (("got %d from the net, errno %d", rr, errno)) + } /* net:ding */ + +/* if we're in "slowly" mode there's probably still stuff in the stdin + buffer, so don't read unless we really need MORE INPUT! MORE INPUT! */ + if (rzleft) + goto shovel; + +/* okay, suck more stdin */ +#ifndef WIN32 + if (FD_ISSET (0, ding2)) { /* stdin: ding! */ + rr = read (0, bigbuf_in, BIGSIZ); + +/* xxx: maybe make reads here smaller for UDP mode, so that the subsequent + writes are smaller -- 1024 or something? "oh, frag it", etc, although + mobygrams are kinda fun and exercise the reassembler. */ + if (rr <= 0) { /* at end, or fukt, or ... */ + FD_CLR (0, ding1); /* disable and close stdin */ + close (0); + } else { + rzleft = rr; + zp = bigbuf_in; +/* special case for multi-mode -- we'll want to send this one buffer to every + open TCP port or every UDP attempt, so save its size and clean up stdin */ + if (! Single) { /* we might be scanning... */ + insaved = rr; /* save len */ + FD_CLR (0, ding1); /* disable further junk from stdin */ + close (0); /* really, I mean it */ + } /* Single */ + } /* if rr/read */ + } /* stdin:ding */ +#else + if (istty) { + /* (weld) cool, we can actually peek a tty and not have to block */ + /* needs to be cleaned up */ + if (kbhit()) { +/* bigbuf_in[0] = getche(); */ + gets(bigbuf_in); + strcat(bigbuf_in, "\n"); + rr = strlen(bigbuf_in); + rzleft = rr; + zp = bigbuf_in; +/* special case for multi-mode -- we'll want to send this one buffer to every + open TCP port or every UDP attempt, so save its size and clean up stdin */ + if (! Single) { /* we might be scanning... */ + insaved = rr; /* save len */ + close (0); /* really, I mean it */ + } + } + } else { + /* (weld) this is gonna block until a so it kinda sucks */ + rr = read (0, bigbuf_in, BIGSIZ); + if (rr <= 0) { /* at end, or fukt, or ... */ + close (0); + } else { + rzleft = rr; + zp = bigbuf_in; +/* special case for multi-mode -- we'll want to send this one buffer to every + open TCP port or every UDP attempt, so save its size and clean up stdin */ + if (! Single) { /* we might be scanning... */ + insaved = rr; /* save len */ + close (0); /* really, I mean it */ + } /* Single */ + } /* if rr/read */ + } + +#endif +shovel: +/* now that we've dingdonged all our thingdings, send off the results. + Geez, why does this look an awful lot like the big loop in "rsh"? ... + not sure if the order of this matters, but write net -> stdout first. */ + +/* sanity check. Works because they're both unsigned... */ + if ((rzleft > 8200) || (rnleft > 8200)) { + holler ("Preposterous Pointers: %d, %d", rzleft, rnleft); + rzleft = rnleft = 0; + } +/* net write retries sometimes happen on UDP connections */ + if (! wretry) { /* is something hung? */ + holler ("too many output retries"); + return (1); + } + if (rnleft) { +#ifdef WIN32 + int ggg=rnleft;while(ggg--)if(np[ggg] > 126)np[ggg] = '.'; // [diegocr] +#endif + rr = write (1, np, rnleft); + fflush(stdin); + if (rr > 0) { + if (o_wfile) + oprint (1, np, rr); /* log the stdout */ + np += rr; /* fix up ptrs and whatnot */ + rnleft -= rr; /* will get sanity-checked above */ + wrote_out += rr; /* global count */ + } +Debug (("wrote %d to stdout, errno %d", rr, errno)) + } /* rnleft */ + if (rzleft) { + if (o_interval) /* in "slowly" mode ?? */ + rr = findline (zp, rzleft); + else + rr = rzleft; +#ifdef WIN32 + rr = send (fd, zp, rr, 0); /* one line, or the whole buffer */ +#else + rr = write (fd, zp, rr); /* one line, or the whole buffer */ +#endif + if (rr > 0) { + zp += rr; + rzleft -= rr; + wrote_net += rr; /* global count */ + } +Debug (("wrote %d to net, errno %d", rr, errno)) + } /* rzleft */ + if (o_interval) { /* cycle between slow lines, or ... */ + sleep (o_interval); + errno = 0; /* clear from sleep */ + continue; /* ...with hairy select loop... */ + } + if ((rzleft) || (rnleft)) { /* shovel that shit till they ain't */ + wretry--; /* none left, and get another load */ + goto shovel; + } + } /* while ding1:netfd is open */ + +/* XXX: maybe want a more graceful shutdown() here, or screw around with + linger times?? I suspect that I don't need to since I'm always doing + blocking reads and writes and my own manual "last ditch" efforts to read + the net again after a timeout. I haven't seen any screwups yet, but it's + not like my test network is particularly busy... */ +#ifdef WIN32 + shutdown(fd, 0x02); /* Kirby */ + closesocket (fd); +#else + close (fd); +#endif + return (0); +} /* readwrite */ + +/* main : + now we pull it all together... */ +main (argc, argv) + int argc; + char ** argv; +{ +#ifndef HAVE_GETOPT + extern char * optarg; + extern int optind, optopt; +#endif + register int x; + register char *cp; + HINF * gp; + HINF * whereto = NULL; + HINF * wherefrom = NULL; + IA * ouraddr = NULL; + IA * themaddr = NULL; + USHORT o_lport = 0; + USHORT ourport = 0; + USHORT loport = 0; /* for scanning stuff */ + USHORT hiport = 0; + USHORT curport = 0; + char * randports = NULL; + int cycle = 0; + +#ifdef HAVE_BIND +/* can *you* say "cc -yaddayadda netcat.c -lresolv -l44bsd" on SunLOSs? */ + res_init(); +#endif +/* I was in this barbershop quartet in Skokie IL ... */ +/* round up the usual suspects, i.e. malloc up all the stuff we need */ + lclend = (SAI *) Hmalloc (sizeof (SA)); + remend = (SAI *) Hmalloc (sizeof (SA)); + bigbuf_in = Hmalloc (BIGSIZ); + bigbuf_net = Hmalloc (BIGSIZ); + ding1 = (fd_set *) Hmalloc (sizeof (fd_set)); + ding2 = (fd_set *) Hmalloc (sizeof (fd_set)); + portpoop = (PINF *) Hmalloc (sizeof (PINF)); + +#ifdef WIN32 + setsockopt_c = (char *)malloc(sizeof(char)); + *setsockopt_c = 1; +#endif + + errno = 0; + gatesptr = 4; +#ifndef WIN32 + h_errno = 0; +#endif +/* catch a signal or two for cleanup */ +#ifdef NTFIXTHIS + signal (SIGINT, catch); + signal (SIGQUIT, catch); + signal (SIGTERM, catch); + signal (SIGURG, SIG_IGN); +#endif + +recycle: + +/* if no args given at all, get 'em from stdin and construct an argv. */ + if (argc == 1) { + cp = argv[0]; + argv = (char **) Hmalloc (128 * sizeof (char *)); /* XXX: 128? */ + argv[0] = cp; /* leave old prog name intact */ + cp = Hmalloc (BIGSIZ); + argv[1] = cp; /* head of new arg block */ + fprintf (stderr, "Cmd line: "); + fflush (stderr); /* I dont care if it's unbuffered or not! */ + insaved = read (0, cp, BIGSIZ); /* we're gonna fake fgets() here */ + if (insaved <= 0) + bail ("wrong"); + x = findline (cp, insaved); + if (x) + insaved -= x; /* remaining chunk size to be sent */ + if (insaved) /* which might be zero... */ + memcpy (bigbuf_in, &cp[x], insaved); + cp = strchr (argv[1], '\n'); + if (cp) + *cp = '\0'; + cp = strchr (argv[1], '\r'); /* look for ^M too */ + if (cp) + *cp = '\0'; + +/* find and stash pointers to remaining new "args" */ + cp = argv[1]; + cp++; /* skip past first char */ + x = 2; /* we know argv 0 and 1 already */ + for (; *cp != '\0'; cp++) { + if (*cp == ' ') { + *cp = '\0'; /* smash all spaces */ + continue; + } else { + if (*(cp-1) == '\0') { + argv[x] = cp; + x++; + } + } /* if space */ + } /* for cp */ + argc = x; + } /* if no args given */ + +/* If your shitbox doesn't have getopt, step into the nineties already. */ +/* optarg, optind = next-argv-component [i.e. flag arg]; optopt = last-char */ + while ((x = getopt (argc, argv, "ade:g:G:hi:lLno:p:rs:tuvw:z")) != EOF) { +/* Debug (("in go: x now %c, optarg %x optind %d", x, optarg, optind)) */ + switch (x) { + case 'a': + bail ("all-A-records NIY"); + o_alla++; break; +#ifdef GAPING_SECURITY_HOLE + case 'e': /* prog to exec */ + pr00gie = optarg; + break; +#endif + case 'L': /* listen then cycle back to start instead of exiting */ + o_listen++; + cycle = 1; + break; + + + case 'd': /* detach from console */ + FreeConsole();; + break; + + + case 'G': /* srcrt gateways pointer val */ + x = atoi (optarg); + if ((x) && (x == (x & 0x1c))) /* mask off bits of fukt values */ + gatesptr = x; + else + bail ("invalid hop pointer %d, must be multiple of 4 <= 28", x); + break; + case 'g': /* srcroute hop[s] */ + if (gatesidx > 8) + bail ("too many -g hops"); + if (gates == NULL) /* eat this, Billy-boy */ + gates = (HINF **) Hmalloc (sizeof (HINF *) * 10); + gp = gethostpoop (optarg, o_nflag); + if (gp) + gates[gatesidx] = gp; + gatesidx++; + break; + case 'h': + errno = 0; +#ifdef HAVE_HELP + helpme(); /* exits by itself */ +#else + bail ("no help available, dork -- RTFS"); +#endif + case 'i': /* line-interval time */ + o_interval = atoi (optarg) & 0xffff; +#ifdef WIN32 + o_interval *= 1000; +#endif + if (! o_interval) + bail ("invalid interval time %s", optarg); + break; + case 'l': /* listen mode */ + o_listen++; break; + case 'n': /* numeric-only, no DNS lookups */ + o_nflag++; break; + case 'o': /* hexdump log */ + stage = (unsigned char *) optarg; + o_wfile++; break; + case 'p': /* local source port */ + o_lport = getportpoop (optarg, 0); + if (o_lport == 0) + bail ("invalid local port %s", optarg); + break; + case 'r': /* randomize various things */ + o_random++; break; + case 's': /* local source address */ +/* do a full lookup [since everything else goes through the same mill], + unless -n was previously specified. In fact, careful placement of -n can + be useful, so we'll still pass o_nflag here instead of forcing numeric. */ + wherefrom = gethostpoop (optarg, o_nflag); + ouraddr = &wherefrom->iaddrs[0]; + break; +#ifdef TELNET + case 't': /* do telnet fakeout */ + o_tn++; break; +#endif /* TELNET */ + + case 'u': /* use UDP */ + o_udpmode++; break; + case 'v': /* verbose */ + o_verbose++; break; + case 'w': /* wait time */ + o_wait = atoi (optarg); + if (o_wait <= 0) + bail ("invalid wait-time %s", optarg); + timer1 = (struct timeval *) Hmalloc (sizeof (struct timeval)); + timer2 = (struct timeval *) Hmalloc (sizeof (struct timeval)); + timer1->tv_sec = o_wait; /* we need two. see readwrite()... */ + break; + case 'z': /* little or no data xfer */ + o_zero++; + break; + default: + errno = 0; + bail ("nc -h for help"); + } /* switch x */ + } /* while getopt */ + +/* other misc initialization */ +#ifndef WIN32 /* Win32 doesn't like to mix file handles and sockets */ + Debug (("fd_set size %d", sizeof (*ding1))) /* how big *is* it? */ + FD_SET (0, ding1); /* stdin *is* initially open */ +#endif + if (o_random) { + SRAND (time (0)); + randports = Hmalloc (65536); /* big flag array for ports */ + } +#ifdef GAPING_SECURITY_HOLE + if (pr00gie) { + close (0); /* won't need stdin */ + o_wfile = 0; /* -o with -e is meaningless! */ + ofd = 0; + } +#endif /* G_S_H */ + if (o_wfile) { + ofd = open (stage, O_WRONLY | O_CREAT | O_TRUNC, 0664); + if (ofd <= 0) /* must be > extant 0/1/2 */ + bail ("can't open %s", stage); + stage = (unsigned char *) Hmalloc (100); + } + + +/* optind is now index of first non -x arg */ +Debug (("after go: x now %c, optarg %x optind %d", x, optarg, optind)) +/* Debug (("optind up to %d at host-arg %s", optind, argv[optind])) */ +/* gonna only use first addr of host-list, like our IQ was normal; if you wanna + get fancy with addresses, look up the list yourself and plug 'em in for now. + unless we finally implement -a, that is. */ + if (argv[optind]) + whereto = gethostpoop (argv[optind], o_nflag); + if (whereto && whereto->iaddrs) + themaddr = &whereto->iaddrs[0]; + if (themaddr) + optind++; /* skip past valid host lookup */ + errno = 0; +#ifndef WIN32 + h_errno = 0; +#endif + +/* Handle listen mode here, and exit afterward. Only does one connect; + this is arguably the right thing to do. A "persistent listen-and-fork" + mode a la inetd has been thought about, but not implemented. A tiny + wrapper script can handle such things... */ + if (o_listen) { + curport = 0; /* rem port *can* be zero here... */ + if (argv[optind]) { /* any rem-port-args? */ + curport = getportpoop (argv[optind], 0); + if (curport == 0) /* if given, demand correctness */ + bail ("invalid port %s", argv[optind]); + } /* if port-arg */ + netfd = dolisten (themaddr, curport, ouraddr, o_lport); +/* dolisten does its own connect reporting, so we don't holler anything here */ + if (netfd > 0) { +#ifdef GAPING_SECURITY_HOLE + if (pr00gie) /* -e given? */ + doexec (netfd); +#ifdef WIN32 + if (!pr00gie) // doexec does the read/write for win32 +#endif + +#endif /* GAPING_SECURITY_HOLE */ + x = readwrite (netfd); /* it even works with UDP! */ + if (o_verbose > 1) /* normally we don't care */ + holler (wrote_txt, wrote_net, wrote_out); + if (cycle == 1) + goto recycle; + exit (x); /* "pack out yer trash" */ + } else + bail ("no connection"); + } /* o_listen */ + +/* fall thru to outbound connects. Now we're more picky about args... */ + if (! themaddr) + bail ("no destination"); + if (argv[optind] == NULL) + bail ("no port[s] to connect to"); + if (argv[optind + 1]) /* look ahead: any more port args given? */ + Single = 0; /* multi-mode, case A */ + ourport = o_lport; /* which can be 0 */ + +/* everything from here down is treated as as ports and/or ranges thereof, so + it's all enclosed in this big ol' argv-parsin' loop. Any randomization is + done within each given *range*, but in separate chunks per each succeeding + argument, so we can control the pattern somewhat. */ + while (argv[optind]) { + hiport = loport = 0; + cp = strchr (argv[optind], '-'); /* nn-mm range? */ + if (cp) { + *cp = '\0'; + cp++; + hiport = getportpoop (cp, 0); + if (hiport == 0) + bail ("invalid port %s", cp); + } /* if found a dash */ + loport = getportpoop (argv[optind], 0); + if (loport == 0) + bail ("invalid port %s", argv[optind]); + if (hiport > loport) { /* was it genuinely a range? */ + Single = 0; /* multi-mode, case B */ + curport = hiport; /* start high by default */ + if (o_random) { /* maybe populate the random array */ + loadports (randports, loport, hiport); + curport = nextport (randports); + } + } else /* not a range, including args like "25-25" */ + curport = loport; +Debug (("Single %d, curport %d", Single, curport)) + +/* Now start connecting to these things. curport is already preloaded. */ + while (loport <= curport) { + if ((! o_lport) && (o_random)) { /* -p overrides random local-port */ + ourport = (RAND() & 0xffff); /* random local-bind -- well above */ + if (ourport < 8192) /* resv and any likely listeners??? */ + ourport += 8192; /* xxx: may still conflict; use -s? */ + } + curport = getportpoop (NULL, curport); + netfd = doconnect (themaddr, curport, ouraddr, ourport); +Debug (("netfd %d from port %d to port %d", netfd, ourport, curport)) + if (netfd > 0) + if (o_zero && o_udpmode) /* if UDP scanning... */ + netfd = udptest (netfd, themaddr); + if (netfd > 0) { /* Yow, are we OPEN YET?! */ + x = 0; /* pre-exit status */ + holler ("%s [%s] %d (%s) open", + whereto->name, whereto->addrs[0], curport, portpoop->name); +#ifdef GAPING_SECURITY_HOLE + if (pr00gie) /* exec is valid for outbound, too */ + doexec (netfd); +#endif /* GAPING_SECURITY_HOLE */ + if (! o_zero) +#ifdef WIN32 +#ifdef GAPING_SECURITY_HOLE + if (!pr00gie) // doexec does the read/write for win32 +#endif +#endif + x = readwrite (netfd); /* go shovel shit */ + } else { /* no netfd... */ + x = 1; /* preload exit status for later */ +/* if we're scanning at a "one -v" verbosity level, don't print refusals. + Give it another -v if you want to see everything. */ +#ifdef WIN32 + if ((Single || (o_verbose > 1)) || (h_errno != WSAECONNREFUSED)) +#else + if ((Single || (o_verbose > 1)) || (errno != ECONNREFUSED)) +#endif + holler ("%s [%s] %d (%s)", + whereto->name, whereto->addrs[0], curport, portpoop->name); + } /* if netfd */ +#ifdef WIN32 + shutdown(netfd, 0x02); /* Kirby */ + closesocket (netfd); /* just in case we didn't already */ +#else + close (netfd); /* just in case we didn't already */ +#endif + if (o_interval) + sleep (o_interval); /* if -i, delay between ports too */ + if (o_random) + curport = nextport (randports); + else + curport--; /* just decrement... */ + } /* while curport within current range */ + optind++; + } /* while remaining port-args -- end of big argv-ports loop*/ + + errno = 0; + if (o_verbose > 1) /* normally we don't care */ + holler ("sent %d, rcvd %d", wrote_net, wrote_out); + +#ifdef WIN32 + WSACleanup(); +#endif + + if (cycle == 1) + goto recycle; + + if (Single) + exit (x); /* give us status on one connection */ + exit (0); /* otherwise, we're just done */ + return(0); +} /* main */ + +#ifdef HAVE_HELP /* unless we wanna be *really* cryptic */ +/* helpme : + the obvious */ +int helpme() +{ + o_verbose = 1; + holler ("[v1.11 NT www.rodneybeede.com/]\n\ +connect to somewhere: nc [-options] hostname port[s] [ports] ... \n\ +listen for inbound: nc -l -p port [options] [hostname] [port]\n\ +options:"); + holler ("\ + -d detach from console, background mode\n"); + +#ifdef GAPING_SECURITY_HOLE /* needs to be separate holler() */ + holler ("\ + -e prog inbound program to exec [dangerous!!]"); +#endif + holler ("\ + -g gateway source-routing hop point[s], up to 8\n\ + -G num source-routing pointer: 4, 8, 12, ...\n\ + -h this cruft\n\ + -i secs delay interval for lines sent, ports scanned\n\ + -l listen mode, for inbound connects\n\ + -L listen harder, re-listen on socket close\n\ + -n numeric-only IP addresses, no DNS\n\ + -o file hex dump of traffic\n\ + -p port local port number\n\ + -r randomize local and remote ports\n\ + -s addr local source address"); +#ifdef TELNET + holler ("\ + -t answer TELNET negotiation"); +#endif + holler ("\ + -u UDP mode\n\ + -v verbose [use twice to be more verbose]\n\ + -w secs timeout for connects and final net reads\n\ + -z zero-I/O mode [used for scanning]"); + bail ("port numbers can be individual or ranges: m-n [inclusive]"); + return(0); +} /* helpme */ +#endif /* HAVE_HELP */ + + + + +/* None genuine without this seal! _H*/ diff --git a/netcat.o b/netcat.o new file mode 100755 index 0000000000000000000000000000000000000000..24bea0fed17ca9c66e25fc06f9b135fb87cacbdd GIT binary patch literal 42323 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 literal 0 HcmV?d00001 diff --git a/readme.rodneybeede.txt b/readme.rodneybeede.txt new file mode 100755 index 0000000..ec9da96 --- /dev/null +++ b/readme.rodneybeede.txt @@ -0,0 +1,17 @@ +This version was compiled without the -e (GAPING_SECURITY_HOLE) option which can trigger anti-virus programs false positives. + + +makewin.cmd is the script that was used to compile. + + +Build Environment: + Gcc 3.4.5 (MinGW version 5.1.4) + Windows 7 Ultimate 64-bit RC build 7100 + + +Original NT version comes from http://joncraton.org/blog/46#disqus_thread + + +Rodney Beede +http://www.rodneybeede.com/ +contactme@rodneybeede.com \ No newline at end of file diff --git a/readme.txt b/readme.txt new file mode 100755 index 0000000..32fd642 --- /dev/null +++ b/readme.txt @@ -0,0 +1,155 @@ + +UPDATE 12/27/04 security fix in -e option for Windows + +Netcat 1.11 for NT - nc111nt.zip + +The original version of Netcat was written by *hobbit* +The NT version was done by Weld Pond + +Netcat for NT is the tcp/ip "Swiss Army knife" that never made it into any +of the resource kits. It has proved to be an extremely versatile tool on +the unix platform. So why should NT always be unix's poor cousin when it +comes to tcp/ip testing and exploration? I bet many NT admins out there +keep a unix box around to use tools such as Netcat or to test their systems +with the unix version of an NT vulnerability exploit. With Netcat for NT +part of that feeling disempowerment is over. + +Included with this release is Hobbit's original description of the powers +of Netcat. In this document I will briefly describe some of the things an +NT admin might want to do and know about with Netcat on NT. For more +detailed technical information please read hobbit.txt included in the +nc11nt.zip archive. + + Basic Features + + * Outbound or inbound connections, TCP or UDP, to or from any ports + * Full DNS forward/reverse checking, with appropriate warnings + * Ability to use any local source port + * Ability to use any locally-configured network source address + * Built-in port-scanning capabilities, with randomizer + * Can read command line arguments from standard input + * Slow-send mode, one line every N seconds + * Hex dump of transmitted and received data + * Ability to let another program service established + connections + * Telnet-options responder + + New for NT + + * Ability to run in the background without a console window + * Ability to restart as a single-threaded server to handle a new + connection + + +A simple example of using Netcat is to pull down a web page from a web +server. With Netcat you get to see the full HTTP header so you can see +which web server a particular site is running. + +Since NT has a rather anemic command processor, some of the things that are +easy in unix may be a bit more clunky in NT. For the web page example first +create a file get.txt that contains the following line and then a blank +line: + +GET / HTTP/1.0 + +To use Netcat to retrieve the home page of a web site use the command: +nc -v www.website.com 80 < get.txt + +You will see Netcat make a connection to port 80, send the text contained +in the file get.txt, and then output the web server's response to stdout. +The -v is for verbose. It tells you a little info about the connection +when it starts. + +It is a bit easier to just open the connection and then type at the console +to do the same thing. +nc -v www.website.com 80 + +Then just type in GET / HTTP/1.0 and hit a couple of returns. You will +see the same thing as above. + +A far more exciting thing to do is to get a quick shell going on a remote +machine by using the -l or "listen" option and the -e or "execute" +option. You run Netcat listening on particular port for a connection. +When a connection is made, Netcat executes the program of your choice +and connects the stdin and stdout of the program to the network connection. + +nc -l -p 23 -t -e cmd.exe + +will get Netcat listening on port 23 (telnet). When it gets connected to +by a client it will spawn a shell (cmd.exe). The -t option tells Netcat +to handle any telnet negotiation the client might expect. + +This will allow you to telnet to the machine you have Netcat listening on +and get a cmd.exe shell when you connect. You could just as well use +Netcat instead of telnet: + +nc xxx.xxx.xxx.xxx 23 + +will get the job done. There is no authentication on the listening side +so be a bit careful here. The shell is running with the permissions of the +process that started Netcat so be very careful. If you were to use the +AT program to schedule Netcat to run listening on a port with the +-e cmd.exe option, when you connected you would get a shell with user +NT AUTHORITY\SYSTEM. + +The beauty of Netcat really shines when you realize that you can get it +listening on ANY port doing the same thing. Do a little exploring and +see if the firewall you may be behind lets port 53 through. Run Netcat +listening behind the firewall on port 53. + +nc -L -p 53 -e cmd.exe + +Then from outside the firewall connect to the listening machine: + +nc -v xxx.xxx.xxx.xx 53 + +If you get a command prompt then you are executing commands on the +listening machine. Use 'exit' at the command prompt for a clean +disconnect. The -L (note the capital L) option will restart Netcat with +the same command line when the connection is terminated. This way you can +connect over and over to the same Netcat process. + +A new feature for the NT version is the -d or detach from console flag. +This will let Netcat run without an ugly console window cluttering up the +screen or showing up in the task list. + +You can even get Netcat to listen on the NETBIOS ports that are probably +running on most NT machines. This way you can get a connection to a +machine that may have port filtering enabled in the TCP/IP Security Network +control panel. Unlike Unix, NT does not seem to have any security around +which ports that user programs are allowed to bind to. This means any +user can run a program that will bind to the NETBIOS ports. + +You will need to bind "in front of" some services that may already be +listening on those ports. An example is the NETBIOS Session Service that +is running on port 139 of NT machines that are sharing files. You need +to bind to a specific source address (one of the IP addresses of the +machine) to accomplish this. This gives Netcat priority over the NETBIOS +service which is at a lower priority because it is bound to ANY IP address. +This is done with the Netcat -s option: + +nc -v -L -e cmd.exe -p 139 -s xxx.xxx.xxx.xxx + +Now you can connect to the machine on port 139 and Netcat will field +the connection before NETBIOS does. You have effectively shut off +file sharing on this machine by the way. You have done this with just +user privileges to boot. + +PROBLEMS with Netcat 1.1 for NT + +There are a few known problems that will eventually be fixed. One is +the -w or timeout option. This works for final net reads but not +for connections. Another problem is using the -e option in UDP mode. +You may find that some of the features work on Windows 95. Most +of the listening features will not work on Windows 95 however. These will +be fixed in a later release. + +Netcat is distributed with full source code so that people can build +upon this work. If you add something useful or discover something +interesting about NT TCP/IP let met know. + +Weld Pond , 2/2/98 + + + +