snort加入egd工控插件

一 加入审计回调函数

// 全局声明
typedef void (*Egd_save_action_record)(void *, void *, int);   
Egd_save_action_record save_action_record = NULL;
// 初始化赋值
save_action_record = _dpd.icsSaveActionRecord;
// 调用
(*save_action_record)(p, &savemdb, ENUM_ACTION_EGD);

1.审计回调函数三个参数:

(1)void *p:指向snort解码后的网络分组包SFSnortPacket *p

(2)void *mdb:IcsSaveMdb对象指针,保存协议深度解析后的结果

(3)int type:协议的cid,标识协议的枚举值

2.审计回调函数作用:

开发snort.c里ICSSaveActionMDB和SaveActionMDB函数,审计回调函数最终会调用snort.c里的ICSSaveActionMDB和SaveActionMDB函数,分别用于将mdb内容拷贝到工控审计和传统审计的共享内存块,由审计业务进程消费后执行各种业务处理。

二 全局对象_dpd

dpd是一个非常重要的全局对象,它被所有插件引用,其定义在sf dynamic_preproc_lib,c中:

DynamicPreprocessorData _dpd;
PREPROC_LINKAGE int InitializePreprocessor(DynamicPreprocessorData *dpd)    // 初始化_dpd
{
    ...
    _dpd = *dpd;    // 结构体拷贝
    DYNAMIC_PREPROC_SETUP();// 调用插件的SetUp函数
}

(1)DynamicPreprocessorData数据结构:

定义在sf_dynamic_preprocessor.h中

typedef struct _ DynamicPreprocessorData {
    ...
    Save_action_record saveActionRecord;
    Save_action_record icsSaveActionRecord;
    ...
}DynamicPreprocessorData;

(2)_dpd赋值

saveActionRecord和icsSaveActionRecord分别是保存传统审计和工控审计的回调函数,它们在sf_dynamic_plugins.c的InitDynamicPreprocessors被赋值:

void InitDynamicPreprocessors(void)
{
    DynamicPreprocessorData preprocData;
    ...
    preprocData.icsSaveActionRecord = ICSSaveActionMDB; // ICSSaveActionMDB定义在snort.cc
    ...
    return InitDynamicPreprocessorPlugins(&preprocData);
}
 
int InitDynamicPreprocessorPlugins(DynamicPreprocessorData *info)
{
    DynamicPreprocessorPlugin *plugin;  // 指向插件链表(双向链表)
    plugin = loadedPreprocessorPlugins; // 插件链表头结点指针
    while (plugin)
    {
        int i = plugin->initFunc(info);      // 调用InitializePreprocessor 将info赋给全局对象_dpd
        ...
    }
}

(3)插件初始化_dpd

snort本身是单进程处理业务,当snort接收到数据包时,所有插件都会被遍历一遍,根据snort.conf配置从而进行相应处理。

(4)插件引用_dpd

dpd在sf_dynamic_preprocessor.h中声明为extern DynamicPreprocessorData _dpd;而每个插件头文件又包含了sf_dynamic_preprocessor.h,因此每个插件都可以引用到_dpd。

三 插件Setup函数

所有插件都有一个Setup函数,如SetupEgd,形如:

void SetupEgd(void)
{
    ...
    _dpd.registerPreproc("egd", EgdInit);
}

SetupEgd定义在spp_egd.c:

#define SetupEgd DYNAMIC_PREPROC_SETUP

这样InitializePreprocessor就可以Setup各个插件了。Setup函数又会调用pluginbase.c的RegisterPreprocessors,对插件进行初始化:

void RegisterPreprocessors(const char *keyword, PreprocConfigFunc pp_config_func)
{
    PreprocConfigFuncNode *node = (PreprocConfigFuncNode *)SnortAlloc(sizeof(PreprocConfigFuncNode));
    ...
    else
    {
        ...
        last->next = node;   // 将node插入链表最后
    }
    ...
}

RegisterPreprocessors会将插件的Init函数插入PreprocConfigFuncNode类型链表的末尾。

函数调用链:SetupEgd=》registerPreproc=》RegisterPreprocessors

四 插件处理函数

所有插件都有一个处理函数,如ProcessEgd,形如:

static void ProcessEgd(void *packetPtr, void *context)
{
    EgdSessionData *egdSessionData = NULL;
    // 以下过程是对egd报文进行解析,并保存解析结果
    ...
}

而ProcessEgd是由_dpd的addPreproc调用:

_dpd.addPreproc(sc, ProcessEgd, PROIRTY_APPLICATION, PP_EGD, PROTO_BIT_TCP | PROTO_BIT_UDP);
// addPreproc是指向sf_dynamic_plugins.c的AddPreprocessor
void AddPreprocessor(struct _SnortConfig *sc, void (*pp_func)(void *, void *), uint16_t priority, uint32_t preproc_id, uint32_t proto_mask) {
    ...
    return (void *)AddFuncToPreprocList(sc, preprocessorFunc,  priority, preproc_id, proto_mask);
}
// AddFuncToPreprocList是定义在pluginbase.c中
PreprocEvalFuncNode *AddFuncToPreprocList(SnortConfig *sc, PreprocEvalFunc pp_eval_func, uint16_t priority, uint32_t preproc_id, uint32_t proto_mask)
{
    ...
    tSfPolicyId policy_id = getParserPolicy(sc);    // 从传入的snort配置读取策略id
    ...
    p = sc->targeted_policies[policy_id];    // 获取具体策略指针
    ...
    else
    {
        PreprocEvalFuncNode *tmp = p->preproc_eval_funcs;
        // 从该策略处理函数链表中查找一个不同preproc_id并且优先级高结点,将pp_func插入该结点前
    }
    ...
    p->num_preprocs++;   // 累加该策略对应的处理函数数量
    ...
    return node;        // 返回链表中该结点
}

即pluginbase将策略对应的插件处理函数组织成链表,当插件调用addPreproc时都会向该链表插入一个新结点,并且链表是按优先级从高到低排序,越往头结点位置的结点优先级越高,也优先被snort调用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值