Monday, September 29, 2008

Guide to AWBO Exercises

Over here at the VRT, we've thoroughly enjoyed sinking our teeth into the awbo exercises. Hopefully, readers who've had the chance to work through these are eagerly anticipating those to come.

On the other hand, there may still be some of you who are interested in giving these a shot, but either haven't ever worked with exploitation before or aren't sure how to set up their environment. For those who need a little extra nudge to get started, I've prepared a simple walk through outlining my personal preferred way of approaching these exercises.

If you've already completed any of the awbos, this guide will likely ring a tad redundant. If you haven't, but have a fairly good understanding of how the stack works, then read on. Given that spoiling any of the exercises would defeat the purpose of publishing them, I've written a short short, exploitable C program we'll be using as an example. The anatomy of the stack is a topic reserved for a later post.

read more here

Snort startup script for Ubuntu

Some folks just cannot write shell scripts, especially startup scripts, no matter what. They aren't just a collection of cli commands echoed into a file with a .sh extension and made executable. Ubuntu has a nice skeleton startup script that provides a good template for writing your own custom scripts. Here is one I made earlier for Snort:


#! /bin/sh
### BEGIN INIT INFO
# Provides: Snort
# Required-Start: $local_fs $remote_fs $syslog $network mysql
# Required-Stop: $local_fs $remote_fs $syslog $network mysql
# Default-Start: 2 3 4 5
# Default-Stop: S 0 1 6
# Short-Description: Init script to start the Snort daemon
# Description: Provides Snort service on startup and terminates
# on shutdown. Snort is an IDS or IPS. This script
# assumes that snort is installed in /usr/sbin and
# that it's main snort.conf file is in /etc/snort.
# The service will be started as a daemon, listening
# on eth0 and will also start quietly. If you require
# something other than this, you will have to edit
# the script accordingly.
# USE AT YOUR OWN RISK, YMMV. THIS SCRIPT COMES WITH
# ABSOLUTELY NO WARRANTY WHATSOEVER.
# License: GPLv2 see http://www.gnu.org/licenses/gpl-2.0.txt
### END INIT INFO

# Author: Nigel Houghton <[email protected]>

PATH=/usr/sbin:/usr/bin:/sbin:/bin
DESC="Snort service for IDS or IPS"
NAME=snort
CONFIG="/etc/snort/snort.conf"
INTERFACE="eth0"
DAEMON=/usr/sbin/$NAME
DAEMON_ARGS="-c $CONFIG -i $INTERFACE -qD"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 1

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
[ -f /etc/default/rcS ] && . /etc/default/rcS

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS \
|| return 2
}

#
# Function that stops the daemon/service
#
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
# Many daemons don't delete their pidfiles when they exit.
if [ -f "$PIDFILE" ]; then
rm -f $PIDFILE
fi
return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
return 0
}

case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
restart|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 3
;;
esac

:


You may use it at your own risk :D Some things may need to be changed before it will work for your system and you should use the update-rc.d command to put the links in the right places for you after installation into /etc/init.d/.

p.s. Don't forget to chmod 0700 /etc/init.d/snortstart after you install it.

Friday, September 19, 2008

AWBO4!

Some of you tore through awbo3 pretty quickly, but I wanted to give others time to catch up before posting this one. We're going to start getting into some issues you'll see in live software when working on exploits. This one in particular might remind you of a certain back orifice parsing vulnerability you may be familiar with.

It was asserted that this one couldn't be done in XPSP2, only in Win2k, but it really depends on how cl orders the stack before tossing the cookie in. Later, you'll get a chance to work on this with a mocked up stack cookie (awbo6) so keep that in mind here. For now though, lets stick to Win2k. The same rules apply here: no NOP sleds, no static stack return addresses.

For those who are just joining us, shellcode is here, and the windbg cheatsheet is here.

Hang on folks, we're venturing into rough waters. AWBO4

"Most deadly errors arise from obsolete assumptions"

Tuesday, September 9, 2008

Logical signatures in ClamAV 0.94

On September 1, 2008 Sourcefire released an engine update for ClamAV. This latest version offers new and updated features that allow researchers to write better signatures to detect malware. A quick overview of the changes in ClamAV 0.94 can be found here.

Up until ClamAV 0.93, the following formats have been used the most to write signatures to detect malware:
  • a full MD5 checksum of a file inside .hdb files in the following format: MD5:FileSize:MalwareName
  • a MD5 for a specific section of PE file stored in .mdb files in the following format: PESectionSize:MD5:MalwareName
  • a signature in a .ndb file using the following format: MalwareName:TargetType:Offset:HexSignature[:MinEngineFunctionalityLevel:[Max]]
ClamAV 0.94 introdcues a key new feature: logical signatures. A logical signature employs Boolean operators to combine one of more .ndb-style signatures into a single one. The main benefit of this approach is that it allows for more flexible pattern matching. The format for these new logical signtures is:

SignatureName;TargetDescriptionBlock;LogicalExpression;Subsig0;Subsig1;Subsig2;...

Logical signatures should be stored in .ldb files.

Let us illustrate how logical signatures can be used by analyzing a mass-mailer worm. The code for this sample is in Visual Basic Script (VBS) and so is easily readable. Right away we can see that the worm can loosely be classified in the category "AV Killer" as well since it attempts to identify the presence of various AV tools in order to disable them.



After normalization, we can create 4 signatures to detect each attempt to disable AV tools as follows:

Kaspersky Antivirus Personal/Kaspersky Antivirus Personal Pro (0): 66696c656578697374732028{-25}202620225c6b6173706572736b79206c61625c6b6173706572736b7920616e7469766972757320706572736f6e616c
{-100}2e64656c65746566696c652028{-25}202620225c6b6173706572736b79206c61625c6b6173706572736b7920616e7469766972757320706572736f6e616c

Antiviral Toolkit Pro (1): 66696c6565786973747328{-25}202620225c616e7469766972616c20746f6f6c6b69742070726f{-100}2e64656c65746566696c652028
{-25}202620225c616e7469766972616c20746f6f6c6b69742070726f

AVPersonal (2): 66696c656578697374732028{-25}202620225c6176706572736f6e616c{-100}2e64656c65746566696c652028{-25}202620225c6176706572736f6e616c

Trend PC-cillin 98 (3): 66696c656578697374732028{-25}202620225c7472656e642070632d63696c6c696e{-100}2e64656c65746566696c652028
{-25}202620225c7472656e642070632d63696c6c696e

Another very important characteristic of this script is that this worm tries to use Outlook MAPI to send itself to the first 8000 contacts found in the address book.



A signature to detect this portion of the file could be (4):

666f7220{-10}203d203120746f20{-10}2e61646472657373656e74726965732e636f756e74{-100}726563697069656e74732e616464
{-100}696620{-10}203e20{-5}207468656e206578697420666f72{-300}2e6174746163686d656e74732e616464{-150}2e73656e64

With ClamAV 0.94 and the addition of logical signatures, we write this highly flexible signature:

Worm.Godog;Target:0;((0|1|2|3)& (4));(0);(1);(2);(3);(4)

With a successful match, this signature will return the malware name "Worm.Godog". A match will occur when signature (4) is detected as well as either signature (0), (1), (2) or (3). The signature will look like the signature below in a .ldb file:

Worm.Godog;Target:0;((0|1|2|3)& (4));66696c656578697374732028
{-25}202620225c6b6173706572736b79206c61625c6b6173706572736b7920616e7469766972757320706572736f6e616c
{-100}2e64656c65746566696c652028{-25}
202620225c6b6173706572736b79206c61625c6b6173706572736b7920616e7469766972757320706572736f6e616c;66696c6565786973747328
{-25}202620225c616e7469766972616c20746f6f6c6b69742070726f{-100}2e64656c65746566696c652028
{-25}202620225c616e7469766972616c20746f6f6c6b69742070726f;66696c656578697374732028
{-25}202620225c6176706572736f6e616c{-100}2e64656c65746566696c652028{-25}202620225c6176706572736f6e616c;66696c656578697374732028
{-25}202620225c7472656e642070632d63696c6c696e{-100}2e64656c65746566696c652028{-25}202620225c7472656e642070632d63696c6c696e;666f7220
{-10}203d203120746f20{-10}2e61646472657373656e74726965732e636f756e74{-100}726563697069656e74732e616464{-100}696620{-10}203e20
{-5}207468656e206578697420666f72{-300}2e6174746163686d656e74732e616464{-150}2e73656e64

In previous versions of ClamAV up to 0.93 included, one would have to write many signatures in order to match the flexibility of the signature above. In this malware sample, 3 different AV tools are disabled the worm tried to spread to the first 8,000 contacts of your Outlook address book. However, a variant could disable just one of the AV tools and still try to spread over the network. To detect the variant that just disables Kaspersky AV, a pre-0.94 signature would look like:

Worm.Godog:0:*:(0){-750}(4)

To detect the variant that just disables Antiviral Toolkit Pro, a pre-0.94 signature would look like:

Worm.Godog:0:*:(1){-700}(4)

More signatures can be written for the other cases.

This simple example shows how logical signatures can be very powerful in reducing the number of signatures written to detect variants within a malware famill. Logical signatures can also help detect malware samples that were previously tough to detect and reduce the number of false positive detections.

Friday, September 5, 2008

Webcast Teaser -- Basic Buffer Overflow Detection

Our next webcast, Performance Rules Creation: Rules Options and Techniques, is scheduled for 1pm EST on Wednesday, September 17th. We’ll be using actual published VRT rules to demonstrate common rule structures, rule options and some of the gotchas that you might run across when writing Snort rules. We will also be referring back to some information from our previous webcast, which concentrated on the architecture of the Snort engine and performance considerations in rule writing. If you didn’t catch it, you might want to review the material. It is archived here.

For example, we’ll be looking at a common buffer overflow detection technique using negative content matches and the isadataat rule option. We use SID 13916 to demonstrate:

alert tcp $EXTERNAL_NET any -> $HOME_NET 4000 (msg:"EXPLOIT Alt-N SecurityGateway username buffer overflow attempt"; flow:established, to_server; content:"username="; nocase; isdataat:450,relative; content:!"&"; within:450; content:!"|0A|"; within:450; metadata:policy balanced-ips drop, policy connectivity-ips drop, policy security-ips drop; reference:url,secunia.com/advisories/30497/; classtype:attempted-admin; sid:13916; rev:2;)

For easier analysis, here is the core detection functionality of the rule, broken into a list:

  • flow:established, to_server;
  • content:"username=";
  • isdataat:450,relative;
  • content:!"&"; within:450;
  • content:!"|0A|"; within:450;

Because this is an attack on a server, we use the flow:established, to_server; rule option to tell Snort to only look at traffic that is headed towards a server (in this case, one listening on port TCP/4000). This both provide an increase in performance by not looking at server-response traffic, and will reduce false-positives by not looking at traffic that could not possibly trigger the vulnerability.

Next, we look to match the string “username=” in the packet. For those following along from last time, this will be the “first, longest” content match, and will be used in the fast-pattern matcher. This string is actually the beginning of the vulnerable field, so we will use it to anchor our upcoming detection. Also, note that we believe that “username=” could be upper or lowercase, or any combination, so we use the nocase keyword to modify the search to be case insensitive.

The attack appears to require at least 450 bytes of data to successfully overflow the buffer. Also, given the protocol we’re looking at, we know that both “&” and “\x0a” (also, \x0d\x0a, but we will just use \x0a for speed, since it works alone or paired with \x0d) are terminating characters that indicate the end of data for that key/value pair. Using this information we build the detection with the last three rule options.

We use a pair of negative content matches, content:!”&”; within: 450; and content:!”|0A|”; within: 450; to ensure that we do not see either terminating condition in the next 450 bytes of payload. Note that we use “within” as opposed to “depth”, because “within” sets the relative match flag and operates from the end of the previous match (username=). Depth would operate from the beginning of the payload (a non-relative search).

There is a problem with using negative content match. It will return as successful (that is, it did not see the provided pattern) even if it runs out of data to read before it reaches the end of our within: 450 requirement. This is bad for two reasons: One, we might false positive on an unreassembled TCP message (splitting the username= field across two packets), and two, if we don’t have enough data to create an overflow, we shouldn’t be doing a pair of content checks. To solve both these issues we use the isdataat: 450, relative; check to ensure that starting from the last match (username=), we have 450 bytes of data remaining in the payload buffer. If there isn’t enough data left, we won’t bother with the last two checks, avoiding a false-positive situation and the overhead of running two long, unnecessary content checks.

The detection is fairly simple, find “username=” and then see if the provided data is 450 or more bytes of data. If it is, we most likely have an attempted buffer overflow attack. But as you can see there are a number of factors we need to get right to ensure we have optimized detection that is both accurate and fast.

If you’re interested in more examples, catch the webcast on September 17th. Here are the details:

Date: Wednesday, September 17, 2008
Time: 1:00 PM US Eastern Daylight Time (GMT -4:00)
Registration: https://sourcefireevents.webex.com/sourcefireevents/onstage/g.php?t=a&d=663541041

Wednesday, September 3, 2008

AWBO Part Deux

Since some people have been chomping at the bit for the next challenge, so here it is. The same rules apply as did last time. When we say no static stack return addresses, this also means of course that there's no need for NOP sleds, so I shouldn't see them in solutions. This time around you'll find a solution under Windows 2000 SP4, then you'll find a solution for Windows XPSP2. I've also included a windbg cheat sheet to save the poor soul who told us he had worked out a solution using only Dr. Watson...

"Please be advised that a noticeable taste of blood is not part of any test protocol"

awbo3.exe download and windbg cheatsheet