Monday, February 25, 2008

Writing your own Preprocessors


Snort Preprocessors Development Kickstart

Last updated: November 29th 2005
Authors: Andrés Felipe Arboleda Torres, Charles Edward Bedón Cortázar


What is a Snort Preprocessor?
Preprocessors are plugable components of Snort, introduced since version 1.5. They're "located" just after the module of protocol analysis and before detection engine and do not depend of rules. They are called whenever a packet arrives, but JUST ONCE, the detection plugins, in the other hand, do depend of rules and may be applied many times for a single packet. SPP's can be used in different ways: They can look for an specific behavior(portscan, flowportscan), to be support for further analysis(is this the expression? help us) like flow, or just collect certain information, like perfmonitor.
More information can be found at http://www.snort.org/docs/snort_htmanuals/htmanual_2.4/node11.html
When should I code a Snort Preprocessor and not a Detection Plugin?
/*TODO*/
A Hello World Preprocessor
These are the steps you should follow to make your first preprocessor(supossing the directory for unzipped Snort is $SNORT_DIR):

1. Open the templates for your code at $SNORT_DIR/templates: 2 files--> spp_template.c and spp_template.h
2. Make your own files, trying to follow the convention of using the prefix "spp_" before the name of the preprocessor. Those files should be created at $SNORT_DIR/src/preprocessors
3. The header file:
spp_helloworld.h

/*To keep you from repeat this anywhere else*/
1 #ifndef __SPP_HELLOWORLD_H__
2 #define __SPP_HELLOWORLD_H__
/*Demostrative(won't be used in this example later):You can define structs to share info if for example, this preprocessor will be used for another one. */
4 typedef struct _helloStruct{
5 int x;
6 char *string;
7 }helloStruct;
/*Demostrative*/
9 int helloCounter=0;
/*This is the actually important prototype. This function will be called when initializating SPP's*/
11 void SetupHelloWorld(void);
/*Demostrative. Remember: important if this preprocessor is intended to be support for another one later*/
13 void myHelloWorldFunction(char *str);
/*Demostrative*/
15 extern helloStruct myHelloWorldStruct;
16 #endif
4. The source file:
spp_helloworld.h

/*config.h is generated by "autoheader", when configuring the project(information about OS, libs available ....)it's located at $SNORT_DIR. Useful things for you to know the what can do and what cannot*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

/*Definition of u_char*/
#include

/*Functions Add* and RegisterPreprocessor */
#include "plugbase.h"

/*Definition of Packet*/
#include "decode.h"

/*Our header file */
#include "spp_helloworld.h"

/*Demostrative */
helloStruct myHelloWorldStruct;

/*Prototypes of internal functions*/

/*Initialization Function(Usually, take parameters from config file, call a parseargs function and initializes local variables) */
void HelloInit(u_char* args);
/*What the pp actually does*/
void HelloFunc();
/*What to do when a term order is received*/
void HelloCleanExitFunction();
/*What to do when a restart order is received*/
void HelloRestartFunction();

Called from plugbase.c
void SetupHelloWorld(void){
/* Here you could (in fact you *should*) use the macro DEBUG_WRAP defined in debug.h, or if you really want this message to appear anyway(not only in debug mode, the place depends on the type of messaging log, it could even be registered in the syslog) use the function logMessage at util.h
NOTE: this function is called always, even if this preproc has not been included in the config file*/
printf("Let's see if Hello World Preprocessor is in the config file...\n");
/*Receives the name of your pp(the one in the config file) and a function pointer to the initialization code */
RegisterPreprocessor("helloworld", HelloInit);
}

/*NOTE: This function is called once, and depends on the addition of the preproc in the config file. See coments above*/
void HelloInit(u_char* args){
printf("Hello world Preprocessor is being initialized...\n");
/*"args" is a string with the arguments in the config file(remember the preprocessor definition syntax preprocessor:). Arguments can have any separator, at $SNORT_DIR/msplit.h, there is a good collection of functions to get the right values, eg, msplit. This file contains some functions not included in libc.*/
printf("Those arguments were received --> %s\n",args)
/*Add this pp to pp list. The argument is a pointer function to the code to be executed everytime a packet arrives*/
AddFuncToPreprocList(HelloFunc);
/*What to do when a term order is received*/
AddFuncToCleanExitList(HelloCleanExitFunction, NULL);
/*What 2 do when a restart order is received*/
AddFuncToRestartList(HelloRestartFunction, NULL);
}

/*NOTE: This function is called when a packet is received*/
void HelloFunc(Packet* p){
printf("Hello world Preproccessor is being called...\n");
/*Just a little demostration. Is the packet TCP?*/
printf((p->tcph==NULL)?
"This packet does not have any TCP header\n":"This a valid TCP packet\n");
}

/*TODO*/
void HelloRestartFunction(){
}

/*Called when Ctrl+C is hit*/
void HelloCleanExitFunction(){
/* Free pointers and other resources, for example. You can also present some stats on stdout or generate more logs*/
}

5. Edit the file $SNORT_DIR/src/plugbase.c: Add these lines-->
plugbase.c
In the includes section:
/* built-in preprocessors */
#include "preprocessors/spp_portscan.h"
(...)
/*Our preprocessor*/
#include "preprocessors/spp_helloworld.h"
(...)

In the function InitPreprocessors:
void InitPreprocessors(){
(...)
SetupHttpInspect();
/*Our preprocessor*/
SetupHelloWorld();
SetupFlow();
(...)
}
6. Edit $SNORT_DIR/src/preprocessors/Makefile (if already generated) or $SNORT_DIR/src/preprocessors/Makefile.in.(before configure)
Makefile or Makefile.in
In the libspp_a_SOURCES section:

(...)
libspp_a_SOURCES = spp_arpspoof.c spp_arpspoof.h spp_bo.c spp_bo.h \
(...)
#Our preprocessor
spp_helloworld.c spp_helloworld.h \
(...)
#And this for the linker in the section "am_libspp_a_OBJECTS"
(...)str_search.$(OBJEXT) spp_portscanai.$(OBJEXT)
(...)
7. Compile ... (nothing is over til it's over)
8. Add our pp in the config file:
etc/snort.conf
(...)
preprocessor flow: stats_interval 0 hash 2
#Our preprocessor
preprocessor helloword: hello world args

preprocessor stream4_reassemble
preprocessor stream4
(...)

Stuff Used

* Snort 2.2.0(successfully used under v2.4.1)
* Anjuta IDE 1.2.2(KDevelop 3.4 too)
* Debian Sarge 3.1 kernel 2.6.13

Bibliography

* http://www.snort.org/docs/

To Do

* Complete the sections marked as "TODO" je je ... excuse us we're a bit impatient, and we can't take til finishin' all work before release the docs... ;)
* Include a little FAQ with information about commonly used functions and data structures
* Do an example with the colaborative work between two or more spp

Happy Snortin'!!!!