Showing posts with label software. Show all posts
Showing posts with label software. Show all posts

Sunday, May 4, 2014

Python gdb Disassembly Extension 1.20

Ive released version 1.20 of my Python gdb Debugging Extensions, which I have now renamed to pygdbdis.

The introductory page for the extensions is here if you want to refresh your memory on what it does.

For a basic overview: The extensions are intended for those of us who use gdb to debug applications without the source - e.g. for reverse engineering, exploit development, etc.  They contain a number of helper functions that allow you to easily view the program state in a familiar and easy to use fashion, with string reading, hexdump memory reading, stack viewing, register printout with pointer dereferencing, etc.

The extensions are tested to work on Mac OSX and Linux with a version of gdb that supports Python (get the macports version of gdb for OSX). The supported targets are x86 and amd_x86_64 processes. Use the 'printextensionhelp' command to show valid commands.  Use 'source /path/to/pygdbdis-1.20.py' in gdb to load the extensions, and you can now autoload them by placing this same line in your gdbinit file (e.g. ~/.gdbinit).

To use the 'fifodisplay' command display to get contextual information about the debugees execution state whenever gdb stops, have a multi paned terminal app with at least three other open terminals, then run the 'fifodisplay' command and follow the prompts to create listeners for the various fifos in the other terminals.

Heres a screenshot of what the fifodisplay output looks like using iTerm2 on OSX.  In the top left pane is the disassembly display fifo, the top right is the register display fifo and the bottom right is the stack display fifo.




The changes in this version:
  • Numerous bug fixes
  • Name change
  • Improvements to the output and functioning of search commands. I still haven't been able to get rid of the memory read warnings, they seem to be a gdb 'feature' you cant disable, although I have moved all of the useful output of the commands to after the warnings appear
  • Exposed a number of user configurable settings that can be changed and viewed with the 'changeextensionsetting' and 'printextensionsettings' commands
  • Cleaned up fifodisplay output to hopefully prevent inappropriate line wrapping in the fifo displays. The fifo output can also be managed to some extent using height and width parameters exposed as user configurable settings
  • Added a by default option to not remove fifodisplay fifos on restart/exit. This functionality was introduced in version 1.10, and can be re-enabled using 'changeextensionsetting'
  • Added a 'setbreakpointatentry' command to set a breakpoint at the entry point of the program. By default this action is also performed automatically when a new objfile is loaded into the debugger, but this can be disabled if you desire
  • Made the 'printextensionhelp' command autodocument the configure gdb commands in the program using the class docstrings.  This means if you add a new command of your own it will be automatically listed in 'printextensionhelp' output with a description defined by the class docstring
  • Removed the ns command, as it was buggy and largely unnecessary
  • Improved the initialisation process for the script, now allowing the extension to be loaded from .gdbinit and allowing reconfiguration of the architecture specific settings if a new objfile is loaded
Download here: pygdbdis-1.20.py



Sunday, March 23, 2014

GDB Extensions 1.10

Here's a new version (1.10) of my gdb extensions. See the original post here to read about what they are and what they do.

Changes:
  • Many bug fixes (oh so many bugfixes)
  • The fifo files for the fifodisplay command have been moved off to the /tmp/ directory instead of the present working directory. There's a variable near the top of the script you can change to move this elsewhere if desired
  • The fifodisplay command now has a more functional "stop" feature that cleans up the fifo files and properly removes the gdb stop handler
  • The 'stop' feature of fifodisplay will also run automatically on an exited gdb event, cleaning up after itself when (for example) you finish your gdb session
  • The fifodisplay command has been modified to be a bit easier to use. It now prompts you to create the appropriate fifo listeners when the command is first run
  • A new 'printextensionhelp' command has been added to print out a list of all the commands added with the extension, as well as the purpose of each command

Thanks to deathjest3r who provided some of the suggestions for improvement that have made it into this new version.

Download link.

Sunday, October 20, 2013

My Python gdb Extensions

Introduction

If you started to learn reverse engineering and exploit development on 32 bit Windows systems as I did, you were probably very unimpressed when you first attempted to try out your skills on *nix machines and started (trying to) use gdb.  I know I was.

Gdb is quite powerful, but it seems to be focused more on debugging applications with source and debug symbols.  While its certainly possible to debug applications while only having access to the stripped binary, a lot of gdb's frequently used features aren't that useful.  Gdb wasnt designed with a focus on reverse engineering in mind, and neither were a lot of the various gdb GUI front ends.  Things that are simple in OllyDbg such as getting an immediate view of the stack, disassembly and register values every time the program stopped, or searching for a particular value through all of program memory are just painful.

Thats why the last time I had to reverse engineer an application on Mac OSX, I wrote some extensions for gdb using the Python API that was added to gdb in version 7.  These extensions consisted of a few new gdb commands, as well as some nifty hooks that enabled me to get the necessary information out of the program in a way that I was familiar with.

The additional commands I added provide new ways to view register values, program memory, the stack, to do assembly level stepping and to search program memory.  There are also hooks that allow certain program data to be sent to fifos every time program execution pauses.  In practice, this allows me to have output like this:

gdb lookin like Olly!


What you see above is a terminal window with multiple panes.  The main pane, on the bottom left is running gdb, with a program currently in the paused state..  The other panes are running the tail command on different fifo pipes, and showing output from gdb relating to the programs disassembly, registers and stack, including some contextual information such as any strings or hex data that might be referenced by the various registers or stack entries.

The idea was to get the break output from gdb as close to the information provided by OllyDbg without having to code up an entire GUI fronted, and after having used the interface for a few weeks I think its a reasonable facsimile. Its not possible to right click on anything as you can in OllyDbg, obviously, but most of that stuff can be done from the gdb command line.  This does however allow you to easily see at a glance most of the important stuff that Olly can show you when you're spending a while stepping through a program waiting for something interesting to happen.

Compatibility


This code has been tested on Mac OSX Mountain Lion and Linux, and works for both 32 and 64 bit processes.  Ive tested this using Python 2.7 and the Mac Ports version of gdb on OSX, and the Ubuntu 13.04 repository version of gdb on Linux, but other versions of gdb over 7 and Pythons over 2.5 SHOULD work too.  Probably. The Python gdb extensions seemed to have 'evolved' a little bit since they were first introduced in gdb 7 – to the extent that some of the early examples of code you can find for creating gdb extensions in Python don't actually work any more.  Your version of gdb also needs to have been configured with the '--with-python' option, which I believe applies to most versions you will get in the various packaging systems around.

Most of the commands in this set of extensions should run on any system that supports the right version of gdb and Python, with the exception of the search commands (which required use of some OS specific memory listing commands) and the register display commands (because these use hard coded register name values, which I have only provided for x86 and amd64 processors).   The stack printer also assumes a little endian order, so if the processor you are using is big endian this wont display right either.

Note: If you're running this on OSX, please note that the Xcode Command Line tools version of gdb WILL NOT work, its too old and doesn't support the Python GDB extensions.  Install macports and their version of gdb.

Supported Commands


Heres a list of commands included:
  • save breakpoints - save breakpoints to a file.  These breakpoints can then be read back into a new session using the built in gdb 'source' command.  This is essentially a fixed version of a broken bit of example code I found on the 'Net.
  • readhexmemory - prints in hex format a given number of bytes from a given address in memory.
  • readhexdumpmemory - prints out a given number of lines (16 bytes per line) of a hex dump of memory starting at a given address. Each line contains the hex value for each byte as well as its ASCII representation, in a similar fashion as you would see in a Hex editor.
  • readstring - prints out any string located at a given address in memory.  Works with ASCII and basic Unicode strings.
  • searchstring - searches allocated program memory for a given string, and prints out all discovered instances along with their associated memory addresses.  Works for ASCII and simple Unicode strings.  Only linux and Masc OSX supported.  Warnings may appear when certain sections of memory cannot be searched – these are nothing to worry about.
  • searchbinary - searches allocated program memory for binary data, provided in hex format, e.g. 414243ae. Only linux and Masc OSX supported. Warnings may appear when certain sections of memory cannot be searched – these are nothing to worry about.
  • printstack - prints out a given number of lines of the stack view, including the address, the value stored in memory at that address and, if the stack entry could be interpreted as a pointer, any data (string if possible, hex if not) stored at that address.  If the number of lines is ommitted, a value of 10 is assumed.
  • printregisters – prints out the registers, along with contextual information of the data located at the memory address stored by each register.
  • printdisassembly – prints out the disassembly for the code located at the instruction pointer register.
  • fifodisplay – registers a number of handlers to automatically run the printstack, print registers and printdisassembly commands each time the program pauses, and to send the output to fifo pipes created in the current working directory named stack, registers and disassembly.  Combined with a multiple paned terminal window, can give you contextual information simialr to OllyDbg. Use the Stop parameter to disable the handlers.
  • no – Does an assembly level step operation that will skip over “call” function calls and wont break on new threads.
  • ns – Does an assembly level step operation that will skip into “call” operations and wont break on new threads.

Usage


You can load these extensions by copying the Python file somewhere where your instance of gdb can see it and using the gdb source command to read it.  You should ideally load the extensions after attaching your file in gdb for debugging, because the load process runs a function to determine the architecture of the file being debugged, and future commands may fail if this is not successful.  You'll get an error message if there are any problems with this setup function, or a success message if everything is OK.  If you get an error message just load the file again after fixing the problem.

Once the file is loaded correctly the commands listed above can be run like any other gdb command, including support for tab command completion and support for the inbuilt gdb help system.

The fifodisplay command, which was responsible for the screenshot shown above, is a little more fiddly to setup however, so I will give a brief example of how to set it up below.

UPDATE: The usage of fifodisplay has changed a little since the 1.10 update to the extensions.  Now, instead of requiring you to run the tail commands to read the fifos from memory the first time the program pauses, running fifodisplay will now prompt you to setup each fifo listener individually immediately.  The fifo files are also now stored in /tmp/ and are cleaned up by the extensions if you run 'fifodisplay stop' or if you exit gdb or stop debugging the target.

To summarise, this is what you need to do to set it up:

Have a terminal program that supports multiple panes.  Im using iTerm2 in the screenshot shown above for the Mac, and on Linux I use Terminator (the Gnome version).  Set up for different panes, all with the same present working directory, and run gdb in the bottom left pane.

Attach to the program you want to run in gdb, and load the extensions file into gdb using 'source' and run the program to a breakpoint.  Now run the fifodisplay command and make the program trigger a stop event in gdb.  The simplest way to do this is to step ahead by one assembly instruction ('stepi') or continue execution until you hit another breakpoint you have configured.

Now, in order, do a tail -f on the 'stack' file in the bottom right window, the 'registers' file in the top right window, and the 'disassembly' file in the top left window.  What you are doing here is displaying the content from fifo pipe files with these names that are created in the present working directory by the gdb event handlers created by the fifodisplay command. These files are created in this order, the first time the gdb instance stops after the fifodisplay command is run.  Gdb will appear to freeze up while it waits for you to run each of these tail commands, because its waiting for each of the fifo pipes to be read from before command execution can continue.  This will eventually time out if you take too long however – if this happens just 'stepi' once more and you can continue on from where you left off opening the fifo files.

When you want to disconnect the handlers, kill each of your tail commands and either run 'fifodisplay Stop' (case sensitive) in gdb, or quit the gdb session.  The fifo pipe files will not be deleted automatically, so on subsequent attempts you'll just be able to start your listening tail commands whenever you wish.  When you want to get rid of the fifo files, just delete them like any other file.

Usage Example


Here's a quick example of me using the fifodisplay command during a gdb session debugging /bin/ls.

First I setup a new terminal session with four panes. Then, in the bottom left hand pane I run gdb. Im using the macports version of gdb (the binary for this is called ggdb).
stephenbradshaw@lion:~$ ggdb /bin/ls
GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin12.3.0".
For bug reporting instructions, please see:
...
Reading symbols from /bin/ls...(no debugging symbols found)...done.
(gdb) 


Within this running session of gdb, I then run commands to find the entry point of the program and set a breakpoint there
(gdb) info file
Symbols from "/bin/ls".
Local exec file:
 `/bin/ls', file type mach-o-x86-64.
 Entry point: 0x100000e0c
 0x0000000100000aa8 - 0x0000000100003e7b is .text
 0x0000000100003e7c - 0x000000010000403e is __TEXT.__stubs
 0x0000000100004040 - 0x000000010000433e is __TEXT.__stub_helper
 0x0000000100004340 - 0x00000001000044c8 is .const
 0x00000001000044c8 - 0x0000000100004900 is .cstring
 0x0000000100004900 - 0x0000000100004998 is __TEXT.__unwind_info
 0x0000000100004998 - 0x0000000100004ff8 is .eh_frame
 0x0000000100005000 - 0x0000000100005028 is __DATA.__got
 0x0000000100005028 - 0x0000000100005038 is __DATA.__nl_symbol_ptr
 0x0000000100005038 - 0x0000000100005290 is __DATA.__la_symbol_ptr
 0x0000000100005290 - 0x00000001000052b8 is .data
 0x00000001000052c0 - 0x00000001000054f0 is .const_data
 0x00000001000054f0 - 0x000000010000557c is __DATA.__common
 0x0000000100005580 - 0x0000000100005640 is .bss
(gdb) break *0x100000e0c
Breakpoint 1 at 0x100000e0c


Now I run the program til it hits the first breakpoint:
(gdb) r
Starting program: /bin/ls

Breakpoint 1, 0x0000000100000e0c in _mh_execute_header ()


Now I load the extensions and run the fifodisplay command:
(gdb) source sb-gdb-extensions.py
gdb extensions 1.00 loaded
(gdb) fifodisplay


Now I step ahead by one assembly instruction. Execution will now seem to freeze in the debugger as it waits for each fifo pipe to be read from:
(gdb) stepi

At this point I ran the following commands, in this order, in the other panes of my terminal window:

Bottom right pane:
stephenbradshaw@lion:~$ tail -f stack


Top right pane:
stephenbradshaw@lion:~$ tail -f registers


Top left pane:
stephenbradshaw@lion:~$ tail -f disassembly


Now in the bottom left pane you should see the stepi command finish in gdb.
0x0000000100000e0d in _mh_execute_header ()
(gdb)


Now you should be able to continue your debugging session as normal, and every time program execution stops in gdb, the stack, register and disassembly information will be updated in each of the associated terminal panes.

Download

The updated version 1.10 of the extensions can be found here.



Wednesday, December 15, 2010

Introducing Vulnserver

Vulnserver

I have just released a program named Vulnserver - a Windows based threaded TCP server application that is designed to be exploited.


Why did I write this?

I am (slowly, and when not occupied with other things) teaching myself to program in C, and this seemed like a good way to further develop my C programming skills.  This gave me an opportunity to see how software is exploited from the developers point of view, and crafting this software so it was exploitable using particular exploit techniques was an interesting challenge, and enabled me to look at exploitation from a new perspective.  And as an added bonus, it gives me the opportunity to claim that any bugs found in my code were put there deliberately.

I often find myself in need of an exploitable program in order to quickly test out shellcode, as well as other exploit techniques I am developing.  This program is ideal for that purpose, because it is small, easily portable, and extremely easy to debug.

I enjoy writing about how to exploit software, but finding exploits that are good to write about can be challenging.  In order to make for a good tutorial style document, you need to find an exploit, ensure the exploitable software is available to be downloaded and used, and if you don't want to continually cover the same ground, the exploit has to require some sort of unique technique in order to make things interesting.  It’s a lot easier to achieve this if you just write the vulnerable software yourself.

I have always liked exploitation exercises, such as the Sourcefire awbos,  and have always wanted to try writing something like that myself.  One thing I never liked about those exercises though was having to send data to these applications via command line arguments.  It makes debugging, fuzzing and exploit writing awkward, and it seems very unlike the way most real life exploits actually operate (especially on Windows).  Therefore, I created vulnserver, but unlike the awbos I implemented it in the form of a threaded TCP server app so you can exploit with ease over the network - making this feel a bit more like a "real" vulnerable server application.


What’s included?

The download package includes the usual explanatory text files, source code for the application as well as pre compiled binaries for vulnserver.exe and its companion dll file.  Working exploits are not included (but keep reading...).


Running Vulnserver

To run vulnserver, make sure the companion dll file essfunc.dll is somewhere within the systems dll path (keeping it in the same directory as vulnserver.exe is usually sufficient), and simply open the vulnserver.exe executable.  The program will start listening by default on port 9999 - if you want to use another port just supply the port number as a command line option to the program - e.g. to listen on port 6666 run vulnserver.exe like so:

vulnserver.exe 6666

The program supports no other command line options.

The program will spit out its version number when you start it up, as well as the version number of its companion dll, so it's obvious what version you are running just in case I need to update it in future. Exploitation can be a finicky business, and changes to/recompilation of a program can change the buffer structure required to gain control of code execution, so I have made tried to make it as easy as possible to determine what version of the program and its associated dll you are running, so if you are following along with any guide you can ensure you have the same version of the application as used in the guide.  This is also something to be aware of if you want to compile the program yourself - different c compilers (even different versions of the same compiler) can produce binaries that exploit in different ways from the same code, and you will get a warning about this when you start the program too.

Once the program is running simply connect to the appropriate port using a command line client like netcat and issue commands separated by newlines.  Perhaps start with HELP to see what commands are available to you...


Finding the bugs in Vulnserver

Vulnserver contains a number of bugs (exactly how many I'm not going to reveal just yet), and each one of them requires a different approach in order to create a successful exploit.  The difficulty of the exploits range from easy to medium difficulty - and the challenge is to execute a bindshell payload for each exploitable bug you find.

If you are at all experienced in analysing C code for vulnerabilities you should be able to spot the bugs pretty quickly by reading the source, but I’d suggest you instead attempt to find the vulnerabilities using fuzzing.  The program will give up its buggy secrets very quickly in response to the right fuzzer, appropriately used.  Connect using a basic TCP client like netcat, ask for HELP to see what type of commands are supported to use as a basis for fuzzing, and go from there.

This program has been released without working exploits for the moment, but for all but one of the exploitable bugs introduced into the program I have produced working exploits, so be assured that exploitation in multiple ways is definitely possible.  The one remaining exploit I have not yet completed is delayed until I can fix some issues with a certain type of publically available shellcode, which "does not always work". 

In the coming weeks, I am going to release a series of articles on how to find and exploit all of the exploitable bugs in this program, so if you can't find the bugs yourself don't despair.

I have confirmed this program runs, and is exploitable on Windows XP SP 2, Windows Vista SP? and Windows 7 systems with default configurations.


Here there be dragons... a Warning about improper use of vulnserver.

Vulnserver doesn't actually do anything other than allow exploitation - there is no useful functionality.  Integrating code to perform some other function didn’t seem to be a good use of binary space or my time considering the purpose of the program.  There has been some effort put in to make it appear as though the program is taking user input and providing responses, so it seems like a regular (albeit very basic) server application, but there's really no reason to run this unless you're actively exploiting it at the time.

You SHOULD NOT run this program on any critical system, and you should not allow this program's listening port to be accessible from any untrusted network, such as the Internet.  There is no malicious code included within this program (check the source to confirm), so this is NOT a virus or malware, but this program can be put to malicious use if an untrusted individual can access it.  That's kind of unavoidable considering what the program was designed for.  So run this only on a well protected (possibly isolated) test system, and only when you are actively using it to test exploitation methods - don’t just leave it running all the time.

Remember that if vulnserver is running on your system, and you're not exploiting it, someone else might be.

Anyway, enjoy the program and drop me a line if you have tried it and like it.


Download

Link below.

Wednesday, November 10, 2010

Version 0.4 of SSL Testing Tool ssltest.pl

New version, fixing a bug with the list command and resolving an issue from Skoyern relating to SSLv2 compliance with PCI DSS.

Download below - this link will always point to the latest version:

Tuesday, November 9, 2010

Version 0.3 of SSL Testing Tool ssltest.pl

I have released a new version of ssltest.pl - version 0.3.  This new version has two changes from version 0.2:
  • The tool now checks to see that it can make a connection to the provided host and port before it performs all of its SSL tests.  This will allow you to differentiate a non listening socket or non working network connection from an SSL service that supports no ciphers (mostly there to remind you when you mistype the hostname/port or when the service is down).  Thanks to Gitsnik for suggesting this (months ago...).
  • The tool now implements some crude detection for sites that allow an SSL connection using weak ciphers exclusively to provide "friendly" advice to the end user to upgrade their browser.  In response to a comment from Anton here.  Basically, I make a simple HTTP 1.1 request over any SSL socket that gets established, check the response for a "401 Unauthorized" response, and treat as unsupported any associated ciphers.  Im reasonably sure that this response should not be generated when authentication is required to access the web resource (that should be "401 Authorization Required"), but just in case the tool will tell you when it considers one or more ciphers to be unsupported because of this reason, and it will give you instructions on how to get more information to confirm.  If this causes false negatives, let me know so I can resolve the issue.  This new feature can also be disabled using the -f switch if it causes problems - see the help for more information.

Download below - this link will always point to the latest version of the tool:

Thursday, August 12, 2010

Version 0.2 of SSL Testing Tool ssltest.pl

I have just released a new version (0.2) of ssltest.pl.

This newest set of changes to the tool still don't include some of the things on my future wishlist, as mentioned in the previous post,  but instead came about when I attempted to use the tool from a Windows system and found it didn't work so well.

The changes in version 0.2 were essentially focused on getting the same functionality from the tool when run in Windows, as when run from Linux, as well as fixing some little niggles I found when attempting to use greppable output after running the tool on a list of sites via a for loop.

Some detail on the changes made in version 0.2:
  • Windows support, including coloured output using Win32::Console::ANSI.
  • Helpful error messages provided for missing perl modules, telling you how to remediate the issue.  Not much of an issue on Linux really, as most of the required modules are installed by default, but during the process of adding Windows support I discovered that IO::Socket::SSL, Net::SSLeay and Win32::Console::ANSI are all not installed by default AND not available in the ActiveState perl repositories.  The error messages will point you in the right direction to remediate the issue on Windows.
  • Some text added to the help message about OpenSSL.  While testing the tool on Windows I discovered that the misbehaving SSL appliance that triggered me writing this tool in the first place also did not respond well to particular versions of OpenSSL, in this case because the SSLv3 Hello packet was using a slightly different format.  Basically I just wanted to raise awareness here that if the tool isn't working for you on a particular system, you may want to try a different version of OpenSSL.
  • The format of the grep-able output has been improved, to include all of the relevant data on each individual line of output, including the compliance status for individual ciphers, hostname and port, protocol (SSLv2, SSLv3, TLSv1), cipher name and cipher description.  Essentially this makes the tool easier to use on large numbers of hosts at once - you can test multiple sites from a script, write all the data to one file and then grep the output to find relevant data.
  • Some minor cosmetic adjustments.

Here's a screenshot of the tool running on Windows, in all its colourful glory.


Download it here (this link will always point to the latest version of the tool):

Tuesday, July 27, 2010

SSL Testing Tool ssltest.pl

Update: I have just updated this tool to version 0.1.1 to resolve a minor bug (thanks Gitsnik) and a few cosmetic issues.

I have used a number of different tools to check cipher support on SSL Servers, including SSLDigger, sslthing, CryptonarkOpenssl and even a few web based solutions.  Each tool has its good and bad points, but recently when trying to confirm that a particular badly behaved reverse proxy was compliant with DSD ISM crypto standards I ran into some problems.  The reverse proxy I was attempting to test was not correctly responding to or closing SSLv2 and TLSv1 sessions, causing a number of the tools that I commonly use to freeze up.

Cryptonark was able to run against the proxy without freezing up, due to its ability to timeout sessions, but it still wasn't providing the right results due to the fact that it only tests SSLv2 and TLSv1, but not SSLv3 - the only protocol that happened to work on this particular system.  The tool is written in Perl however, so I consequently decided to quickly modify it to test SSLv3 as well.

But what started off as a quick modification, soon turned into a complete rewrite, as I rapidly came up with a list of additional features I wanted in addition to the SSLv3 support - optional verbose output (such as listing unsupported ciphers, plus connection attempts), colour highlighting for DSD ISM compliance as well as PCI-DSS, control over timeout settings, the ability to individually test protocols, more detail in the explanatory text for each cipher, greppable compliance status for each cipher, etc.  I have essentially reused the essential design concepts of the Cryptonark tool (including colour coding output, use of IO::Socket::SSL to make SSL connections, documenting supported ciphers within the tool, checking supported ciphers against a compliance standard), but have completely rewritten the code from scratch to clean it up, reduce repetition and dependence on additional perl modules, and ease implementation of the new features.

So now the tool is complete, it includes all those additional features I wanted, and it works very nicely against that badly behaving reverse proxy that started this whole thing.

I have decided to make the tool available here, first of all so I can easily get to a copy when needed, and also just in case anyone else finds it useful.  Until I can think of something better, I'm releasing this under the imaginative name of ssltest.pl - so called because the tool is used to test ssl.

Here is a listing of the help:
lupin@lion:~$ ssltest.pl
ssltest 0.1.1
grey-corner.blogspot.com

Tests the provided SSL host to determine supported SSL protocols and ciphers.
Originally based on Cryptonark by Chris Mahns.

USAGE:

/home/lupin/bin/ssltest.pl [options] host port
/home/lupin/bin/ssltest.pl [--pci|--ssl2|--ssl3|--tls1] --list


OPTIONS:

        -v|--verbose    Verbosity level. Use once to also list tested
                        ciphers that are not enabled on the target host.
                        Use twice to also show when host connection
                        attempts are made.

        -r|--ssl2       Performs cipher tests for the sslv2 protocol.
                        Default is all protocols (ssl2, ssl3, tls1).

        -s|--ssl3       Performs cipher tests for the sslv3 protocol.
                        Default is all protocols (ssl2, ssl3, tls1).

        -t|--tls1       Performs cipher tests for the tlsv1 protocol.
                        Default is all protocols (ssl2, ssl3, tls1).

        -x|--timeout    Sets timeout value in seconds for connections.
                        Default 4.  Lower value for hosts that may not
                        properly close connections when an unsupported
                        protocol request is attempted.  Raise value for
                        slow links/hosts.

        -i|--ism        Marks enabled ciphers that are compliant with the
                        DSD ISMs standards for in-transit protection of
                        IN-CONFIDENCE information (ISM Sep 2009).  Default
                        compliance standard used (as opposed to PCI).

        -p|--pci        Marks enabled ciphers that are compliant with
                        PCI-DSS standards.  Provided as an alternate
                        compliance standard to the DSD ISM.

        -g|--grep       Outputs in a semicolon ";" separated greppable
                        format, adds text for compliance status.  Use
                        when you need to write output to a text file and
                        you want compliance status to be included in
                        text format instead of just being repressnted by
                        terminal colour.

        -l|--list       Lists ciphers checked by this tool and exits,
                        with output colour coded to indicate compliance
                        status with the selected standard (pci or ism).
                        Host and port values do not need to be provided
                        when using this option, as no host connection is
                        made.  Purely informational, so you can see what
                        ciphers are tested for, and which are deemed to be
                        compliant with the various standards.


If one or more protocol/s (SSLV2, SSLV3, TLSV1) are not specifically enabled,
tests for all protocols will be performed.  If you know that a host does not
support certain protocols (or does not properly close connection attempts made
using particular protocols) you can only include tests for the protocols you
are interested in to speed up the test.  If no compliance standard is
specifically enabled, or if more than one standard is enabled, the default
is to use the DSD ISM.


EXAMPLES:

/home/lupin/bin/ssltest.pl -vvrsi test.example.com 443

Performs testing on host test.example.com port 443, using the sslv3 protocol
(-s), and sslv2 protocol (-r), matches responses against the cipher
requirements in the ISM (-i) and provides double verbose output (-vv) where
ciphers unsupported by the destination host and connection attempts are printed
to screen.

/home/lupin/bin/ssltest.pl --list

Provides a list of all ciphers supported by the tool, colour coded to indicate
which ones are considered to be compliant with the ISM.  Add the --pci switch
to colour code listed ciphers for PCI compliance instead, or supply the --ssl2,
--ssl3 or --tls1 switches to only list ciphers appropriate to those protocols.

Here is the tool in action, performing a test of the SSL ciphers supported by www.google.com

lupin@lion:~$ ssltest.pl www.google.com 443
Checking for Supported SSLv2 Ciphers on www.google.com:443...
Checking for Supported SSLv3 Ciphers on www.google.com:443...
   DES-CBC3-SHA, 3DES 168 bits, RSA Authentication, SHA1 MAC, RSA Key Exchange
   AES128-SHA, AES 128 bits, RSA Authentication, SHA1 MAC, RSA Key Exchange
   AES256-SHA, AES 256 bits, RSA Authentication, SHA1 MAC, RSA Key Exchange
   RC4-MD5, RC4 128 bits, RSA Authentication, MD5 MAC, RSA Key Exchange
   RC4-SHA, RC4 128 bits, RSA Authentication, SHA1 MAC, RSA Key Exchange
Checking for Supported TLSv1 Ciphers on www.google.com:443...
   DES-CBC3-SHA, 3DES 168 bits, RSA Authentication, SHA1 MAC, RSA Key Exchange
   AES128-SHA, AES 128 bits, RSA Authentication, SHA1 MAC, RSA Key Exchange
   AES256-SHA, AES 256 bits, RSA Authentication, SHA1 MAC, RSA Key Exchange
   RC4-MD5, RC4 128 bits, RSA Authentication, MD5 MAC, RSA Key Exchange
   RC4-SHA, RC4 128 bits, RSA Authentication, SHA1 MAC, RSA Key Exchange

I have reproduced above the colour coding the tool uses, a really helpful feature "borrowed" from Cryptonark, showing which ciphers are considered to be supported under the DSD ISM.  You can see from the above output that no SSlv2 ciphers are supported, and that some ciphers are coloured green, indicating that they are compliant with the selected standard of the ISM, and others are coloured red, indicating they are not.

Some ideas I have for the next revision of this tool are to have it verify that the hostname matches the common name on the certificate, to confirm the certificate has not expired, and possibly also to verify that the certificate is signed by a trusted certificate authority and has not been revoked.

You can download version 0.1 of the tool from here (this link will always point to the newest version of the tool):

Let me know if you try this tool out and find it useful.