FROM: NETWORKSHOP
SKILL LEVEL: AGILE
Introduction
socat is a powerful UNIX command-line tool for crafting, sending and receiving network packets. Once understood it can be used to prototype client-server designs, probing and fuzzing remote machines, data-transfer and even proxy traffic from one host to another.
NOTE: the below examples use socat to move data around networks in the open, with no encryption in place. With this in mind you should only use socat to move data of a volatile nature over a trusted VPN or using socat’s SSL options. To move data around securely on networks you don’t control you are better to use ssh and scp (section coming soon).
Installing socat
Installing socat on Linux systems
Most Linux distributions provide socat in their repositories.
To install it on a Debian-based Linux system (most distributions, including Ubuntu, CrunchBang and Debian itself) do the following:
sudo apt-get install socat
To install socat on a RedHat system, do as follows:
sudo yum -y install socat
Installing socat on OS X
Mac OS X users should download the latest version of socat from http://www.dest-unreach.org/socat/ and compile it as follows (here we use socat-1.7.2.4.tar.gz as an example).
Unpack the archive:
tar xvzf socat-1.7.2.4.tar.gz
Change to the newly created directory and configure the source for compilation:
cd socat-1.7.2.4
./configure
Compile the source:
make
Install it:
sudo make install
Examples
Send a UDP packet to a remote host
Here we send a UDP packet with a string in its payload to port 2001 on remote host 20.21.22.23.
We can pass socat our string with echo over a UNIX pipe:
echo "SO MANY BEDS, WITH PHONES NEXT TO HEADS" | socat - UDP4-DATAGRAM:20.21.22.23:2001
Send data to a remote host, logging to a file
In this example we start socat on the remote host, telling it to listen for connections on port 3333. Each time it receives a connection it will execute cat, redirecting and appending (‘>>’) received input as output into the file /tmp/log.txt:
REMOTE HOST
socat tcp-l:3333,reuseaddr,fork system:'cat >> /tmp/log.txt',nofork
Now on our client machine we echo a string over a UNIX pipe to socat, which then sends it within a TCP packet to the remote host example.net on port 3333:
LOCAL HOST
echo "I CAN SEE INTO YOUR KITCHEN FROM HERE" | socat - TCP4:example.net:3333
Send a UDP packet to a remote host, hitting every port (packet protest)
Here we use a range in bash, the most popular UNIX shell, to send to ports incrementing from 1001 to 65535 on the remote domain nsa.gov, sleeping for 1/10th of a second in between. Please note this is very network-noisy.
for PORT in {1001..65535}; do echo "READ YOUR CONSTITUTION, NOT OUR EMAIL." | socat - UDP4-DATAGRAM:nsa.gov:$PORT; sleep .1; done
Execute commands on a remote host, viewing command output locally
socat can be used to trigger system calls and shell scripts on the remote host. Used this way socat effectively replaces netcat and remote command execution with ssh (albeit without encryption) and affords the user great flexibility.
In the following example we execute the command ls -lt on the remote host, outputting standard output to our shell on the local machine. This can be very useful if you want to monitor the contents of a directory on a server or other remote machine. Importantly, the commands executed will not appear in the remote user’s shell history.
First we start socat on the remote server (example.net) on an arbitrary port (3333), executing the specified command each time a packet is received:
REMOTE HOST
socat tcp-l:3333,reuseaddr,fork system:'ls -lt',nofork
Note that the reuseaddr option keeps socat in a listening state rather than exiting after each call, while fork will spawn a new child-process each time it’s called.
LOCAL HOST
Now on the client we send our packet to example.net:
socat - TCP4:example.net:3333
Output from the remotely executed ls -lt command will appear in the local shell.
Naturally the output from the remote command can be logged to a local file, like so:
socat - TCP4:example.net:3333 >> log.txt
Monitoring the display of a remote computer
In this example we’ll use socat and command line tools to take a screen-grab on a remote machine that has a graphical display, retrieving the file to a local directory. This can be a useful way of monitoring remote machines with desktop environments.
REMOTE HOST
Linux and OS X have different command line tools for screencapture. If the remote machine runs Linux we’d use scrot. If OS X, screencapture. For this example we’ll use Linux as it’s the OS most used on embedded computers (like the BeagleBone Black and Raspberry Pi) and servers.
CAP=scrot # Linux
# CAP=screencapture # OS X
On the remote machine (on a LAN or Internet), we start our capture command.
socat tcp-l:3333,reuseaddr,fork system:'s=cap.png; $CAP $s; cat $s'
The above command can be left running, a server that will take a screen-grab whenever we ask for it.
LOCAL (‘MONITORING’) HOST
Now on our local monitoring machine we’ll create a folder for our screen grabs:
mkdir Screengrabs
Now we tell socat to send a TCP packet to trigger and retrieve the capture on our local monitoring machine.
socat - TCP4:example.net:3333 > Screengrabs/$(date +%Y-%m-%d_%H-%M-%S).png
This will produce a PNG file whose file name inherits a date/time form (eg.2014-05-08_21-49-51.png) in the Screengrabs directory.
AUTOMATION
The capture trigger and retrieval command can be easily automated to ask for a screen-grab every few seconds:
#!/bin/bash
# remote-grab.sh - Remote screengrab trigger and retrieval script.
# Use with *socat* command on a Linux or OS X remote host with graphical display:
# CAP=scrot # For Linux
# CAP=screencapture # For OS X
# PORT=3333
# socat tcp-l:$PORT,reuseaddr,fork system:'s=cap.png; $CAP $s; cat $s'
# Vars
REMOTE='example.net' # A variable for the remote host we're monitoring
PORT=3333 # Define a port (be sure it matches that of the server)
DIR=~/Screengrabs # A variable for a directory that will hold our screen-grabs
POLL=10 # A variable for our poll interval, in seconds
# Check the directory for our screen-grabs exists. If not, create it.
if [ ! -d $DIR ]
then
mkdir $DIR
fi
# Simple loop
while true
do
# A variable for our file name that calls *date*
FN=$(date +%Y-%m-%d_%H-%M-%S).png
# Send a TCP packet on port 3333 to trigger capture and retrieval
socat - TCP4:$REMOTE:$PORT > $DIR/$FN
echo "Retrieved $FN and wrote it to $DIR"
# Get some rest
sleep $POLL
done
Copy out the file to remote-grab.sh and set it to executable:
chmod +x remote-grab.sh
Run it like so:
./remote-grab.sh