snort 源码分析之 模式匹配引擎接口 SearchAPI 源码分析(AC算法)

/*
 *  基于snort-2.9.5的源码进行分析
 *  src/preprocessors/str_search.h|.c
 */

/*
 * t_search 结构用于管理SearchAPI对象
 */
typedef struct tag_search
{
    /*
     * mpse 由mpseNew函数创建
     */
    void *mpse;
    /*
     *  所有模式串中最长串的长度
     */
    unsigned int max_len;
    /*
     * 该引擎在创建时就默认设置为1
     */
    int in_use;
} t_search;

typedef struct _search_api
{
    int (*search_init)(unsigned int);

    int (*search_reinit)(unsigned int);

    void (*search_free)(void);

    void (*search_add)(unsigned int, const char *, unsigned int, int);

    void (*search_prep)(unsigned int);

    int (*search_find)(unsigned int, const char *, unsigned int, int, MatchFunction); 

    /* 6/1/06*/
    void (*search_free_id)(unsigned id);
    
    int (*search_get_handle)(void);
    int (*search_put_handle)(unsigned int);

    /*
     * 创建多模式匹配引擎接口函数  
     */
    void * (*search_instance_new)(void);
    /*
     * 释放多模式匹配引擎接口函数  
     */
    void   (*search_instance_free)(void * instance);
    /*
     * 增加模式串接口函数  
     */
    void   (*search_instance_add) (void * instance, const char *s, unsigned int s_len, int s_id);
    /*
     * 模式串预处理接口函数   :比如 创建trie 和构建自动机
     */
    void   (*search_instance_prep)(void * instance );
    /*
     * 匹配函数   :MatchFunction:匹配成功后的回调函数,可执行一些相关操作
     */
    int    (*search_instance_find)(void * instance, const char *s, unsigned int s_len, int confine, MatchFunction); 
    
} SearchAPI;

/* API exported by this module */
SearchAPI searchAPI =
{
    SearchInit,
    SearchReInit,
    SearchFree,
    SearchAdd,
    SearchPrepPatterns,
    SearchFindString,
    SearchFreeId,
    SearchGetHandle,
    SearchPutHandle,
    /*
     * 创建引擎的函数
     */
    SearchInstanceNew,
    /*
     * 释放引擎的函数
     */
    SearchInstanceFree,
    /*
     * 增加模式串函数
     */
    SearchInstanceAdd,
    /*
     * 引擎预处理函数:构建trie 自动机
     */
    SearchInstancePrepPatterns,
    /*
     * 搜索函数
     */
    SearchInstanceFindString,
};

SearchAPI *search_api = &searchAPI;

接下来分析上面提及的那几个函数的实现

1:创建对象

/*
 * 创建mpse管理对象和mpse对象
 */
void *  SearchInstanceNew(void)
{
    /* 创建管理对象 */
    t_search * search = malloc(sizeof(t_search));
    if( !search )
        return NULL;

    /* 创建mpse对象, 通过MPSE_AC_BNFA宏设置,多模式匹配使用的算法*/
    search->mpse  = mpseNew(MPSE_AC_BNFA, MPSE_DONT_INCREMENT_GLOBAL_COUNT,
                            NULL, NULL, NULL);
    if (search-> mpse == NULL )
    {
        free(search);
        return NULL;
    }
    search->in_use=1;
    search->max_len=0;

    return search;
}

2:释放对象

void SearchInstanceFree( void * instance )
{
    t_search * search = (t_search*)instance;
    if( instance )
    {
        mpseFree( search->mpse );
        free( instance );
    }
}

3:增加模式串

/*
 *  instance : 管理对象
 *  pat : 模式串
 *  pat_len : 模式串长度
 *  id : 模式串所在模式串数组中的索引,例如 html_patterns
 */
void SearchInstanceAdd( void*instance, const char *pat, unsigned int pat_len, int id)
{
    t_search * search = (t_search*)instance;

    /* 添加模式串至mpse引擎中*/
    if( search && search->mpse )
        mpseAddPattern( search->mpse, (void *)pat, pat_len, 1, 0, 0, 0, (void *)(long) id, 0);

    /* 更新模式串的最大长度*/
    if ( search && pat_len > search->max_len )
         search->max_len = pat_len;

}

4:预处理模式串(生成自动机)

/*
 * instance : 管理对象
 */
void SearchInstancePrepPatterns(void * instance)
{
    t_search * search = (t_search*)instance;
    if( search && search->mpse )
    {
        /* 在调用完SearchInstanceAdd后,调用本函数进行模式预处理编译*/
        mpsePrepPatterns( search->mpse, NULL, NULL);
    }
}

5:搜索查找

/*
 * 搜索函数
 * instance : 管理对象
 * str :源串
 * str_len : 源串长度
 * confine : 1 表示更新模式串的最大长度
 * Match : 匹配成功后的回调函数
 */
int  SearchInstanceFindString(void * instance,
                              const char *str,
                              unsigned int str_len,
                              int confine,
                              int (*Match) (void *, void *, int, void *, void *))
{
    int num;
    int start_state = 0;
    t_search * search = (t_search*)instance;

    if ( confine && (search->max_len > 0) )
    {
        if ( search->max_len < str_len )
        {
            str_len = search->max_len;
        }
    }
    num = mpseSearch( search->mpse, (unsigned char*)str, str_len, Match, (void *) str,
            &start_state);

    return num;

}

以上介绍了模式匹配引擎接口的几个关键函数。接下来结合snort源代码分析如何使用这些接口

以html_patterns为例进行分析:

/*
 * 结构定义 
 */
typedef struct _HiSearchToken               
{   
    /* 模式串*/
    char *name;
    /* 串长度*/
    int   name_len;
    /* 串所在数组中的索引*/
    int   search_id;
} HiSearchToken;

a:创建管理对象,并添加串数组,编译

/* 管理对象*/
void *hi_htmltype_search_mpse = NULL;

...
void HI_SearchInit(void)
{
...
    /* 创建 管理对象 实际调用SearchInstanceNew*/
    hi_htmltype_search_mpse = search_api->search_instance_new();
    if (hi_htmltype_search_mpse == NULL)
    {
        FatalError("%s(%d) Could not allocate memory for HTTP <script> type search.\n",
                                   __FILE__, __LINE__);
    }
    /* 循环添加串 */
    for (tmp = &html_patterns[0]; tmp->name != NULL; tmp++)
    {
        hi_html_search[tmp->search_id].name = tmp->name;
        hi_html_search[tmp->search_id].name_len = tmp->name_len;
        /* 添加串至 管理对象中*/
        search_api->search_instance_add(hi_htmltype_search_mpse, tmp->name, tmp->name_len, tmp->search_id);
    }

    /* 编译  html_patterns串 所有初始化工作完成*/
    search_api->search_instance_prep(hi_htmltype_search_mpse);
}

b:搜索


int hi_server_norm(HI_SESSION *Session, HttpSessionData *hsd)
{

...
     /* 查找过程, 如果成功调用HI_SearchStrFound 善后处理*/       
     script_found = search_api->search_instance_find(hi_htmltype_search_mpse, (const char *)js_start, (angle_bracket-js_start), 0 , HI_SearchStrFound); 

...
}


/*  返回1 表示 搜索成功*/
int HI_SearchStrFound(void *id, void *unused, int index, void *data, void *unused2)
{
    int search_id = (int)(uintptr_t)id;

    hi_search_info.id = search_id;
    hi_search_info.index = index;
    hi_search_info.length = hi_current_search[search_id].name_len;

    /* Returning non-zero stops search, which is okay since we only look for one at a time */
    return 1;
}

以上就分析完了snort的模式匹配引擎接口的使用

可以参考https://github.com/testwill/Multi-pattern-matching-engine中的mpse_test.c进行编写自己的测试程序进行使用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值