How to send binary data in netcat to an already established connection?
I can do the following to send binary data in netcat:
echo -e '\x80' | nc host port
But I don't want to do it like this, what I want is to connect to a server:
nc 192.168.1.115 12345
And then send some text:
aaaaaaaaaabbbbbbbbbbccccccccccc
And then send some binary data:
0x80 0xF4 0x12
How can I do that?
Solution 1:
Note: while following this solution, type commands in a single shell session (or use a single script) unless said otherwise. This is because it uses variables and file descriptors, they are not directly available outside their original session.
Create a temporary fifo. The right way to create a temporary file is with mktemp
. Unfortunately it cannot create fifos. It can create a temporary directory though:
tmpd=`mktemp -d`
tmpf="$tmpd"/fifo
mkfifo "$tmpf"
printf "%s\n" "$tmpf" # just to know the path to the fifo, it may be useful later
Alternatively you can create a named fifo by hand in some fixed or ad-hoc location. It's up to you.
Create a background process that will read the fifo and pass data to a server:
nc 192.168.1.115 12345 < "$tmpf" &
ncpid=$! # PID may be useful later
Pay attention if nc
doesn't exit prematurely. Assuming there's no problem with the connection itself nor the server, the above background command will stay connected until you finish sending the first bunch of data through the fifo. But you want it to stay open and accept multiple writes, so open the fifo and don't close it (yet):
exec 3> "$tmpf"
Now you can send whatever you like through the fifo and the background connection persists:
echo abcd >&3 # sends text
echo -e '\x80' >&3 # sends "binary"
cat /etc/issue >&3 # sends file
cat >&3 # type whatever you want, terminate with Ctrl+D
Any of this commands can be invoked with the path to the fifo instead of &3
, if only you know the path. Knowing the path, you can write to the fifo from the same or another shell session:
cat > /path/to/the/fifo # type whatever you want, terminate with Ctrl+D
Or you can open a descriptor in another session in a similar manner like in the original one. Whatever way you write to the fifo, the nc
will pass it to the remote server in a single connection.
But beware of race conditions. Using a single descriptor inside a single shell session is a good way to avoid them.
After you pass whatever data you need, terminate the nc
and close the descriptor in the original shell session:
kill $ncpid
exec 3>&-
Note in some circumstances the sole latter command is enough to make the background nc
exit; it depends on what you did and what you are still doing with the fifo. For this reason I chose to kill the nc
explicitly.
Remove the temporary directory and its content (i.e. the fifo):
rm -r "$tmpd"
Final note:
It's not necessary to put nc
into background in the first place. You can run it in one terminal, write to the fifo (knowing its path) from another one. This way you can easily monitor its state. Tailor this solution to your needs.
Solution 2:
The following seems to work:
while read -r; do echo -en "$REPLY" | nc ...; done
This allows you to include \xNN
escape sequences with your normal data, as in:
aaaaaaaaaabbbbbbbbbbccccccccccc\x80\xF4\x12
Remember to double any literal \
characters in your text input. Note that the use of read -r
and $REPLY
instead of a variable stops the stripping of leading and trailing blanks.
This doesn't add a new-line to the end of the buffer, so you need either to omit the n
option from the echo
command or to type \x0a
where you want a new-line.
I can't set up nc
at present, but I have tested with:
while read -r; do echo -en "$REPLY" | cat | xxd; done
For testing, you can use od -ct x1
if you don't have xxd
; or use od -c
if you are happy to see binary characters in octal. You can omit cat |
from the pipe: I included it as possibly a better simulation of the use of nc
.
Solution 3:
You can get help from a named pipe to do it, with a little trick:
remote$ nc -v -n -l -p 8888 > /tmp/data
Listening on [0.0.0.0] (family 0, port 8888)
Connection from 10.0.3.1 47108 received!
local:1$ mkfifo /tmp/fifo
local:1$ nc -v -n <>/tmp/fifo 10.0.3.66 8888
Connection to 10.0.3.66 8888 port [tcp/*] succeeded!
It's important to open the fifo read-write (or else have an other neutral process like sleep 9999 >/tmp/fifo
keeping it opened for writing) else the first (end of) write done will end netcat's read loop. Hence the <>
.
local:2$ echo aaaaaaaaaabbbbbbbbbbccccccccccc > /tmp/fifo
local:2$ cat /bin/ls > /tmp/fifo # sends the binary contents of the file /bin/ls, which would probably garble the input or output
local:2$ cat > /tmp/fifo
Some more interactive text
(local:1$ )
^C
remote$ od -c /tmp/data|head -4
0000000 a a a a a a a a a a b b b b b b
0000020 b b b b c c c c c c c c c c c \n
0000040 177 E L F 002 001 001 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000060 003 \0 > \0 001 \0 \0 \0 0 T \0 \0 \0 \0 \0 \0