snort 소스 코드 분석의 규칙 구조 분석 (2)

9826 단어 snort
전편 에 서 는 snort 의 규칙 을 대조 하여 그 규칙 필드 들 을 간단하게 소개 하 였 다.
다음은 규칙 헤드 와 규칙 옵션 의 데이터 구 조 를 살 펴 보 겠 습 니 다.

/*          */
typedef struct _RuleFpList
{
    /* context data for this test */
    /*           */
    void *context;

    /* rule check function pointer */
    /*             ,  :   ,     ,           :                          ,   */
    int (*RuleHeadFunc)(Packet *, struct _RuleTreeNode *, struct _RuleFpList *, int);

    /* pointer to the next rule function node */
    struct _RuleFpList *next;
} RuleFpList;

/*
 *    
 */
typedef struct _RuleTreeNode
{
    /*               */
    RuleFpList *rule_func; /* match functions.. (Bidirectional etc.. ) */

    /*      ,   */
    int head_node_number;

    /*               :RULE_TYPE__ALERT*/
    RuleType type;

    /*        IP */
    IpAddrSet *sip;
    /*   IP */
    IpAddrSet *dip;

    /*       : tcp udp */
    int proto;

    /*     */
    PortObject * src_portobject;
    /*      */
    PortObject * dst_portobject;

    /*    :      ,     :any  */
    uint32_t flags;     /* control flags */

    /* stuff for dynamic rules activation/deactivation */
    /*   Dynamic      */
    int active_flag;
    int activation_counter;
    int countdown;
    ActivateListNode *activate_list;

#if 0
    struct _RuleTreeNode *right;  /* ptr to the next RTN in the list */

    /** list of rule options to associate with this rule node */
    OptTreeNode *down;   
#endif

    /**points to global parent RTN list (Drop/Alert) which contains this 
     * RTN.
     */
    /*                alert*/
    struct _ListHead *listhead;

    /**reference count from otn. Multiple OTNs can reference this RTN with the same
     * policy.
     */
    /*          ,                     */
    unsigned int otnRefCount;

} RuleTreeNode;


/*       */
typedef struct _ListHead
{
    struct _OutputFuncNode *LogList;
    struct _OutputFuncNode *AlertList;
    struct _RuleListNode *ruleListNode;
} ListHead;

/*     ,         ListHead      ,           ,  name="snort",          ,    */
typedef struct _RuleListNode
{
    ListHead *RuleList;         /* The rule list associated with this node */
    RuleType mode;              /* the rule mode */
    int rval;                   /* 0 == no detection, 1 == detection event */
    int evalIndex;              /* eval index for this rule set */
    char *name;                 /* name of this rule list (for debugging)  */
    struct _RuleListNode *next; /* the next RuleListNode */
} RuleListNode;

앞에서 언급 한 규칙 헤드 는 많은 군더더기 가 존재 하 는데, 다음은 snort 가 어떻게 무 거 운 것 을 제거 하 는 지 분석한다.
snort 가 규칙 헤드 를 분석 할 때 ProcessHeadNode 함수 에서 findHeadNode 를 호출 하여 조회 하기 전에 같은 규칙 헤드 가 있 는 지,
rtn - > otnRefCount + 가 존재 하면 인용 수 를 증가 합 니 다. 그렇지 않 으 면 새로운 규칙 헤더 대상 을 만 들 고 각종 일치 하 는 반전 함 수 를 설정 합 니 다.
소스 코드 형식 으로 규칙 헤더 의 분석 절 차 를 분석 하 다.
static void ParseRule(SnortConfig *sc, SnortPolicy *p, char *args,
                      RuleType rule_type, ListHead *list)
{
...
    /*        ,        , tcp any any -> any any*/
    if (*args == '(')
    {
        test_rtn.flags |= ANY_DST_PORT;
        test_rtn.flags |= ANY_SRC_PORT;
        test_rtn.flags |= ANY_DST_IP;
        test_rtn.flags |= ANY_SRC_IP;
        test_rtn.flags |= BIDIRECTIONAL;
        test_rtn.type = rule_type;
        protocol = IPPROTO_TCP;

        roptions = args;

        DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, "Preprocessor Rule detected
");); } else { /* proto ip port dir ip port r*/ /* mpspit , '\t' , " \t", 7 , alert, 6 , , 7, num_toks , , , '\\' */ toks = mSplit(args, " \t", 7, &num_toks, '\\'); /* A rule might not have rule options */ if (num_toks < 6) { ParseError("Bad rule in rules file: %s", args); } /* , toks[6]: */ if (num_toks == 7) roptions = toks[6]; /* */ test_rtn.type = rule_type; ... /* Set the rule protocol - fatal errors if protocol not found */ /* :alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS */ /* */ protocol = GetRuleProtocol(toks[0]); test_rtn.proto = protocol; ... /* IP , snort_config targeted_policies ip_vartable $HOME_NET */ ProcessIP(sc, toks[1], &test_rtn, SRC, 0); ... /* IP , snort_config targeted_policies portVarTable PortObject */ if (ParsePortList(&test_rtn, portVarTable, nonamePortVarTable, toks[2], protocol, 0 /* =src port */ )) { ParseError("Bad source port: '%s'", toks[2]); } /* , */ if ((strcmp(toks[3], RULE_DIR_OPT__DIRECTIONAL) != 0) && (strcmp(toks[3], RULE_DIR_OPT__BIDIRECTIONAL) != 0)) { ParseError("Illegal direction specifier: %s", toks[3]); } /* New in version 1.3: support for bidirectional rules * This checks the rule "direction" token and sets the bidirectional * flag if the token = '<>' */ /* "->", "<>"*/ if (strcmp(toks[3], RULE_DIR_OPT__BIDIRECTIONAL) == 0) { DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Bidirectional rule!
");); test_rtn.flags |= BIDIRECTIONAL; } ... /* */ test_rtn.listhead = list; /* */ rtn = ProcessHeadNode(sc, &test_rtn, list); ... } }

 
규칙 헤드 리 셋 함수 소스 코드 분석
static RuleTreeNode * ProcessHeadNode(SnortConfig *sc, RuleTreeNode *test_node,
                                      ListHead *list)
{
    /*         */
    RuleTreeNode *rtn = findHeadNode(sc, test_node, getParserPolicy(sc));
    /*    ,     ,     */
    if (rtn == NULL)
    {
        DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Building New Chain head node
");); rtn = (RuleTreeNode *)SnortAlloc(sizeof(RuleTreeNode)); rtn->otnRefCount++; /* copy the prototype header info into the new header block */ XferHeader(test_node, rtn); head_count++; rtn->head_node_number = head_count; /* initialize the function list for the new RTN */ /* */ SetupRTNFuncList(rtn); /* add link to parent listhead */ rtn->listhead = list; ... } else { /* */ rtn->otnRefCount++; FreeRuleTreeNode(test_node); } return rtn; }

 
static void SetupRTNFuncList(RuleTreeNode * rtn)
{
    /*           ,         CheckBidirectional*/
    if(rtn->flags & BIDIRECTIONAL)
    {
        DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"CheckBidirectional->
");); AddRuleFuncToList(CheckBidirectional, rtn); } /* */ else { /* Attach the proper port checking function to the function list */ /* * the in-line "if's" check to see if the "any" or "not" flags have * been set so the PortToFunc call can determine which port testing * function to attach to the list */ PortToFunc(rtn, (rtn->flags & ANY_DST_PORT ? 1 : 0), (rtn->flags & EXCEPT_DST_PORT ? 1 : 0), DST); /* as above */ PortToFunc(rtn, (rtn->flags & ANY_SRC_PORT ? 1 : 0), (rtn->flags & EXCEPT_SRC_PORT ? 1 : 0), SRC); /* link in the proper IP address detection function */ AddrToFunc(rtn, SRC); /* last verse, same as the first (but for dest IP) ;) */ AddrToFunc(rtn, DST); } /* tack the end (success) function to the list */ /* snort , 1 , , */ AddRuleFuncToList(RuleListEnd, rtn); } /* 1, , 1 ok */ int RuleListEnd(Packet *p, struct _RuleTreeNode *rtn_idx, RuleFpList *fp_list, int check_ports) { return 1; } /* rfunc insert */ void AddRuleFuncToList(int (*rfunc) (Packet *, struct _RuleTreeNode *, struct _RuleFpList *, int), RuleTreeNode * rtn) { RuleFpList *idx; DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Adding new rule to list
");); idx = rtn->rule_func; if(idx == NULL) { rtn->rule_func = (RuleFpList *)SnortAlloc(sizeof(RuleFpList)); rtn->rule_func->RuleHeadFunc = rfunc; } else { while(idx->next != NULL) idx = idx->next; idx->next = (RuleFpList *)SnortAlloc(sizeof(RuleFpList)); idx = idx->next; idx->RuleHeadFunc = rfunc; } }

 
규칙 헤드 분석의 소스 분석 은 여기까지 입 니 다.
반전 함 수 를 어떻게 호출 하여 일치 하 는 지 보 세 요.
/*
 *       
 * rtn :    
 * p :    
 * check_ports :      
 */
int fpEvalRTN(RuleTreeNode *rtn, Packet *p, int check_ports)
{

...
    /*        1,   1   */
    if(!rtn->rule_func->RuleHeadFunc(p, rtn, rtn->rule_func, check_ports))
    {
        DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
                    "   => Header check failed, checking next node
");); DEBUG_WRAP(DebugMessage(DEBUG_DETECT, " => returned from next node check
");); PREPROC_PROFILE_END(ruleRTNEvalPerfStats); return 0; } ... /* 1*/ return 1; }

좋은 웹페이지 즐겨찾기