My-Tiny.Net :: Networking with Virtual Machines



Netcat


#!/bin/bash
cat <<'EOF' |nc $1 $2 
:                   :
:    /\_/\          :
:   / 0 0 \         :
:  ====v==== Netcat :
:   \  W  /   ____  :
:    |   |   /      :
:   / ___ \  |      :
:  / /   \ \-'      :
: (((-----)))       :
:                   :
EOF
The developer says ( http://nc110.sourceforge.net/ )
Netcat is 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. Netcat, or "nc" as the actual program is named, should have been supplied long ago as another one of those cryptic but standard Unix tools.

Netcat tries its best to behave just like "cat". It 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, and sent to the target host. 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 how this behaviour is different from most other applications which shut everything down and exit after an end-of-file on the standard input.
In the simplest usage, nc host port creates a TCP connection to the given port on the given target host. The host argument can be a name or IP address. A port argument is required for outbound connections, and can be numeric or a name as listed in /etc/services. Netcat can bind to any local port, subject to privilege restrictions and ports that are already in use.

Netcat can also function as a server, by listening for an inbound connection on an arbitrary port and then doing the same reading and writing.

Ctrl c will make netcat close the network connection and exit.

Netcat is a core component of some backdoors, so many sysadmins keep a sharp eye on who it is available to and how it is used. But hey - we display the root password for every login, so never mind!

One important thing to know is that there are three versions out there: Classic, GNU, and BSD. Tinynet hosts have Classic (nc) and BSD (bsdnc) available. GNU has pretty much the same capabilities as Classic netcat, but the BSD variant has some useful additions. The BSD version is also the one most people document, without saying so. The main differences are in the command arguments:
  • Listening for connections: With the Classic version, you have to specify the port using -p, where the -p modifier in the BSD version changes the source port.
  • Run as a background process: the BSD version has the -d option for this, where the Classic version requires some tricks to keep netcat from exiting if it cannot read immediately from stdin.
  • Keep the connection listening after a client quits: The BSD version has the -k option for this, where using the Classic version you have to try something like
    echo -n | nc -l -v -p 23434 | bash mklist.sh &
    or
    tail -f /dev/null | nc -l -v -p 23434 | bash mklist.sh &
Outside of this, some versions (but never BSD) will have a -c or -e switch to execute a command after connecting - in the Classic netcat source, written by *Hobbit*, this is the GAPING_SECURITY_HOLE compile option. It is easy to do this with any version using a named pipe, so we'll come back to it later.

Bottom line is: be sure to use -h to see what switches you have available.

Check man nc and man bsdnc for more; the NetCat Cheat Sheet from www.sans.org is also quite good.

Put a message in a log file

A "UNIX-domain socket" is an internal interprocess communication mechanism that uses the same system call libraries as the network stack. In simple terms, a TCP/IP socket allows communication between processes over the network: a listening TCP socket is identified by a local port and possibly local IP. A unix domain socket (or just "unix socket") allows communication between processes running on the same machine. Lots of listening sockets live in the filesystem hierarchy and access to them can be controlled by filesystem permissions.

We can list our listening network ports with netstat -tulp
and list our unix sockets with netstat -ap --unix or lsof -U
where type STREAM is equivalent to a TCP network socket and type DGRAM is equivalent to a UDP network socket.
In a file listing, ls -l /run for example, the unix sockets have  s  a the beginning of their permissions list.
To see all of the unix sockets in the filesystem: find / -type s |grep -v 'postfix' (leave the postfix ones off the list - is uses a lot!)

Classic netcat can only connect to network sockets, but the BSD version has -U for connecting to a STREAM socket and -uU for connecting to a DGRAM socket.

The syslog daemon listens on the UNIX-domain datagram socket /dev/log to collect messages from other processes and write them to the proper log file based on the facility and priority included in the message. Long story short, the command to add a line to the file for messages with facility kern and priority error (/var/log/messages by default) is

   echo "<3>$0[$$]: --- IM IN UR BASE PLUTIN UR LAWGZ ---" | bsdnc -uU -w 1 /dev/log  

where $0 is the name of the shell or shell script and $$ is the process id (pid) of the current shell. The number between the angle brackets < > is the syslog Facility and Priority encoded into a single number - see the Quick Reference :: Syslog Codes page on the menu for a handy table. Or even better, use /usr/local/bin/msg2syslog with facility priority "message"
(facility and priority must be names in UPPERCASE).

Netcat Listener

Start with two hosts, a listener [endpoint] and a source [sender].

Netcat expects to have ports connected and active so it can immediately send its stdin across the socket. That means we need to get netcat listening on the [endpoint] first. We use bsdnc because -lk makes it easy to reconnect, with -v to show a "Connection Accepted" message:    bsdnc -lkv 23432

Now switch to your [sender] host, have the name or ip of your end.point.host handy, and type in
echo "logged in as: $(whoami)" |nc end.point.host 23432

then use Up Arrow and change it to
echo "current directory: $PWD" |nc end.point.host 23432

then use Up Arrow and cycle through these two commands once more. Switch to your [endpoint] to see the outcome.

Use Ctrl c on the [endpoint] to exit netcat.

Netcat and Named Pipes

"Round tripping" named pipes is where things get interesting. We will do this exercise in two virtual terminals on the TinyNet Gateway or MailHost, but it works the same on two different hosts, as long as the named pipes are created on the listener [endpoint] host.

If you did not do this before (see the Named Pipes section in the Redirection page under Standard I/O on the menu), make the named pipe we will use with the command mkfifo /tmp/piper

In one virtual terminal (VT):

nc -l -p 23432 < /tmp/piper | tee /dev/stderr | nc localhost 587 |tee /tmp/piper

and in another VT: nc 127.0.0.1 23432

Type the "telnet mail" commands (from Configure Mail::Testing on the menu) in the VT with the short nc command. Then switch to the listener VT to see both sides of the connection there too!! The first trick is tee sends output to both the screen (stderr) and nc (stdout), and the second is using the named pipe to catch input from both sides of the conversation.

Use Ctrl c in the listener VT to exit netcat. If you want to do this across the network, just make sure the named pipes are created on the listener [endpoint] host, use the name or IP of a mailserver instead of localhost in the middle of the listener command, and use the name or IP of the listener host instead of 127.0.0.1 to connect.

While this exercise does not seem too sensible with just two VTs, you have to remember that you see your own interactive session in one VT, while other is eavesdropping on the conversation and recording it - quite useful for debugging!

The script below enhances this idea by using two background processes to modify the data in the pipes. sed is the "stream editor", a powerful tool that uses regular expressions to filter input: in this case we have a simple regular expression to change the beginning of each line, adding directional arrows for each message. It also uses mktemp and trap to clean up the FIFOs when it ends (be sure to take a look at the man pages!)

This script is /usr/local/sbin/piper.sh
     #!/bin/sh -e
     if [ $# != 3 ]; then
        echo "usage: $0 [src-port] [dst-host] [dst-port]"
        exit 0
     fi

     TMP=$(mktemp -d)                # safely create a temporary directory
     BACK=$TMP/pipe.back
     SENT=$TMP/pipe.sent             # make the fifo names
     RCVD=$TMP/pipe.rcvd

     mkfifo -m 0600 $BACK $SENT $RCVD     # make the fifos 
     trap 'rm -rf "$TMP"' EXIT            # clean up at exit

     sed 's/^/ => /' <$SENT &             # edit the streams
     sed 's/^/ <= /' <$RCVD &

     nc -l -p $1 <$BACK | tee $SENT | nc $2 $3 | tee $RCVD >$BACK

# run this script in one VT with (for example)    ./piper 23432 localhost 25
# and in another one run    nc 127.0.0.1 23432    and type your email dialog

# thanks to:
# https://notes.tweakblogs.net/blog/7955/using-netcat-to-build-a-simple-tcp-proxy-in-linux.html


Final Note

Windows also has "named pipes", but they behave differently. On Windows the thing called a named pipe is an interprocess communication (IPC) object where things can flow both ways and there is some metadata (you can obtain the credentials of the thing on the other end, etc.). They need to be opened with a special system call, after which they behave mostly like a normal win32 handle. Unix has a thing called a "Unix socket" or AF_UNIX socket which, being bidirectional, works more like (but not exactly like) a win32 "named pipe".


Special Parameters in the Bash shell
    $0        the name of the shell or shell script
    $1 $2 $3  ... the positional parameters
    $#        the number of positional parameters
    "$@"      an array of the positional parameters, {$1, $2, $3 ...}
    $IFS      the (input) field separator.
    "$*"      the IFS expansion of the positional parameters, $1 $2 $3 ...

    $$        PID of the current shell (not subshell)
    $!        PID of the most recent background command
    $?        most recent foreground pipeline exit status

trap is a function built into the shell that defines and activates handlers
      to be run when the shell receives signals or other special conditions.

From the man page:

ARG is a command to be read and executed when the shell receives the signal(s) SIGNAL_SPEC.
If ARG is absent (and a single SIGNAL_SPEC is supplied) or ARG is a dash ("-"), 
   each specified signal is reset to its original value. 
If ARG is the null string, each SIGNAL_SPEC is ignored by the shell and by the commands it invokes.

If a SIGNAL_SPEC is EXIT (0), ARG is executed upon exit from the shell.
If a SIGNAL_SPEC is DEBUG, ARG is executed before every simple command.
If a SIGNAL_SPEC is RETURN, ARG is executed each time a shell function or a script 
   run by the "." or source built-in commands finishes executing.
A SIGNAL_SPEC of ERR means to execute ARG each time a command's failure 
   would cause the shell to exit when the -e option is enabled.

If no arguments are supplied, trap prints the list of commands associated with each signal. 

EXAMPLE
       trap 'rm -f /tmp/xyz$$; exit' ERR EXIT
Set a trap which, on shell error or shell exit, deletes a temporary file xyz$$.