Keeping a record of all of the commands you type as well as their output is obviously useful during a forensic investigation. On Unix and Linux systems, we have the "script" command which does precisely this. You run "script <filename>" and the script command spawns a new shell: everything you type and all output you receive in return is automatically captured to the specified file.
From a forensic perspective, however, the classic problem is that script insists on writing its output to a file in the local file system. This is particularly a problem during the initial stages of incident response when you're operating on a live system trying to verify whether or not it has been compromised. If you capture your session with the script command, you may be trampling important data as your output file grows. Of course you could attach a portable storage device and write your output there, but that could be problematic on many levels.
This topic came up recently when Ed Skoudis and I were working on an article for our Command Line Kung Fu blog (a useful resource for Incident Response professionals, since we provide helpful command line short-cuts using both the Windows and Unix command shells). During our conversation, I realized that there might be a work-around that allows the script command to send its output over the network. Sure enough, after a little bit of hacking I came up with a devious little method to accomplish exactly this.
Suppose we had another machine on the same network as the host we are investigating. Let's suppose this other machine has IP address 192.168.100.1 and there's a netcat process listening on port 9999 and redirecting its output to some file ("nc -l 9999 >myoutput"). Now, on the machine you're investigating, run the following commands:
$ mkfifo /tmp/fifo $ cat /tmp/fifo >/dev/tcp/192.168.100.1/9999 & [1] 1523 $ script -f /tmp/fifo Script started, file is /tmp/fifo $
Some explanation is clearly in order here:
- The mkfifo command creates a special type of object in the file system called a FIFO (short for "first in, first out"). The FIFO allows one command to write data into this "file" and another command to read data out of it. This is perfect for our purposes.
- The next command uses the cat to read data out of the FIFO and redirect that output into /dev/tcp/192.168.100.1/9999. This "file name" is a specially recognized syntax in the bash shell that means "write the data over the network to host 192.168.100.1 on port 9999/tcp" (for more information see Ed's excellent "Netcat Without Netcat" presentation). We use "&" to put this command in the background where it will sit and wait for us to start putting data into the FIFO.
- Finally we fire up the script command and tell it to write its data into the FIFO. We also add the "-f" ("flush") argument so that the script command doesn't buffer its output- the remote side will see the commands being typed and get the output instantly. We're now in the subshell spawned by the script command and anything that happens from here on out should start appearing in the output file on the remote system.
The "/dev/tcp/..." syntax is a useful little bit of bash shell trickery. But even if you didn't have this, you could do something similar if your incident response kit included netcat. Just change the second command in the output above to
cat /tmp/fifo | nc 192.168.100.1 9999
The real trick here is obviously knowing how to create and manipulate FIFOs, and for whatever reason this doesn't seem to be something that's commonly covered in most Unix classes. But you have to admit it's an impressively useful thing to know for situations such as this when you have a command like script that insists only on writing to a local "file".
Obviously, on principles of strict forensic soundness it must be admitted that creating the FIFO does alter the file system slightly. The FIFO itself requires an inode, though no data blocks will be consumed. Also the contents of the directory the FIFO is placed in will be modified. However, I will point out that many Unix systems are configured by default to use memory-based file systems for directories such as /tmp or /var/run. If this is the case on the system you're investigating, I would recommend creating your FIFO in one of these memory-based file systems to minimize any impact to the file system on disk.
Hope you find this little trick useful in future investigations!
Hal Pomeranz, Deer Run Associates, is an independent IT/Computer Security consultant and a SANS Faculty Fellow. He spends far too much time hanging out in the sketchy parts of the Unix operating system.