Shell Monitoring: 

Using A Modified Script Utility

Ryan C. Barnett
RCBarnett@Hushmail.com


  1. Modified Script for Monitoring Shells
    1. Scope
    2. Tool Description
      1. Script Details
    3. Test Apparatus
    4. Environmental Conditions
    5. Description of Procedures
      1. Question 1 - How do we force shell sessions into the script command?
        1. Modifying the script C source code
      2. Question 2 - How do we log the shell sessions remotely?
      3. Question 3 - Is Syslogd the best transport method?
      4. Question 4 - How can I transfer the files securely?
      5. Question 5 - How can we verify the integrity of the data?
      6. Question 6 - How can we capture all login shells?
      7. Question 7 - How can we capture non-login shells?
      8. Question 8 - How can we force interactive, non-login shells into our script?
    6. Criteria for Approval
    7. Data and Results
      1. Insider Threat
      2. The Honeypot Compromise
    8. Analysis
    9. Presentation
    10. Conclusion
    11. Additional Info
    12. Script Source Code
      1. Solaris Script Code
      2. HPUX Script Code
      3. IRIX Script Code

Modified Script for Monitoring Shells

Shell Session Monitoring with Modified “script” Command:
This section will describe both the implementation and use of a modified version of the Unix “script” command which will aid in capturing Blackhat shell sessions on either a compromised honeypot system or a live production system.  This implementation could be used in the following scenarios: Scope:
In order to capture not only Blackhat keystrokes on my honeypot system, but entire shell sessions, I have come up with a method to force all user shells on the system into a modified version the typical Unix script command.  I have edited the script C source code, for both Redhat Linux 6.2 and Solaris 8, to make the shell sessions logging stealthy and to transfer the logging data to a remote host.  This implementation allows me to have a complete log of the attacker’s shell session while they are unaware of the monitoring.

During live incident response engagements, this implementation could be used to "wiretap" individual system accounts who have been identified as malicious.  This would allow the incident response team to utilize a shell session monitoring mechanism which is both easy to implement and analyze the resulting data quickly.

The scope if this test will be to show how to implement, configure and then test the use of this modified script technique for capturing shell sessions.

Tool Description:
One of the Honeynet Project’s biggest obstacles has been developing effective methods of Data Capture on Honeypot Systems.   The following excerpts are taken from the Honeynet Project’s paper entitled “Know Your Enemy: Honeynets” located on the Projects website - http://project.honeynet.org/papers/honeynet/ -
 
Data Capture
Data capture is the capturing of all of the blackhat's activities. It is these activities that are then analyzed to learn the tools, tactics, and motives of the blackhat community. The challenge is to capture as much data as possible, without the blackhat knowing their every action is captured. This is done with as few modifications as possible, if any, to the honeypots. Also, data captured cannot be stored on locally on the honeypot. Information stored locally can potentially be detected by the blackhat, alerting them the system is a Honeynet. The stored data can also be lost or destroyed. Not only do we have to capture the blackhats every move without them knowing, but we have to store the information remotely…

--CUT--

A second method to capturing system data is to modify the system to capture keystrokes and screen shots and remotely forward that data. The Honeynet Project is currently testing several tools that have this functionality. The first is a modified version of bash. This shell, developed by Antonomasia, can be used to replace the system binary /bin/bash. The trojaned shell forwards the user's keystrokes to syslogd, which is then forwarded to a remote syslog server. A second option is a modified version of TTY Watcher. This kernel module captures both user keystrokes and screen captures and forward this information over a non-standard TCP connection. There are a variety of other options to this functionality…

You may be asking yourself, “Why do you need to have host-based session logging if you already have all of these network based monitoring tools?”  Relying only on network based monitoring tools does capture the vast majority of keystrokes that are sent to a honeypot, either in the initial scans, probes, exploits and/or during the subsequent illegal sessions.  The need for additional monitoring tools and host-based monitoring methods has grown due to changes in the attacker’s transport channels, specifically, the use of encrypted channels to access compromised systems.  More and more attacker are including Secure Shell (SSH) servers within their rootkits.  These encrypted channels essentially leave the network monitoring mechanisms blinded from clear text that would have been passed along the wire via telnet and ftp.  There are some newer possibilities for “snooping in” on encrypted channels such as SSH (I.E.- using sshmitm from the dsniff tools suite), however, it is no piece of cake to implement effectively within a typical Honeynet environment.  This technique would only work if the attacker would use your trojaned SSH server to access the honeypot.  Playing “Man in the Middle” monitoring tricks is focusing on the transport of the attacker’s session, rather than the goal of the attacker, which is the root shell itself.  This leads us to complimenting the existing network based monitoring tools with host based solutions.

The techniques discussed in the Honeynet paper above are very effective.  The only shortcoming of the modified bash shell is that it only shows the attacker’s keystrokes and nothing else.  It does not show the output from these commands.  Here is an example of a honeypot syslog session while using the modified bash shell mentioned above –
 
Mar 16 08:47:05 asdf1 -bash: HISTORY: PID=4172 UID=0 ls
Mar 16 08:47:45 asdf1 -bash: HISTORY: PID=4172 UID=0 mkdir /var/...
Mar 16 08:47:46 asdf1 -bash: HISTORY: PID=4172 UID=0 ls
Mar 16 08:48:29 asdf1 -bash: HISTORY: PID=4172 UID=0 cd /var/...
Mar 16 08:48:32 asdf1 -bash: HISTORY: PID=4172 UID=0 ftp ftp.home.ro
Mar 16 08:54:35 asdf1 -bash: HISTORY: PID=4172 UID=0 tar -zxvf emech-2.8.tar.gz
Mar 16 08:54:39 asdf1 -bash: HISTORY: PID=4172 UID=0 cd emech-2.8
Mar 16 08:54:44 asdf1 -bash: HISTORY: PID=4172 UID=0 ./configure
Mar 16 08:55:04 asdf1 -bash: HISTORY: PID=4172 UID=0 y
Mar 16 08:55:29 asdf1 -bash: HISTORY: PID=4172 UID=0 make

This is essentially forwarding a bash history file to a remote host via the Syslog daemon.  Don’t get me wrong this is tremendously useful information.  The only shortcoming is that you cannot see “exactly” what the attacker saw.  For example, in the 3rd line from the syslog file above, the attacker had just created a hidden directory within /var called  “…” (dot dot dot).  He then issued an “ls” to get a directory listing.  Wouldn't it be nice if you could see what other files were located within this directory?  Also, in line number 5, the attacker used FTP to connect to a remote server.  The bash history file does not show any information about this session.  What was the username that attacker used on the FTP host?  What other files were on this host?  That information would be even more valuable to an investigator than just relying on the bash history information.

This brings us to the method that I would like to introduce.  This method includes using a modified version of the typical Unix “script” command to capture not only the attacker’s keystrokes, but also all text displayed to their screen including STDIN/OUT/ERR.  Instead of seeing only keystrokes, this technique will give the Forensic Investigator an "Over the Shoulder" view of an attacker's shell session.

Script Details
Forensic Investigators have long relied on the Unix “script” command for use as an audit record of their activities on a compromised host.  The script command essentially captures all data that is displayed on the terminal screen and saves this record to a file upon the exit of the script session.  The MAN page for the script command is rather short so I will include it here –
 
SCRIPT(1)                   System Reference Manual                  SCRIPT(1)

NAME

     script - make typescript of terminal session

SYNOPSIS

     script [-a] [-f] [-q] [-t] [file]

DESCRIPTION

     Script makes a typescript of everything printed on your terminal.  It is
     useful for students who need a hardcopy record of an interactive session
     as proof of an assignment, as the typescript file can be printed out lat-
     er with lpr(1).

     If the argument file is given, script saves all dialogue in file. If no
     file name is given, the typescript is saved in the file typescript.

     Options:

     -a      Append the output to file or typescript, retaining the prior con-
             tents.

     -f      Flush output after each write. This is nice for telecooperation:
             One person does `mkfifo foo; script -f foo' and another can su-
             pervise real-time what is being done using `cat foo'.

     -q      Be quiet.

     -t      Output timeing data to standard error. This data contains two
             fields, separated by a space. The first field indicates how much
             time elapsed since the previous output. The second field indi-
             cates how many characters were output this time. This information
             can be used to replay typescripts with realistic typing and out-
             put delays.

     The script ends when the forked shell exits (a control-D to exit the
     Bourne shell (sh(1)),  and exit, logout or control-d (if ignoreeof is not
     set) for the C-shell, csh(1)).

     Certain interactive commands, such as vi(1),  create garbage in the type-
     script file.  Script works best with commands that do not manipulate the
     screen, the results are meant to emulate a hardcopy terminal.

ENVIRONMENT

     The following environment variable is utilized by script:

     SHELL  If the variable SHELL exists, the shell forked by script will be
            that shell. If SHELL is not set, the Bourne shell is assumed.
            (Most shells set this variable automatically).

SEE ALSO

     csh(1) (for the history mechanism).

HISTORY

     The script command appeared in 3.0BSD.

BUGS

     Script places everything in the log file, including linefeeds and
     backspaces.  This is not what the naive user expects.

 Linux                           July 30, 2000                               1

The script command has proven to be a very valuable tool for documenting actions taken by Forensic Analysts while investigating compromised systems.  It wasn't until I started focusing on different ways to implement keystroke/session logging on honeypots, as opposed to logging forensic sessions, that I came back to this interesting utility.

The complete set of tools and applications for this test is as follows:


Test Apparatus:
The testing was conducted on a closed network.  The network consisted of one Windows 2000 Workstation, which was the VMWare Host OS machine.  There was one RedHat Linux Guest OS machines on the Windows 2000 Workstation.  There was also two SUN Microsystems SUNBlade 100 Workstations on the test network.  The machines were connected by a CableTron Systems Multi Port Repeater with LANVIEW- MR9T 802.3 10BaseT.  Since this test was conducted on a closed network, the possibility for outside network interference was minimized.  The test environment used for these tests was:



Environmental Conditions:
The testing was conducted on a closed network.  The machines were connected by a CableTron Systems Multi Port Repeater with LANVIEW- MR9T 802.3 10BaseT.  Since this test was conducted on a closed network, the possibility for outside network interference was minimized.

Test Network

Description of the procedures --
Testing Phase:
There are two main issues to deal with in regards to host based keystroke/session monitoring:

  1. Hide the monitoring from the attacker
  2. Ensuring the integrity of the data that is captured
We will use these two rules to guide our implementations.

Question 1 - How do we force shell sessions into the script command?
An attacker will certainly not choose to enter a script session, so we must come up with a way to FORCE them into this session.  We would also like this to happen behind the scenes, so the attacker does not get suspicious.  In order to accomplish this task, I analyzed the normal system login procedure looking for a way to tripwire a normal user account into using the standard Linux script utility.  Here is an overview, from the Bash MAN page, for the different ways that a shell can be invoked: (All bolded lines within Pseudo Terminals are either commands executed or important entries)
 
INVOCATION

A login shell is one whose first character of argument zero is a -, or one started with the --login option. 

An interactive shell is one started without non-option arguments and without the -c option whose standard input and output are both connected to terminals (as determined by isatty(3)), or one started with the -i option. PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state. 

The following paragraphs describe how bash executes its startup files. If any of the files exist but cannot be read, bash reports an error. Tildes are expanded in file names as described below under Tilde Expansion in the EXPANSION section. 

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior. 

When a login shell exits, bash reads and executes commands from the file ~/.bash_logout, if it exists. 
 

This means that if I can add some lines of text to the user's home .bash_profile, I should be able to rediect them into my modified script session.  I ran an strace on the process of spawning a login shell and looked for places to tripwire.  The strace log file shows that when root executes the following command "# /bin/sh -login", the Bash Shell will try and emulate the Bourne Shell as much as possible and it will eventually read the user's ~/.profile.  This is a potential place to put our booby-trap.
 
[root@saphe3 rbarnett]# strace -o test1 /bin/sh -login
bash# exit
[root@saphe3 rbarnett]# less test1
execve("/bin/sh", ["/bin/sh", "-login"], [/* 24 vars */]) = 0
brk(0)                                  = 0x80994a0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40014000
open("/etc/ld.so.preload", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 4

-- CUT --

rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
open("/root/.profile", O_RDONLY)        = -1 ENOENT (No such file or directory)
stat("/var/spool/mail/root", 0xbffff990) = -1 ENOENT (No such file or directory)
time(NULL)                              = 1024334534
open("/root/.bash_history", O_RDONLY)   = 3
 

On our Linux systems we have symbolically linked the normal Bourne Shell (/bin/sh) to point to the Bash Shell.  This means that, for this scenario, we need to consider what shell our potential attacker might use.  Since the vast majority of scripted attacks use the most common /bin/sh shell, we will need to focus on thisshell as well as Bash.

Note - All data that is updated within the ~/.bash_profile file, in the following examples, should be copied and renamed to the ~/.profile name so that it will catch all access attempts for the Bourne Shell.

During this analysis, I decided that the user's home ~/.bash_profile would be the best place to conduct some testing.  I updated the appropriate login files (.profile, etc…) within the home directories of all system users.  I added the following lines to their ~/.bash_profile –
 
[root@saphe3 rbarnett]# cat ./.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
 . ~/.bashrc
fi

# User specific environment and startup programs
PATH=$PATH:$HOME/bin
BASH_ENV=$HOME/.bashrc
USERNAME=""

export USERNAME BASH_ENV PATH

exec /usr/bin/script /tmp/shell_log.` date +'%Y-%m-%d:%H:%M:%S' `.$$ 
#Thanks to Brian Hatch for the date stamp/PID logging idea

This configuration allowed for the normal login procedures of the system -> telnet -> login -> /etc/profile -> ~/.profile.  At this point in the login process, the user has already authenticated, the system wide profiles have been applied and the user’s .profile has been applied all the way until the 2nd to last line in the file “/usr/bin/script /tmp/shell_log.` date +'%Y-%m-%d:%H:%M:%S' `.$$.  The user is never actually dropped into their normal shell.  The normal .profile process is suspended and they are instead put into a script session, with the session log being saved in the shell_log.date... file in the /tmp/ directory.  It is important to designate a directory where the user has WRITE access, otherwise, the script session will error out.

A nice additional feature of this implementation is that even if the user spawned a different sub-shell (I.E. issued “$/bin/csh” to go to the C Shell) while within the script session, script would appropriately fork and log that sub-shell as well.  Whatever the end user sees, is what is logged.  When the user typed either “exit” or “Ctrl+D” to exit, they were then placed back into the suspended .profile process, which then logs them off the system.  It is very important that the script command be executed with "exec", otherwise, the user would then be dropped into a normal shell and thus all of the script logging would stop.  This process worked great during my testing phase to log all of the normal system user sessions.  In addition to the text of the session, the beginning and end of the file included the normal date stamps of the session.

There was one drawback however.  This new session logging mechanism was not hidden from the user and they knew that something suspicious was going on.  When they logged in, the were dutifully greeted with the normal Linux script session output (Bolded) –
 
Script started, file is /tmp/shell_log.2002-08-15:14:05:13.18752

$ls

file1 file2 file3

$exit

Script done, file is /tmp/shell_log.2002-08-15:14:05:13.18752

This banner information announced to the user that they were in fact in the script session instead of a normal shell.  If this method of keystroke/session monitoring was to be utilized on a live honeypot, these announcement messages from the script utility needed to be removed or altered.  This is in accordance with Rule #1 of honeypot keystroke/session monitoring - Hide the monitoring from the attacker.

Modifying the Script C Code:
In order to suppress the normal script status messages, I needed to edit the source code of the script command.  I searched on the Web for the source code for this program and found it within the utils-linux-2.11n.tar.gz file.  I edited the file script.c and made the following changes (diff changes are piped through ediff for better readability ) to remove the Banner Messages –
 
# diff script.c.orig script.c | ediff

-------- 1 line changed at 178 from:
                printf(_("Script started, file is %s\n"), fname);
-------- to:
                printf(_(""), fname);     /*We got rid of the default script announcement messages.  The script is now invoked without fanfare.*/
 

-------- 1 line changed at 333 from:
                        printf(_("Script done, file is %s\n"), fname);
-------- to:
                        printf(_(""), fname);   /*This is where we got rid of the normal exit announcements from script.*/

-------- 1 line added at 396:

When compiling this new version of the script command, I edited the default Makefile and added in the "-static" flag for compiling.  Here is an excerpt from the new Makefile entry with the new "-static" flag bolded:
 
# For script only
LIBPTY=
ifeq "$(HAVE_OPENPTY)" "yes"
LIBPTY:=$(LIBPTY) -lutil -static
endif

We then run make to create the new binary.  The resulting compiled script binary was then statically linked, and therefore, would not need to access and system shared libraries.
 
[root@saphe3 misc-utils]# pwd
/mnt/util-linux-2.11n/misc-utils
[root@saphe3 misc-utils]# make
cc -s script.o -o script  -lutil -static
[root@saphe3 misc-utils]# file ./script
./script: ELF 32-bit LSB executable, Intel 80386, version 1, statically linked, stripped
[root@saphe3 misc-utils]# cp ./script /usr/bin/bash_check

I then renamed this file to the less conspicuous name "bash_check" and placed it in the /usr/bin directory.  Next, I updated the ~/.bash_profile file to execute the new bash_check file instead of the real script command.  I have moved the execution of the script further up into the normal ~/.bash_profile settings.  This is used for camouflaging the script execution.  Note: Script will read the environment setting of “SHELL” to execute during the script session.  Therefore, if you want the script sessions to log to bash (since this might log commands in the ~/.bash_history file), you should specify it within the “SHELL=” settings in the ~/.bash_profile and make sure that it comes before the script command.  I then tested it and it worked perfectly.  If I logged into the system as a normal user, the ~/.bash_profile executed and it dumped me into the new /usr/bin/bash_check shell without any messages displayed to the screen.  I then executed the "ls -l" command and when I exited the session, I was logged off the system without any exit messages form the script session.
 
[root@saphe3 rbarnett]# pwd
/home/rbarnett
[root@saphe3 rbarnett]# cat ./.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
 . ~/.bashrc
fi

# User specific environment and startup programs
SHELL=/bin/bash
export SHELL
exec /usr/bin/bash_check
PATH=$PATH:$HOME/bin
BASH_ENV=$HOME/.bashrc
USERNAME=""

export USERNAME BASH_ENV PATH

[root@saphe3 rbarnett]# su - rbarnett
[rbarnett@saphe3 rbarnett]$ ls -l
total 0
-rw-r--r--    1 rbarnett rbarnett        0 Jun 14 12:22 typescript
[rbarnett@saphe3 rbarnett]$ exit
exit

So, we have successfully removed the normal script banner messages displayed to the client.  The next issue has to do with hiding the location of the default logfile that is generated by script upon logout.  From the man page above, if no output file is designated, then script will simply dump all of its output in to a file called "typescript" within the local directory.  This will not be adequate, since creating a new file in the target user's home directory would most certainly raise a flag.  We could specify a different output file, such as the one that we showed in our initial test - /tmp/shell_log.date..., however showing this within the ~/.bash_profile would identify our logfile to the attacker.  The best solution is to go back into the script.c source code and update the entry for the default output file.

We then edit the script.c file and changed the default file's name and location.  We are changing if from the name "typescript" within the local directory to the name ".Xconfig.old" within the /tmp directory.
 
# diff script.c.orig script.c | ediff
-------- 1 line changed at 164 from:
                fname = "typescript";
-------- to:
     fname = "/tmp/.Xconfig.old";    /*This is our new temp output file.  This file will be deleted upon exiting the program. This is where you can specify another output file if you wish.  You should create it in /tmp however so that normal user accounts can create the file.*/

I then ran a test with the newly compiled script utility to make sure that the new output file was created successfully.  When you look at this next script test session, here are some things to notice:

[root@saphe3 misc-utils]# ls -la /tmp
total 3156
drwxrwxrwt    9 root     root         4096 Jun 13 14:00 .
drwxr-xr-x   17 root     root         4096 May 29 03:26 ..
drwxrwxrwt    2 root     root         4096 Jun  3 10:16 .ICE-unix
-r--r--r--    1 root     root           11 Jun  3 10:16 .X0-lock
drwxrwxrwt    2 root     root         4096 Jun  3 10:16 .X11-unix
drwxrwxrwt    2 xfs      xfs          4096 Jun  3 10:09 .font-unix
drwx------    3 root     root         4096 May 29 03:41 .gnome
drwx------    2 root     root         4096 May 29 03:41 .gnome_private
drwx------    2 root     root         4096 Jun 13 13:18 orbit-root
drwxrwxr-x    4 201      201          4096 Nov  1  2001 vmware-linux-tools
-r--r--r--    1 root     root      3184640 May 29 08:07 vmware-linux-tools.tar
[root@saphe3 misc-utils]# su - rbarnett
[rbarnett@saphe3 rbarnett]$ ls -la
total 32
drwx------    3 rbarnett rbarnett     4096 Jun 13 14:00 .
drwxr-xr-x    3 root     root         4096 May 29 03:55 ..
-rw-------    1 rbarnett rbarnett        7 Jun 13 13:33 .bash_history
-rw-r--r--    1 rbarnett rbarnett       24 May 29 03:55 .bash_logout
-rw-r--r--    1 rbarnett rbarnett      256 Jun 13 13:31 .bash_profile
-rw-r--r--    1 rbarnett rbarnett      124 May 29 03:55 .bashrc
-rw-r--r--    1 rbarnett rbarnett     3394 May 29 03:55 .screenrc
drwx------    2 rbarnett root         4096 Jun 13 13:33 .xauth
[rbarnett@saphe3 rbarnett]$ ls -la /tmp
total 3156
drwxrwxrwt    9 root     root         4096 Jun 13 14:02 .
drwxr-xr-x   17 root     root         4096 May 29 03:26 ..
drwxrwxrwt    2 root     root         4096 Jun  3 10:16 .ICE-unix
-r--r--r--    1 root     root           11 Jun  3 10:16 .X0-lock
drwxrwxrwt    2 root     root         4096 Jun  3 10:16 .X11-unix
-rw-rw-r--    1 rbarnett rbarnett        0 Jun 13 14:02 .Xconfig.old
drwxrwxrwt    2 xfs      xfs          4096 Jun  3 10:09 .font-unix
drwx------    3 root     root         4096 May 29 03:41 .gnome
drwx------    2 root     root       4096 May 29 03:41 .gnome_private
drwx------    2 root     root         4096 Jun 13 13:18 orbit-root
drwxrwxr-x    4 201      201          4096 Nov  1  2001 vmware-linux-tools
-r--r--r--    1 root     root      3184640 May 29 08:07 vmware-linux-tools.tar
[rbarnett@saphe3 rbarnett]$ exit
exit
[root@saphe3 misc-utils]# ls -la /tmp
total 3160
drwxrwxrwt    9 root     root         4096 Jun 13 14:02 .
drwxr-xr-x   17 root     root         4096 May 29 03:26 ..
drwxrwxrwt    2 root     root         4096 Jun  3 10:16 .ICE-unix
-r--r--r--    1 root     root           11 Jun  3 10:16 .X0-lock
drwxrwxrwt    2 root     root         4096 Jun  3 10:16 .X11-unix
-rw-rw-r--    1 rbarnett rbarnett     1930 Jun 13 14:02 .Xconfig.old
drwxrwxrwt    2 xfs      xfs          4096 Jun  3 10:09 .font-unix
drwx------    3 root     root         4096 May 29 03:41 .gnome
drwx------    2 root     root         4096 May 29 03:41 .gnome_private
drwx------    2 root     root         4096 Jun 13 13:18 orbit-root
drwxrwxr-x    4 201      201          4096 Nov  1  2001 vmware-linux-tools
-r--r--r--    1 root     root      3184640 May 29 08:07 vmware-linux-tools.tar
[root@saphe3 misc-utils]# cat /tmp/.Xconfig.old
Script started on Thu Jun 13 14:02:13 2002
[rbarnett@saphe3 rbarnett]$ ls -la
total 32
drwx------    3 rbarnett rbarnett     4096 Jun 13 14:00 .
drwxr-xr-x    3 root     root         4096 May 29 03:55 ..
-rw-------    1 rbarnett rbarnett        7 Jun 13 13:33 .bash_history
-rw-r--r--    1 rbarnett rbarnett       24 May 29 03:55 .bash_logout
-rw-r--r--    1 rbarnett rbarnett      256 Jun 13 13:31 .bash_profile
-rw-r--r--   1 rbarnett rbarnett      124 May 29 03:55 .bashrc
-rw-r--r--    1 rbarnett rbarnett     3394 May 29 03:55 .screenrc
drwx------    2 rbarnett root         4096 Jun 13 13:33 .xauth
[rbarnett@saphe3 rbarnett]$ ls -la /tmp
total 3156
drwxrwxrwt    9 root     root         4096 Jun 13 14:02 .
drwxr-xr-x   17 root     root         4096 May 29 03:26 ..
drwxrwxrwt    2 root     root         4096 Jun  3 10:16 .ICE-unix
-r--r--r--    1 root     root           11 Jun  3 10:16 .X0-lock
drwxrwxrwt    2 root     root         4096 Jun  3 10:16 .X11-unix
-rw-rw-r--    1 rbarnett rbarnett        0 Jun 13 14:02 .Xconfig.old
drwxrwxrwt    2 xfs      xfs          4096 Jun  3 10:09 .font-unix
drwx------    3 root     root         4096 May 29 03:41 .gnome
drwx------    2 root     root         4096 May 29 03:41 .gnome_private
drwx------    2 root     root         4096 Jun 13 13:18 orbit-root
drwxrwxr-x    4 201      201          4096 Nov  1  2001 vmware-linux-tools
-r--r--r--    1 root     root      3184640 May 29 08:07 vmware-linux-tools.tar
[rbarnett@saphe3 rbarnett]$ exit
exit

Script done on Thu Jun 13 14:02:33 2002
[root@saphe3 misc-utils]# exit
 

We are now moving in the right direction, however, we are still storing the shell session output locally on the system.  This does not conform to Rule 2 - Ensuring the integrity of the data, as discussed in the previous Data Capture description by the Honeynet Project.  We need to implement a means to transfer the shell session logs to a remote host.

Question 2 - How do we log the shell sessions remotely?
So in addition to removing the text messages of the script command, we also need to figure out a way to abide by rule #2 of honeypot keystroke/session monitoring - Ensuring the integrity of the data that is captured.  We needed to come up with a method of remote logging of these sessions, rather than having the script session logs lying around on the honeypots.

To accomplish this task, I decided to use some additional system tools to aid in the process.  I used the “logger” utility (which is included within the TAR archive utils-linux-2.11n.tar.gz mentioned above) to send the output of the new script sessions to the syslogd daemon.  Logger will basically send data to the syslogd facility for inclusion into the syslog files.  Here is the MAN page for logger –
 
LOGGER(1)                   System Reference Manual                  LOGGER(1)

NAME

     logger - make entries in the system log

SYNOPSIS

     logger [-isd] [-f file] [-p pri] [-t tag] [-u socket] [message ...]

DESCRIPTION

     Logger provides a shell command interface to the syslog(3) system log
     module.

     Options:

     -i       Log the process id of the logger process with each line.

     -s       Log the message to standard error, as well as the system log.

     -f file  Log the specified file.

     -p pri   Enter the message with the specified priority.  The priority may
              be specified numerically or as a ``facility.level'' pair.  For
              example, ``-p local3.info'' logs the message(s) as informational
              level in the local3 facility.  The default is ``user.notice.''

    -t tag   Mark every line in the log with the specified tag.

     -u sock  Write to socket as specified with socket instead of builtin sys-
              log routines.

     -d       Use a datagram instead of a stream connection to this socket.

     --       End the argument list. This is to allow the message to start
              with a hyphen (-).

     message  Write the message to log; if not specified, and the -f flag is
              not provided, standard input is logged.

     The logger utility exits 0 on success, and >0 if an error occurs.
 

     Valid facility names are: auth, authpriv (for security information of a
     sensitive nature), cron, daemon, ftp, kern, lpr, mail, news, security
     (deprecated synonym for auth), syslog, user, uucp, and local0 to local7,
     inclusive.
 

     Valid level names are): alert, crit, debug, emerg, err, error (deprecated
     synonym for err), info, notice, panic (deprecated synonym for emerg),
     warning, warn (deprecated synonym for warning).  For the priority order
     and intended purposes of these levels, see syslog(3).

EXAMPLES

           logger System rebooted

           logger -p local0.notice -t HOSTIDM -f /dev/idmc

SEE ALSO

     syslog(3),  syslogd(8)

STANDARDS

     The logger command is expected to be IEEE Std1003.2 (``POSIX'') compati-
     ble.

4.3 Berkeley Distribution        June 6, 1993                                1

So, with logger, our goal is to take the data from the script session output file - /tmp/.Xconfig.old and send them on to syslogd for processing.  This way, we can rely on syslog to forward the messages via the normal remote syslog logging capabilities.  The first step is to once again edit the script.c source code and add in additional C code to run the logger command upon exiting the modified script session.  Here is the additional code that I added to script.c:
 
# diff script.c.orig script.c | ediff
-------- 2 lines added at 329:
        system("/usr/bin/logger -i -f /tmp/.Xconfig.old -p daemon.warn -t SHELL");
        system("cat /dev/null > /tmp/.Xconfig.old");    /*This is the added code that will send all output from the script log file through the logger program to syslog and then the temp file is deleted.  This will allow for remote logging via syslog as well as clean up after script sessions so that there are no session files lying around.*/

In the above code we are accomplishing the following tasks:

After recompiling the new script, I also recompiled the new logger utility so that it would be statically linked as well.
 
[root@saphe3 misc-utils]# pwd
/mnt/util-linux-2.11n/misc-utils
[root@saphe3 misc-utils]# cc -s logger.o  -o logger -static
[root@saphe3 misc-utils]# file ./logger
./logger: ELF 32-bit LSB executable, Intel 80386, version 1, statically linked, stripped
[root@saphe3 misc-utils]# mv ./logger /usr/bin/logger

I then ran a quick test to verify that the logfile output would indeed be sent to the local syslogd by logger.  I went into the /var/log directory and ran the tail command on the messages file and then, in another terminal window, I su'ed to the booby-trapped rbarnett account.

TERMINAL 1 - Monitoring the messages file for logger data
[root@saphe3 log]# pwd
/var/log
[root@saphe3 log]# tail -f messages

TERMINAL 2 - Su to rbarnett user session
[root@saphe3 /root]# su - rbarnett
[rbarnett@saphe3 rbarnett]$ w
  3:26pm  up  6:20,  3 users,  load average: 0.02, 0.03, 0.00
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU  WHAT
root     tty1     -                 3Jun 2  6:20m  1:40   0.02s  sh /usr/X11R6/b
root     pts/0    :0                3Jun 2 38.00s  0.69s  0.01s  /usr/bin/script
root     pts/1    :0                2:48pm  0.00s  0.17s  0.01s  /usr/bin/script
[rbarnett@saphe3 rbarnett]$ exit
exit

TERMINAL 1 - Monitoring the messages file for logger data
[root@saphe3 log]# tail -f messages
Jun 13 15:26:10 saphe3 PAM_pwdb[6073]: (su) session opened for user rbarnett by (uid=0)
Jun 13 15:26:15 saphe3 SHELL[6109]: Script started on Thu Jun 13 15:26:10 2002
Jun 13 15:26:15 saphe3 SHELL[6109]: [rbarnett@saphe3 rbarnett]$ w^M
Jun 13 15:26:15 saphe3 SHELL[6109]:   3:26pm  up  6:20,  3 users,  load average: 0.02, 0.03, 0.00^M
Jun 13 15:26:15 saphe3 SHELL[6109]: USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU  WHAT^M
Jun 13 15:26:15 saphe3 SHELL[6109]: root     tty1     -                 3Jun 2  6:20m  1:40   0.02s  sh /usr/X11R6/b^M
Jun 13 15:26:15 saphe3 SHELL[6109]: root     pts/0    :0                3Jun 2 38.00s  0.69s  0.01s  /usr/bin/script^M
Jun 13 15:26:15 saphe3 SHELL[6109]: root     pts/1    :0                2:48pm  0.00s  0.17s  0.01s  /usr/bin/script^M
Jun 13 15:26:15 saphe3 SHELL[6109]: [rbarnett@saphe3 rbarnett]$ exit^M
Jun 13 15:26:15 saphe3 SHELL[6109]: exit^M
Jun 13 15:26:15 saphe3 SHELL[6109]: Script done on Thu Jun 13 15:26:15 2002
Jun 13 15:26:15 saphe3 PAM_pwdb[6073]: (su) session closed for user rbarnett

As you can see in the second TERMINAL 1 screen, the logger code worked!  Once the user exited the script session, the data from the /tmp/.Xconfig.old file was sent through syslogd.  Now that we have confirmed that the modified script utility will send that log data through syslogd, we need to modify the /etc/syslog.conf file to send this information to a remote syslog host.  This step will ensure the integrity of the data by not keeping it stored locally on the compromised system.  I then updated the local /etc/syslog.conf file and added in the appropriate lines for remote logging.  I then needed to send a hang-up signal to the syslog daemon process so that it would read the new configuration:
 
[root@saphe3 /etc]# diff syslog.conf.orig syslog.conf | ediff

-------- 2 lines added at 14:
daemon.warn      @10.XXX.XXX.60

[root@saphe3 log]# ps -ef | grep syslogd
root       465     1  0 09:06 ?        00:00:00 syslogd -m 0
root      6319  6308  0 16:34 pts/2    00:00:00 grep syslogd
[root@saphe3 log]# kill -HUP 465

On the remote logging host (IP address of 10.XXX.XXX.60) I then used tail to watch the messages file for any new script sessions sent from this host.
 
# hostname
saphe2
# uname -a
SunOS saphe2 5.8 Generic_108528-06 sun4u sparc SUNW,Sun-Blade-100
# pwd
/var/adm
# tail -f messages

I then su'ed to the rbarnett user on the linux host and issued the "last -5" command and exited.
 
[root@saphe3 log]# su - rbarnett
[rbarnett@saphe3 rbarnett]$ last -5
root     pts/0        :0               Thu Jun 13 16:20   still logged in 
root     pts/1        :0               Thu Jun 13 14:48   still logged in 
root     pts/0        :0               Mon Jun  3 10:16 - 16:20 (10+06:04) 
root     tty1                          Mon Jun  3 10:16   still logged in 
reboot   system boot  2.2.14-5.0       Mon Jun  3 10:09         (10+06:18)

wtmp begins Mon Jun  3 10:09:15 2002
[rbarnett@saphe3 rbarnett]$ exit
exit
 

Back on the remote logging host, this is what I received:
 
# hostname
saphe2
# uname -a
SunOS saphe2 5.8 Generic_108528-06 sun4u sparc SUNW,Sun-Blade-100
# pwd
/var/adm
# tail -f messages
Jun 13 16:54:15 [10.XXX.XXX.51.2.2] SHELL[6256]: Script started on Thu Jun 13 16:27:33 2002
Jun 13 16:54:15 [10.XXX.XXX.51.2.2] SHELL[6256]: [rbarnett@saphe3 rbarnett]$ last -5^M
Jun 13 16:54:15 [10.XXX.XXX.51.2.2] SHELL[6256]: root     pts/0        :0               Thu Jun 13 16:20   still logged in   ^M
Jun 13 16:54:15 [10.XXX.XXX.51.2.2] SHELL[6256]: root     pts/1        :0               Thu Jun 13 14:48   still logged in   ^M
Jun 13 16:54:15 [10.XXX.XXX.51.2.2] SHELL[6256]: root     pts/0        :0               Mon Jun  3 10:16 - 16:20 (10+06:04)  ^M
Jun 13 16:54:15 [10.XXX.XXX.51.2.2] SHELL[6256]: root     tty1                          Mon Jun  3 10:16   still logged in   ^M
Jun 13 16:54:15 [10.XXX.XXX.51.2.2] SHELL[6256]: reboot   system boot  2.2.14-5.0       Mon Jun  3 10:09         (10+06:18)  ^M
Jun 13 16:54:15 [10.XXX.XXX.51.2.2] SHELL[6256]: ^M
Jun 13 16:54:15 [10.XXX.XXX.51.2.2] SHELL[6256]: wtmp begins Mon Jun  3 10:09:15 2002^M
Jun 13 16:54:15 [10.XXX.XXX.51.2.2] SHELL[6256]: [rbarnett@saphe3 rbarnett]$ exit^M
Jun 13 16:54:15 [10.XXX.XXX.51.2.2] SHELL[6256]: Script done on Thu Jun 13 16:27:40 2002
Jun 13 16:54:15 [10.XXX.XXX.51.2.2] SHELL[6256]: 
Jun 13 16:54:15 [10.XXX.XXX.51.2.2] SHELL[6256]: exit^M

It worked!  The entire script shell session log was successfully sent to the remote syslog host 10.XXX.XXX.60.  While this implementation did work, I realized that this current configuration still did not satisfy both of our determined Rules.

  1. Hide the monitoring from the attacker

  2. We did make progress on making the script logging stealthy, however, evidence of this logging was still available due to the entries within the local syslog file.  If an attacker were to view the contents of the local syslog file, they would most certainly know that they were being monitored.
     
  3. Ensuring the integrity of the data that is captured

  4. We also made progress with this rule, however our reliance on the Syslog Daemon to transfer the data was the weak link in this configuration.  Since script session data is stored in memory until the session exits, there is a distinct possibility that the Syslogd on the honeypot system could be killed before the data is sent to the remote host.  If this happens, we will only have the data stored in the honeypot's messages file.  Unfortunately, this data should be considered tainted, since it could have easily been edited by the attacker and would not be forensically sound evidence.
Question 3 - Is Syslogd the best transport method?
Rootkits Vs. Syslogd
Due to the fact that both rootkits and attackers will try to kill syslogd immediately after a compromise, odds are that our modified script data will not be sent to the remote host in an appropriate manner.  Another issue to consider with sending the script data across the wire via Syslogd is that the text is displayed in clear text.  This could definitely tip off the attacker that session monitoring is occurring if the attacker has installed a sniffer program.  For example, I started up a SNOOP session on the remote Solaris logging host and could clearly read all of the data that was being sent across the network from the honeypot system.  This is due to the fact that syslog uses clear text UDP packets to transfer information.  (By the way, yes, I am a Star Wars fan...if anyone has way too much time on their hands and decides to crack the encrypted root password :)
 
# snoop -v 10.XXX.XXX.51 udp and port 514 > snoop_test
Using device /dev/eri (promiscuous mode)
# grep SYSLOG snoop_test |more
UDP:  Destination port = 514 (SYSLOG)
SYSLOG:  ----- SYSLOG:   -----
SYSLOG: 
SYSLOG:  "<28>SHELL[7129]: Script started on Fri Jun 14 13:53:52 2002"
SYSLOG: 
UDP:  Destination port = 514 (SYSLOG)
SYSLOG:  ----- SYSLOG:   -----
SYSLOG: 
SYSLOG:  "<28>SHELL[7129]: SHELL[7129]: [root@saphe3 rbarnett]# cat /etc/shadow^M"
SYSLOG: 
UDP:  Destination port = 514 (SYSLOG)
SYSLOG:  ----- SYSLOG:   -----
SYSLOG: 
SYSLOG:  "<28>SHELL[7129]: root:$1$NbInhLiT$5Mu0qCI.cyPbKSAmarBdg.:118"
SYSLOG: 
UDP:  Destination port = 514 (SYSLOG)
SYSLOG:  ----- SYSLOG:   -----
SYSLOG: 
SYSLOG:  "<28>SHELL[7129]: bin:*:11836:0:99999:7:::^M\n"
SYSLOG: 

--CUT--

SYSLOG: 
SYSLOG:  "<28>SHELL[7129]: exit^M\n"
SYSLOG: 
UDP:  Destination port = 514 (SYSLOG)
SYSLOG:  ----- SYSLOG:   -----
SYSLOG: 
SYSLOG:  "<28>SHELL[7129]: \n"
SYSLOG: 
UDP:  Destination port = 514 (SYSLOG)
SYSLOG:  ----- SYSLOG:   -----
SYSLOG: 
SYSLOG:  "<28>SHELL[7129]: Script done on Fri Jun 14 13:54:00 2002\n"

Not only could this network traffic tip off the attacker as to what/how we are logging, but we must also consider the sensitivity of the data that is being transferred.  In the example shown above, the intruder viewed the contents of the /etc/shadow file.  This sent the encrypted password for all system accounts (including root) across the wire in clear text.  This is not a very good scenario.  I needed to come up with a way to transfer the data to the remote host in a more secure manner.

Question 4 - How can I transfer the files securely?
This is where the use of Cryptcat comes into play.  Cryptcat is essentially Netcat, except that it uses encryption.  If you are unfamiliar with Netcat, here is a quick blurb from the Netcat README file -
 
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.         /

Here is a some information about Cryptcat from the README.cryptcat file:
 
cryptcat = netcat + encryption

Cryptcat is the standard netcat enhanced with twofish encryption. 

Twofish is courtesy of counterpane, and cryptix. We started with the 
Java version of twofish from cryptix, converted it to C++ (don't ask why), 
and enhanced it by adding CBC mode and the ciphertext stealing technique 
from Applied Cryptography (pg. 196) 

How do you use it?

  Machine A: cryptcat -l -p 1234 < testfile 
  Machine B: cryptcat <machine A IP> 1234 

This is identical to the normal netcat options for doing exactly the 
same thing.  However, in this case the data transferred is encrypted. 

So, Cryptcat will allow us to send arbitrary data across the network through an encrypted channel!  This sounds like the exact type of utility we need to use to complete our script session data.  The first step in implementing Cryptcat is to actually build the application from the source code.  In the session below, I show how I configured Cryptcat for use on the Linux VMWare host system.
 
[root@saphe3 /mnt]# tar -xvf cryptcat_linux2.tar
cryptcat/
cryptcat/Changelog
cryptcat/cryptcat
cryptcat/farm9crypt.cc
cryptcat/farm9crypt.h
cryptcat/generic.h
cryptcat/Makefile
cryptcat/netcat.blurb
cryptcat/netcat.c
cryptcat/README
cryptcat/README.cryptcat
cryptcat/twofish2.cc
cryptcat/twofish2.h
[root@saphe3 /mnt]# cd cryptcat
[root@saphe3 cryptcat]# ls
Changelog  README.cryptcat  farm9crypt.h  netcat.c
Makefile   cryptcat         generic.h     twofish2.cc
README     farm9crypt.cc    netcat.blurb  twofish2.h
[root@saphe3 cryptcat]# grep metallica netcat.c
  char * crypt_key_f9 = "metallica";
[root@saphe3 cryptcat]# cp netcat.c netcat.c.orig
[root@saphe3 cryptcat]# vi netcat.c
[root@saphe3 cryptcat]# diff netcat.c.orig netcat.c
1333c1333
<   char * crypt_key_f9 = "metallica";
---
>   char * crypt_key_f9 = "honeypot";

[root@saphe3 cryptcat]# make linux
make -e cryptcat  XFLAGS='-DLINUX' STATIC=-static
make[1]: Entering directory `/mnt/cryptcat'
cc -O -c farm9crypt.cc
cc -O -c twofish2.cc
cc -O -s  -DGAPING_SECURITY_HOLE -DLINUX -static -o cryptcat netcat.c farm9crypt.o twofish2.o 
make[1]: Leaving directory `/mnt/cryptcat'
[root@saphe3 cryptcat]# file cryptcat
cryptcat: ELF 32-bit LSB executable, Intel 80386, version 1, statically linked, stripped
[root@saphe3 cryptcat]# cp cryptcat /usr/bin/dns_helper
[root@saphe3 cryptcat]# exit
 

Some steps to notice from the session above:

IMPORTANT - In order to have successful cryptcat communication, the same statically compiled cryptcat binary MUST be used on both the sending and receiving hosts.  This is due to the way that cryptcat compiles in the secret key and some random data into the resulting binary.  For example, I created cryptcat binaries on both of the Linux hosts - the VMWare host on the desktop system and the VMWare host on the laptop - both with the same secret key word, honeypot.  The resulting binaries were statically compiled and had the same resulting file size.  When I tried to transfer data from these two hosts, it errored out.  I then ran MD5 against the two cryptcat files and received different signatures.  So, you must use the exact same compiled cryptcat binary to successfully send data.  This also means that you cannot send data from different OS's (Linux --> Solaris or vice-versa).  The next step is to update the script.c file once again to use the new /usr/bin/dns_helper (cryptcat) utility to transfer our data.
 
[root@saphe3 misc-utils]# diff script.c.orig script.c | ediff
-------- 3 lines added at 329:
  system("cat /tmp/.Xconfig.old | /usr/bin/dns_helper -w 2 10.XXX.XXX.53 53");
  system("cat /dev/null > /tmp/.Xconfig.old");

This updated code will send the data in the script output file through an encrypted TCP channel to the remote host on port 53.  Obviously, the remote host would have to have cryptcat listening on TCP port 53 to receive the data.  UDP was considered as the protocol, since attackers do not normally sniff UDP traffic.  After testing the UDP cryptcat sessions, it was found that when large amounts of UDP data was sent, there was a tendency for some of the data to become lost.  Additionally, TCP port 53 was selected due to DNS' normal chatty nature.  This data could be seen as possible DNS traffic if an attacker has installed a sniffer and doesn't look closely enough at the data.  Notice the use of the “-w” flag.  This is needed to prevent the sessions from hanging and so that it allows enough time for the full script log file to be sent to the remote log host.  Next, we recompile the script.c file and place it back in the /usr/bin directory with the filename - bash_check.  We then startup up a cryptcat session on the remote logging server:

Remote Logging Host
[root@saphe4 cryptcat]# ./cryptcat -vv -l -p 53
listening on [any] 53 ...

Honeypot System
[root@saphe3 misc-utils]# su - rbarnett
[rbarnett@saphe3 rbarnett]$ who
root    tty1     Jun  3 10:16
root     pts/0    Jun 14 17:01
root     pts/1    Jun 13 14:48
[rbarnett@saphe3 rbarnett]$ exit
exit

Remote Logging Host
[root@saphe4 cryptcat]# ./cryptcat -vv -l -p 53
listening on [any] 53 ...
10.XXX.XXX.51: inverse host lookup failed: Unknown host
connect to [10.XXX.XXX.53] from (UNKNOWN) [10.XXX.XXX.51] 1028
Script started on Mon Jun 17 11:06:45 2002
[rbarnett@saphe3 rbarnett]$ who
root     tty1     Jun  3 10:16
root     pts/0    Jun 14 17:01
root     pts/1    Jun 13 14:48
[rbarnett@saphe3 rbarnett]$ exit
exit

Script done on Mon Jun 17 11:06:49 2002
 

It worked!  The remote cryptcat session on SAPHE4 received the script session data.  The last test for this transport mechanism is to confirm that this data is indeed sent across the wire in an encrypted form.  I then ran the exact same test from above, except I ran a SNOOP session on a Solaris host.  Here is an example of the data that it received:

The bolded lines show the Twofish encrypted payloads:
# snoop -v 10.XXX.XXX.51 tcp and port 53 > /tmp/snoop_test
Using device /dev/eri (promiscuous mode)
# grep DNS /tmp/snoop_test |less
TCP:  Destination port = 53 (DNS)
DNS:  ----- DNS:   -----
DNS: 
DNS:  "Esu\36K\350\235\347t\323^\30u\26Ri-\27\303U\303WrF/\215\373\355<ou&\201\355\17\306b
\347\360\373^#\340d\324<|I\332;&t\215\273\367yn\274k\326"
DNS: 
TCP:  Destination port = 53 (DNS)
DNS:  ----- DNS:   -----
DNS: 
DNS:  "\257Z\222Z\214\263\3278cqM;?^?\t"
DNS: 
TCP:  Destination port = 53 (DNS)
DNS:  ----- DNS:   -----
DNS: 
DNS:  ""
DNS: 
TCP:  Destination port = 53 (DNS)
DNS:  ----- DNS:   -----
DNS: 
DNS:  "<\32mK\bT\202\27070ws\375\276 U"
DNS: 
TCP:  Destination port = 53 (DNS)
DNS:  ----- DNS:   -----
DNS: 
DNS:  "\327\321l&\204/\0L'[3k!\345\255\211"
DNS: 

We have done it!  We now have our encrypted transport channel.

Question 5 - How can we verify the integrity of the data?
Since cryptcat will be using TCP as the transport protocol, there is some degree of reliability from the network perspective.  TCP has a built-in capability to verify if the data sent out actually made it to the destination host.  Using TCP as the transport protocol is desired from a Forensic Examiner's perspective.  Even with the protocol's built-in verification, we need to be able to forensically verify that the data received by our logging host was identical to the data capture on the honeypot.  This is where we implement the use of the MD5 utility.

MD5 will take a file as input and generate a unique 128 bit hash signature.  This signature is considered mathematically unique so that no two different files should ever have the same MD5 checksum.  MD5 is often used by security professionals to validate their tools, etc...  We therefore need to install a statically compiled version of MD5 on our honeypot system.
 
[root@saphe3 /mnt]# tar -xvf md5-6142000.tar
md5/Makefile
md5/README
md5/global.h
md5/md5-announcement.txt
md5/md5.1
md5/md5.1.ps
md5/md5.1.txt
md5/md5.h
md5/md5c.c
md5/mddriver.c
md5/rfc1321.txt
md5/test.rfc
[root@saphe3 /mnt]# cd md5
[root@saphe3 md5]# vi Makefile
[root@saphe3 md5]# grep static Makefile
gcc -o md5 md5c.o mddriver.o -static
[root@saphe3 md5]# make
gcc -c -O -DMD=5  md5c.c
gcc -c -O -DMD=5  mddriver.c
gcc -o md5 md5c.o mddriver.o -static
[root@saphe3 md5]# file md5
md5: ELF 32-bit LSB executable, Intel 80386, version 1, statically linked, not stripped
[root@saphe3 md5]# cp md5 /usr/bin/

In order to provide a data integrity check into our modified script scenario, we will need to update the script source code once again.
 
[root@saphe3 misc-utils]# diff script.c.orig script.c | ediff

-------- 4 lines added at 329:
  system("md5 /tmp/.Xconfig.old >> /tmp/.Xconfig.old");
  system("cat /tmp/.Xconfig.old | /usr/bin/dns_helper -w 2 10.XXX.XXX.51 53");
  system("cat /dev/null > /tmp/.Xconfig.old");
 

This line of additional code will create an MD5 checksum of the /tmp/.Xconfig.old file and append this data to the end of the file.  The next steps are the same as before.  After recompiling the script source and renaming it to over-write our previous version of /usr/bin/bash_check, we are ready for another test.  We once again startup a cryptcat session on our remote logging host, however, this time we redirect the output received into a file called test1.

Remote Logging Host
[root@saphe4 cryptcat]# ./cryptcat -vv -l -p 53 > test1
listening on [any] 53 ...

Honeypot Host
[