📄 netcat.c
字号:
}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; rr = write (fd, zp, rr); /* one line, or the whole buffer */ if (rr > 0) { if (o_wfile) oprint (0, zp, rr); /* log what got sent */ 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... */ close (fd); 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;#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)); errno = 0; gatesptr = 4; h_errno = 0;/* catch a signal or two for cleanup */ signal (SIGINT, catch); signal (SIGQUIT, catch); signal (SIGTERM, catch);/* and suppress others... */#ifdef SIGURG signal (SIGURG, SIG_IGN);#endif#ifdef SIGPIPE signal (SIGPIPE, SIG_IGN); /* important! */#endif/* if no args given at all, get 'em from stdin, construct an argv, and hand anything left over to readwrite(). */ 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, "ae:g:G:hi:lno: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 '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; 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 */Debug (("fd_set size %d", sizeof (*ding1))) /* how big *is* it? */ FD_SET (0, ding1); /* stdin *is* initially open */ 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; h_errno = 0;/* 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-arg? */ 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);#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); exit (x); /* "pack out yer trash" */ } else /* if no netfd */ 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; /* if it *still* conflicts, 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) 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. */ if ((Single || (o_verbose > 1)) || (errno != ECONNREFUSED)) holler ("%s [%s] %d (%s)", whereto->name, whereto->addrs[0], curport, portpoop->name); } /* if netfd */ close (netfd); /* just in case we didn't already */ 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 (wrote_txt, wrote_net, wrote_out); if (Single) exit (x); /* give us status on one connection */ exit (0); /* otherwise, we're just done */} /* main */#ifdef HAVE_HELP /* unless we wanna be *really* cryptic *//* helpme : the obvious */helpme(){ o_verbose = 1; holler ("[v1.10]\n\connect to somewhere: nc [-options] hostname port[s] [ports] ... \n\listen for inbound: nc -l -p port [-options] [hostname] [port]\n\options:");/* sigh, this necessarily gets messy. And the trailing \ characters may be interpreted oddly by some compilers, generating or not generating extra newlines as they bloody please. u-fix... */#ifdef GAPING_SECURITY_HOLE /* needs to be separate holler() */ holler ("\ -e prog program to exec after connect [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\ -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: lo-hi [inclusive]");} /* helpme */#endif /* HAVE_HELP *//* None genuine without this seal! _H*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -