文章目录
参考
本专栏所有相关博文使用的snort版本均为 2.9.15.1
0.开胃菜
1. 预处理器回顾
- 预处理器在Snort应用规则前处理接收到的数据
- 预处理器对每一个数据包只执行一次
- 被捕获的数据包首先经过预处理器,然后经过探测引擎根据规则处理。
- 输入插件和预处理器是同一概念
- 当Snort接收到数据包的时候,主探测引擎并不能对它们进行处理和应用规则,比如,数据包有可能是分片的,需要重新组装,预处理器就是做这样的工作,使数据能够被探测引擎处理,另外,一些预处理器还可以做一些其它工作,比如探测包中的一些明显错误。
- 你可以编写自己的预处理器,察看Snort源代码doc目录中的README.PLUGINS文件,你可以获得相关的资料,也可以在templates目录中查看源代码示例。
2. README.PLUGINS
Plugin Info 12/5/99 Martin Roesch Overview: Snort version 1.5 introduces a major new concept, plugins. There are two types of plugin currently available in Snort: detection plugins and preprocessors. Detection plugins check a single aspect of a packet for a value defined within a rule and determine if the packet data meets their acceptance criteria. For example, the tcp flags detection plugin checks the flags section of TCP packets for matches with flag combinations defined in a particular rule. Detection plugins may be called multiple times per packet with different arguments. Preprocessors are only called a single time per packet and may perform highly complex functions like TCP stream reassembly, IP defragmentation, or HTTP request normalization. They can directly manipulate packet data and even call the detection engine directly with their modified data. They can perform less complex tasks like statistics gathering or threshold monitoring as well. Adding New Plugins to Snort as a User: Right now, adding a new plugin to Snort is straightforward but requires you to edit two files by hand. The plugin should consist of two files, "sp_something.c"/"sp_something.h" for detection plugins, and "spp_something.c"/"spp_something.h" for preprocessors. For detection plugins, there are two steps to integrating it with Snort: 1) Edit plugbase.h and insert the line #include "sp_something.h" into the file with the other "#include" statements. Save and close the file. 2) Edit the plugbase.c file and in the InitPlugins() function, add the name of the setup function to the list with the other Setup functions. Save and close the file. 3) Edit the Makefile.am and add the names of the two files to the list of names on the "snort_SOURCES" line. Save and exit the file. Run "automake". Someday, there will be a nice little program that will do all this work for you! Writing New Snort Plugins as a Developer: This process is also pretty straight forward, and the best place to look for information on doing these things is at the files in the "templates" directory. The sp_* files are setup for detection plugins, and the spp_* files refer to the preprocessor files. The main thing to remember once you've got it written is to put the proper includes and function calls into plugbase[.c|.h]. I should probably flesh out this document more, but I think that the best info is in the template files. If you have any questions or comments, don't hesitate to send me an e-mail!
机翻来自百度
插件信息 1999年5月12日 马丁·罗斯奇 概述: Snort版本1.5引入了一个重要的新概念,即插件。有两种类型 Snort中当前可用插件的数量:检测插件和预处理器。 检测插件检查数据包的一个方面是否有在 一种规则,用于确定包数据是否满足其接受标准。为了 例如,tcp标志检测插件检查tcp数据包的标志部分 用于与特定规则中定义的标志组合匹配。检测 每个包可以使用不同的参数多次调用插件。 预处理器在每个包中只调用一次,并且可以执行很高的性能 复杂功能,如TCP流重组、IP碎片整理或HTTP 请求规范化。它们可以直接操作包数据,甚至调用 检测引擎直接用他们修改过的数据。他们能做的更少 复杂的任务,例如统计数据收集或阈值监视。 以用户身份向Snort添加新插件: 现在,向Snort添加一个新插件很简单,但是需要您 手工编辑两个文件。插件应该由两个文件组成, “sp_something.c”或“sp_something.h”用于检测插件,以及 “spp_something.c”或“spp_something.h”表示预处理器。对于检测插件, 将它与Snort集成有两个步骤: 1) 编辑plugbase.h并插入行 #包括“sp_something.h” 与其他“#include”语句一起放入文件。保存并关闭 文件。 2) 编辑plugbase.c文件,在InitPlugins()函数中,添加 列表中的设置函数和其他设置函数。保存和 关闭文件。 3) 编辑Makefile.am并将两个文件的名称添加到 “snort_SOURCES”行中的名称。保存并退出文件。跑步 “汽车制造”。 总有一天,会有一个很好的小程序来帮你完成所有的工作! 作为开发人员编写新的Snort插件: 这个过程也是非常直接的,而且是最好的地方 有关执行这些操作的信息位于“templates”目录中的文件中。 sp U*文件是为检测插件设置的,spp U*文件是指 预处理器文件。一旦你写好了,最重要的是要记住 是将适当的include和函数调用放入plugbase[.c |.h]。我 也许应该更详细地说明这个文件,但是我认为最好的信息 在模板文件中。如果你有任何问题或意见,不要 不好意思给我发电子邮件!
3. spp_template.c
/* $Id$ */ /* Snort Preprocessor Plugin Source File Template */ /* spp_template * * Purpose: * * Preprocessors perform some function *once* for *each* packet. This is * different from detection plugins, which are accessed depending on the * standard rules. When adding a plugin to the system, be sure to * add the "Setup" function to the InitPreprocessors() function call in * plugbase.c! * 注意:上面是Snort源文件中spp_template.c (预处理器模板)中的注释, * 这个注释没有及时更新 * 原文中的InitPreprocessors( ) 函数已经被替换成了 RegistPreprocessors( ) * * Arguments: * * This is the list of arguments that the plugin can take at the * "preprocessor" line in the rules file * * Effect: * * What the preprocessor does. Check out some of the default ones * (e.g. spp_frag2) for a good example of this description. * * Comments: * * Any comments? * */ #include <sys/types.h> #include <stdlib.h> #include <ctype.h> #include <rpc/types.h> /* * If you're going to issue any alerts from this preproc you * should include generators.h and event_wrapper.h */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "generators.h" #include "event_wrapper.h" #include "util.h" #include "plugbase.h" #include "parser.h" /* * put in other inculdes as necessary */ /* * your preprocessor header file goes here if necessary, don't forget * to include the header file in plugbase.h too! */ #include "spp_template.h" /* * define any needed data structs for things like configuration */ typedef struct _TemplateData {
/* Your struct members here */ } TemplateData; /* * If you need to instantiate the preprocessor's * data structure, do it here */ TemplateData SomeData; /* * function prototypes go here */ static void TemplateInit(u_char *); static void ParseTemplateArgs(char *); static void PreprocFunction(Packet *); static void PreprocCleanExitFunction(int, void *); static void PreprocRestartFunction(int, void *); /* * Function: SetupTemplate() * * Purpose: Registers the preprocessor keyword and initialization * function into the preprocessor list. This is the function that * gets called from InitPreprocessors() in plugbase.c. * * Arguments: None. * * Returns: void function * */ void SetupTemplate() {
/* * link the preprocessor keyword to the init function in * the preproc list */ RegisterPreprocessor("keyword", TemplateInit); DebugMessage(DEBUG_PLUGIN,"Preprocessor: Template is setup...\n"); } /* * Function: TemplateInit(u_char *) * * Purpose: Calls the argument parsing function, performs final setup on data * structs, links the preproc function into the function list. * * Arguments: args => ptr to argument string * * Returns: void function * */ static void TemplateInit(u_char *args) {
DebugMessage(DEBUG_PLUGIN,"Preprocessor: Template Initialized\n"); /* * parse the argument list from the rules file */ ParseTemplateArgs(args); /* * perform any other initialization functions that are required here */ /* * Set the preprocessor function into the function list */ AddFuncToPreprocList(PreprocFunction); AddFuncToCleanExitList(PreprocCleanExitFunction, NULL); AddFuncToRestartList(PreprocRestartFunction, NULL); } /* * Function: ParseTemplateArgs(char *) * * Purpose: Process the preprocessor arguments from the rules file and * initialize the preprocessor's data struct. This function doesn't * have to exist if it makes sense to parse the args in the init * function. * * Arguments: args => argument list * * Returns: void function * */ static void ParseTemplateArgs(char *args) {
/* your parsing function goes here, check out the other spp files for examples */ } /* * Function: PreprocFunction(Packet *) * * Purpose: Perform the preprocessor's intended function. This can be * simple (statistics collection) or complex (IP defragmentation) * as you like. Try not to destroy the performance of the whole * system by trying to do too much.... * * Arguments: p => pointer to the current packet data struct * * Returns: void function * */ static void PreprocFunction(Packet *p) {
/* your preproc function goes here.... */ /* * if you need to issue an alert from your preprocessor, check out * event_wrapper.h, there are some useful helper functions there */ } /* * Function: PreprocCleanExitFunction(int, void *) * * Purpose: This function gets called when Snort is exiting, if there's * any cleanup that needs to be performed (e.g. closing files) * it should be done here. * * Arguments: signal => the code of the signal that was issued to Snort * data => any arguments or data structs linked to this * functioin when it was registered, may be * needed to properly exit * * Returns: void function */ static void PreprocCleanExitFunction(int signal, void *data) {
/* clean exit code goes here */ } /* * Function: PreprocRestartFunction(int, void *) * * Purpose: This function gets called when Snort is restarting on a SIGHUP, * if there's any initialization or cleanup that needs to happen * it should be done here. * * Arguments: signal => the code of the signal that was issued to Snort * data => any arguments or data structs linked to this * functioin when it was registered, may be * needed to properly exit * * Returns: void function */ static void PreprocRestartFunction(int signal, void *foo) {
/* restart code goes here */ }
4. spp_template.h
/* $Id$ */ /* Snort Preprocessor Plugin Header File Template */ /* This file gets included in plugbase.h when it is integrated into the rest * of the program. */ #ifndef __SPP_TEMPLATE_H__ #define __SPP_TEMPLATE_H__ /* * list of function prototypes to export for this preprocessor */ void SetupTemplate(); #endif /* __SPP_TEMPLATE_H__ */
5. 预处理器的Hello World
5.1 复制模板
进入snort-2.9.15.1/
cp templates/spp_template.h src/preprocessors/spp_helloworld.h
cp templates/spp_template.c src/preprocessors/spp_helloworld.c
5.2 包含新文件
vim src/plugbase.c
在64行,插入
#include "preprocessors/spp_helloworld.h"
703行插入
SetupHelloWorld();
稍后会在spp_helloworld.c
编写这个函数并在spp_helloworld.h
中声明
保存退出
5.3 修改spp_helloworld.h
vim src/preprocessors/spp_helloworld.h
把 #ifndef
改掉
13行声明上文修改的那个函数
void SetupHelloWorld();
保存退出
5.4 修改spp_helloworld.c
我这个写的挺丑的,应该把声明放一块,函数放一块…下次一定改
先总体看一下,此文件应有如下几个函数及其声明,从上到下:
- 空函数:HelloWorldReloadFunction。snort reload时调用的函数,可不写函数体
- 声明:HelloWorldInit
- 函数:SetupHelloWorld。主程序启动,运行plugbase.c时,调用此函数。此函数内调用RegisterPreprocessor进行预处理器注册,以及调用HelloWorldInit进行预处理器的初始化
- 函数:HelloWorldMain。预处理器的主函数,即每收到一个符合条件的包都会调用此函数
- 函数:HelloWorldInit。预处理器的初始化函数,此函数内调用AddFuncToPreprocList,将预处理器的主函数(功能函数)HelloWorldMain添加到对应链表中。在新版snort中,需要有一句session_api->enable_preproc_all_ports(sc,PP_HELLOWORLD_RT, 0x01);
否则预处理器主函数不能正常工作。
vim src/preprocessors/spp_helloworld.c
58行,修改为
#include "spp_helloworld.h"
然后加上
#include "session_api.h" #include "decode.h"
// 添加函数到预处理器链表时用的 #define PROTO_MASK 0x0001
5.4.1 空函数 HelloWorldReloadFunction
// 重加载的函数,可不写函数体 void HelloWorldReloadFunction(){
}
5.4.2 声明 HelloWorldInit
// 声明 static void HelloWorldInit();
5.4.3 函数 主配置函数 SetupHelloWorld
修改函数SetupTemplate()
为SetupHelloWorld()
// 主配置函数 void SetupHelloWorld() {
/* * link the preprocessor keyword to the init function in * the preproc list */ // RegisterPreprocessor("keyword", TemplateInit); // DebugMessage(DEBUG_PLUGIN,"Preprocessor: Template is setup...\n"); #ifndef SNORT_RELOAD // 预处理器名称, 用于初始化预处理器的函数 RegisterPreprocessor("HelloWorld", HelloWorldInit); printf("*wuming-register* HelloWorld start\n"); #else // ReloadFunction可以暂时不写 RegisterPreprocessor("HelloWorld", HelloWorldInit, HelloWorldReloadFunction,NULL,NULL, NULL); printf("*wuming-register* HelloWorld reload\n"); #endif printf("*wuming-setup done*\n"); DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: HelloSnort is setup...\n");); }
5.4.4 函数 HelloWorldMain
static void PreprocFunction(Packet *p)
// 实际执行的主函数 static void HelloWorldMain(Packet *p){
printf("*wuming-main* Hello World's main function*\n"); }
5.4.5 函数 HelloWorldInit
修改 TemplateInit()
如下
static void HelloWorldInit(struct _SnortConfig *sc,u_char *args) {
// DebugMessage(DEBUG_PLUGIN,"Preprocessor: Template Initialized\n"); /* * parse the argument list from the rules file */ // ParseTemplateArgs(args); /* * perform any other initialization functions that are required here */ /* * Set the preprocessor function into the function list */ DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: HelloSnortInit Initialized\n");); // printf("HelloSnortInit ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^is setup"); // 参数分别为:结构体指针 预处理器实际执行的函数 处理器优先级 预定义常数 自定义解码类型标志 AddFuncToPreprocList(sc, HelloWorldMain, 0x01, PP_HELLOWORLD_RT, PROTO_MASK); session_api->enable_preproc_all_ports(sc,PP_HELLOWORLD_RT, 0x01); printf("*wuming-init done*\n"); // 不需要总结输出的话这行可以删掉 // 预处理器名称, //RegisterPreprocStats("HelloWorld", ProfinetPrintStats); // AddFuncToCleanExitList(PreprocCleanExitFunction, NULL); // AddFuncToRestartList(PreprocRestartFunction, NULL); }
保存退出
5.5 修改preprocids.h
spp_helloworld.c
中预定义常数PP_HELLOWORLD_RT
需要添加到 src/preprocids.h
vim src/preprocids.h
增加一行,然后PP_MAX
增加1
5.6 MakeFile.am
vim src/preprocessors/Makefile.am
把预处理器的两个文件添加到libspp_a_SOURCES
5.7 snort.conf
vim your_path/snort.conf
270行附近 step5,添加5.4中定义的预处理器名称HelloWorld
5.8 automake && make && make install
automake && make && make install
没有报错的话就可以启动了,有报错的话就回去DEBUG
一定要注意对应的函数名、常量名是否正确,否则会出现各种奇怪的BUG
5.9 启动snort
我使用-A参数直接打印到控制台
snort -A console -i ens33 -c your_path/snort.conf
6. 完整的 spp_helloworld.c
再次说明一下,写的很丑,其实原来的模板中都有注释的,最好还是按对应的位置来写。
/* $Id$ */ /* Snort Preprocessor Plugin Source File Template */ /* spp_template * * Purpose: * * Preprocessors perform some function *once* for *each* packet. This is * different from detection plugins, which are accessed depending on the * standard rules. When adding a plugin to the system, be sure to * add the "Setup" function to the InitPreprocessors() function call in * plugbase.c! * * Arguments: * * This is the list of arguments that the plugin can take at the * "preprocessor" line in the rules file * * Effect: * * What the preprocessor does. Check out some of the default ones * (e.g. spp_frag2) for a good example of this description. * * Comments: * * Any comments? * */ #include <sys/types.h> #include <stdlib.h> #include <ctype.h> #include <rpc/types.h> /* * If you're going to issue any alerts from this preproc you * should include generators.h and event_wrapper.h */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "generators.h" #include "event_wrapper.h" #include "util.h" #include "plugbase.h" #include "parser.h" #include "session_api.h" #include "decode.h" /* * put in other inculdes as necessary */ /* * your preprocessor header file goes here if necessary, don't forget * to include the header file in plugbase.h too! */ #include "spp_helloworld.h" // 添加函数到预处理器链表时用的 #define PROTO_MASK 0x0001 /* * define any needed data structs for things like configuration */ typedef struct _TemplateData {
/* Your struct members here */ } TemplateData; /* * If you need to instantiate the preprocessor's * data structure, do it here */ TemplateData SomeData; /* * function prototypes go here */ static void TemplateInit(u_char *); static void ParseTemplateArgs(char *); static void PreprocFunction(Packet *); static void PreprocCleanExitFunction(int, void *); static void PreprocRestartFunction(int, void *); /* * Function: SetupTemplate() * * Purpose: Registers the preprocessor keyword and initialization * function into the preprocessor list. This is the function that * gets called from InitPreprocessors() in plugbase.c. * * Arguments: None. * * Returns: void function * */ // 重加载的函数,可不写 void HelloWorldReloadFunction(){
} // 声明 static void HelloWorldInit(); // 此函数用于调用下面的初始化函数 HelloWorldRTInit() void SetupHelloWorld() {
/* * link the preprocessor keyword to the init function in * the preproc list */ // RegisterPreprocessor("keyword", TemplateInit); // DebugMessage(DEBUG_PLUGIN,"Preprocessor: Template is setup...\n"); #ifndef SNORT_RELOAD // 预处理器名称, 初始化预处理器的函数 RegisterPreprocessor("HelloWorld", HelloWorldInit); printf("*wuming-register* HelloWorld start\n"); #else // ReloadFunction可以暂时不写 RegisterPreprocessor("HelloWorld", HelloWorldInit, HelloWorldReloadFunction,NULL,NULL, NULL); printf("*wuming-register* HelloWorld reload\n"); #endif printf("*wuming-setup done*\n"); DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: HelloSnort is setup...\n");); } // 实际执行的主函数 static void HelloWorldMain(Packet *p){
printf("*wuming-main* Hello World's main function*\n"); } /* * Function: TemplateInit(u_char *) * * Purpose: Calls the argument parsing function, performs final setup on data * structs, links the preproc function into the function list. * * Arguments: args => ptr to argument string * * Returns: void function * */ // 初始化预处理器 static void HelloWorldInit(struct _SnortConfig *sc,u_char *args) {
// DebugMessage(DEBUG_PLUGIN,"Preprocessor: Template Initialized\n"); /* * parse the argument list from the rules file */ // ParseTemplateArgs(args); /* * perform any other initialization functions that are required here */ /* * Set the preprocessor function into the function list */ DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: HelloSnortInit Initialized\n");); // 参数分别为:结构体指针 预处理器实际执行的函数 处理器优先级 预定义常数 自定义解码类型标志 AddFuncToPreprocList(sc, HelloWorldMain, 0x01, PP_HELLOWORLD_RT, PROTO_MASK); session_api->enable_preproc_all_ports(sc,PP_HELLOWORLD_RT, 0x01); printf("*wuming-init done*\n"); // 不需要总结输出的话这行可以删掉 // 预处理器名称, //RegisterPreprocStats("HelloWorld", ProfinetPrintStats); // session_api->enable_preproc_all_ports(sc, PP_HELLOWORLD_RT, PROTO_BIT_IP); // AddFuncToCleanExitList(PreprocCleanExitFunction, NULL); // AddFuncToRestartList(PreprocRestartFunction, NULL); } /* * Function: ParseTemplateArgs(char *) * * Purpose: Process the preprocessor arguments from the rules file and * initialize the preprocessor's data struct. This function doesn't * have to exist if it makes sense to parse the args in the init * function. * * Arguments: args => argument list * * Returns: void function * */ static void ParseTemplateArgs(char *args) {
/* your parsing function goes here, check out the other spp files for examples */ } /* * Function: PreprocFunction(Packet *) * * Purpose: Perform the preprocessor's intended function. This can be * simple (statistics collection) or complex (IP defragmentation) * as you like. Try not to destroy the performance of the whole * system by trying to do too much.... * * Arguments: p => pointer to the current packet data struct * * Returns: void function * */ static void PreprocFunction(Packet *p) {
/* your preproc function goes here.... */ /* * if you need to issue an alert from your preprocessor, check out * event_wrapper.h, there are some useful helper functions there */ } /* * Function: PreprocCleanExitFunction(int, void *) * * Purpose: This function gets called when Snort is exiting, if there's * any cleanup that needs to be performed (e.g. closing files) * it should be done here. * * Arguments: signal => the code of the signal that was issued to Snort * data => any arguments or data structs linked to this * functioin when it was registered, may be * needed to properly exit * * Returns: void function */ static void PreprocCleanExitFunction(int signal, void *data) {
/* clean exit code goes here */ } /* * Function: PreprocRestartFunction(int, void *) * * Purpose: This function gets called when Snort is restarting on a SIGHUP, * if there's any initialization or cleanup that needs to happen * it should be done here. * * Arguments: signal => the code of the signal that was issued to Snort * data => any arguments or data structs linked to this * functioin when it was registered, may be * needed to properly exit * * Returns: void function */ static void PreprocRestartFunction(int signal, void *foo) {
/* restart code goes here */ }
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/233419.html原文链接:https://javaforall.net