suricata匹配从入门到精通(五)----二次开发保护规则库

5 篇文章 0 订阅
3 篇文章 0 订阅

0x00 背景

开源的suricata资源包是没有做加密处理,如果想要保护资源包,需要二次开发修改suricata源码。

本文基于suricata6.0.1 版本https://github.com/OISF/suricata/archive/refs/tags/suricata-6.0.1.zip二开。

0x01 实践

通过debug,跟规则处理相关需要修改2个地方。

1. src/suricata.c
2. src/detect-engine-loader.c

3. src/detect.h  和 configure.ac 应该是没改

修改suricata.c

原 237行下面加了2句:
extern int py_env_init();
extern void py_env_finilize();


修改 void PostConfLoadedDetectSetup(SCInstance *suri) 方法
原2350行后新增1句:
py_env_init();

原2827行新增1句:
py_env_finilize();

修改 src/detect-engine-loader.c

新增2个方法的实现:

PyObject * pModule = NULL;
PyObject * pFunc = NULL;

int py_env_init()
{
    const char *module_name = "hello2";
    const char *module_method = "test";
    
    Py_Initialize();//调用Py_Initialize()进行初始化

    PyRun_SimpleString("import sys");
    //PyRun_SimpleString("import logrec");
    PyRun_SimpleString("sys.path.append('/opt/ids/objectdir')");
    
    pModule = PyImport_ImportModule(module_name);//调用的Python文件名
    if (!pModule) {
        SCLogError(SC_ERR_OPENING_RULE_FILE, "Failed to load \"%s\"", module_name);
        return -1;
    }
    
    pFunc = PyObject_GetAttrString(pModule, module_method);//调用的函数名
    //创建参数:
    //PyObject *pArgs = PyTuple_New(1);
    //PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", "Hello Python!!"));
    if (!pFunc) {
        SCLogError(SC_ERR_OPENING_RULE_FILE, "Cannot find python function \"%s\"", module_method);
        return -1;
    }

    return 0;
}


void py_env_finilize()
{
    Py_DECREF(pFunc);
    Py_DECREF(pModule);
    Py_Finalize();//调用Py_Finalize,和Py_Initialize相对应的.
}

上面代码的作用是引入 /opt/ids/objectdir 路径下的 hello2.py 并执行它里面的 test() 方法。

再根据源代码 detect-engine-loader.c中的方法DetectLoadSigFile() 新增一个方法:DetectLoadEncryptSigFile() 用于读取加密文件:

static void GetContentFromSigFile(char *content)
{
    PyObject *pReturn = NULL;
        
    //pReturn=PyEval_CallObject(pFunc, pArgs);//调用函数,并传入参数pArgs
    if (pFunc && PyCallable_Check(pFunc)) {
        pReturn=PyEval_CallObject(pFunc, NULL);
        if (pReturn) {
            char *result = NULL;
            PyArg_Parse(pReturn, "s", &result);
            if (result) {
                strncpy(content, result, strlen(result) > SIG_RULE_MAX_BUFFER_SIZE ? SIG_RULE_MAX_BUFFER_SIZE : strlen(result));
            } else {
                SCLogError(SC_ERR_OPENING_RULE_FILE, "Result parse error");
            }
                
            Py_DECREF(pReturn);
        } else {
            SCLogError(SC_ERR_OPENING_RULE_FILE, "Call python method failed");
        }
    }
}


static int my_split(char **dst, char *src, char const *sep)
{
    int num = 0;
    char *tmp = NULL;
    for (dst[num] =strtok_r(src, sep, &tmp); dst[num] != NULL; dst[++num] = strtok_r(NULL, sep, &tmp));
    return num;
}


static int DetectLoadEncryptSigFile(DetectEngineCtx *de_ctx, char *sig_file,
        int *goodsigs, int *badsigs)
{
    Signature *sig = NULL;
    int good = 0, bad = 0;
    char line[DETECT_MAX_RULE_SIZE] = "";
    size_t offset = 0;
    int lineno = 0, multiline = 0;
    char *p[SIG_RULE_MAX_NUM];
    const char *token = "\r\n";
    int i;
    char *content = (char *)malloc(SIG_RULE_MAX_BUFFER_SIZE);
    (*goodsigs) = 0;
    (*badsigs) = 0;

    memset(content, 0, SIG_RULE_MAX_BUFFER_SIZE);
    GetContentFromSigFile(content);
    if (content == NULL) {
        SCLogError(SC_ERR_OPENING_RULE_FILE, "opening rule file %s:", sig_file);
        return -1;
    }

    int num = my_split(p, content, token);
    //while(fgets(line + offset, (int)sizeof(line) - offset, fp) != NULL) {
    for (i = 0; i < num; i++) {
        strncpy(line + offset, p[i], (int)sizeof(line) - offset);
        lineno++;
        size_t len = strlen(line);

        /* ignore comments and empty lines */
        if (line[0] == '\n' || line [0] == '\r' || line[0] == ' ' || line[0] == '#' || line[0] == '\t')
            continue;

        /* Check for multiline rules. */
        while (len > 0 && isspace((unsigned char)line[--len]));
        if (line[len] == '\\') {
            multiline++;
            offset = len;
            if (offset < sizeof(line) - 1) {
                /* We have room for more. */
                continue;
            }
            /* No more room in line buffer, continue, rule will fail
             * to parse. */
        }

        /* Check if we have a trailing newline, and remove it */
        len = strlen(line);
        if (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
            line[len - 1] = '\0';
        }

        /* Reset offset. */
        offset = 0;

        de_ctx->rule_file = sig_file;
        de_ctx->rule_line = lineno - multiline;

        sig = DetectEngineAppendSig(de_ctx, line);
        if (sig != NULL) {
            if (rule_engine_analysis_set || fp_engine_analysis_set) {
                RetrieveFPForSig(de_ctx, sig);
                if (fp_engine_analysis_set) {
                    EngineAnalysisFP(de_ctx, sig, line);
                }
                if (rule_engine_analysis_set) {
                    EngineAnalysisRules(de_ctx, sig, line);
                }
            }
            SCLogDebug("signature %"PRIu32" loaded", sig->id);
            good++;
        } else {
            if (!de_ctx->sigerror_silent) {
                SCLogError(SC_ERR_INVALID_SIGNATURE, "error parsing signature \"%s\" from "
                        "file %s at line %"PRId32"", line, sig_file, lineno - multiline);

                if (!SigStringAppend(&de_ctx->sig_stat, sig_file, line, de_ctx->sigerror, (lineno - multiline))) {
                    SCLogError(SC_ERR_MEM_ALLOC, "Error adding sig \"%s\" from "
                            "file %s at line %"PRId32"", line, sig_file, lineno - multiline);
                }
                if (de_ctx->sigerror) {
                    de_ctx->sigerror = NULL;
                }
            }
            if (rule_engine_analysis_set) {
                EngineAnalysisRulesFailure(line, sig_file, lineno - multiline);
            }
            if (!de_ctx->sigerror_ok) {
                bad++;
            }
        }
        multiline = 0;
    }
    free(content);

    *goodsigs = good;
    *badsigs = bad;
    return 0;
}

0x02 后记

本文只是抛砖引玉,hello2里面的代码读者也可以自行发挥想象力去编写,目的是读取加密的规则库。分享一下我的设计理念,这份代码使用了python调用c编译的so而已 :) 以后有机会再细讲吧~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值