⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netcat.c

📁 一个nc的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
}



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
  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 :

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -