snort 소스 코드 분석의 규칙 구조 분석 (2)
9826 단어 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;
}