📄 sp_pattern_match.c
字号:
/*** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* $Id$ */#include <errno.h>#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef HAVE_STRINGS_H#include <strings.h>#endif#ifdef DEBUG#include <assert.h>#endif#include "sp_pattern_match.h"#include "bounds.h"#include "rules.h"#include "plugbase.h"#include "debug.h"#include "mstring.h"#include "util.h" #include "parser.h" /* why does parser.h define Add functions.. */#include "plugin_enum.h"#include "checksum.h"#include "inline.h"static void PayloadSearchInit(char *, OptTreeNode *, int);static void PayloadSearchListInit(char *, OptTreeNode *, int);static void ParseContentListFile(char *, OptTreeNode *, int);static void PayloadSearchUri(char *, OptTreeNode *, int);static void ParsePattern(char *, OptTreeNode *, int);static int CheckANDPatternMatch(Packet *, struct _OptTreeNode *, OptFpList *);static int CheckORPatternMatch(Packet *, struct _OptTreeNode *, OptFpList *);static int CheckUriPatternMatch(Packet *, struct _OptTreeNode *, OptFpList *);static void PayloadSearchOffset(char *, OptTreeNode *, int);static void PayloadSearchDepth(char *, OptTreeNode *, int);static void PayloadSearchNocase(char *, OptTreeNode *, int);static void PayloadSearchRegex(char *, OptTreeNode *, int);static void PayloadSearchDistance(char *, OptTreeNode *, int);static void PayloadSearchWithin(char *, OptTreeNode *, int);static void PayloadSearchRawbytes(char *, OptTreeNode *, int);static void PayloadReplaceInit(char *, OptTreeNode *, int);static PatternMatchData * ParseReplacePattern(char *, OptTreeNode *);int PayloadReplace(Packet *, struct _OptTreeNode *, OptFpList *, int depth);static int uniSearchReal(char *data, int dlen, PatternMatchData *pmd, int nocase);static PatternMatchData * NewNode(OptTreeNode *, int);void PayloadSearchCompile();int list_file_line; /* current line being processed in the list file */int lastType = PLUGIN_PATTERN_MATCH;u_int8_t *doe_ptr;int detect_depth; /* depth to the first char of the match */extern HttpUri UriBufs[URI_COUNT]; /* the set of buffers that we are using to match against set in decode.c */extern u_int8_t DecodeBuffer[DECODE_BLEN];extern char *file_name;extern int file_line;void SetupPatternMatch(){ RegisterPlugin("content", PayloadSearchInit); RegisterPlugin("content-list", PayloadSearchListInit); RegisterPlugin("offset", PayloadSearchOffset); RegisterPlugin("depth", PayloadSearchDepth); RegisterPlugin("nocase", PayloadSearchNocase); RegisterPlugin("rawbytes", PayloadSearchRawbytes); RegisterPlugin("regex", PayloadSearchRegex); RegisterPlugin("uricontent", PayloadSearchUri); RegisterPlugin("distance", PayloadSearchDistance); RegisterPlugin("within", PayloadSearchWithin); RegisterPlugin("replace", PayloadReplaceInit); DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Plugin: PatternMatch Initialized!\n"););}void PayloadReplaceInit(char *data, OptTreeNode * otn, int protocol){ PatternMatchData *idx; PatternMatchData *test_idx; if(!InlineMode()) return; idx = (PatternMatchData *) otn->ds_list[PLUGIN_PATTERN_MATCH]; if(idx == NULL) { FatalError("ERROR %s Line %d => Please place \"content\" rules " "before depth, nocase, replace or offset modifiers.\n", file_name, file_line); } test_idx = ParseReplacePattern(data, otn);#ifdef DEBUG printf("idx (%p) pattern_size (%d) replace_size (%d)\n", test_idx, test_idx->pattern_size, test_idx->replace_size);#endif if (test_idx && test_idx->pattern_size != test_idx->replace_size) { FatalError("ERROR %s Line %d => The length of the replacement " "string must be the same length as the content string.\n", file_name, file_line); }#ifdef DEBUG printf("PayLoadReplaceInit Added to rule!\n");#endif}/*************************************************************************//* *//* Sigh.... this should be part of ParsePattern, but that can wait *//* *//*************************************************************************/PatternMatchData * ParseReplacePattern(char *rule, OptTreeNode * otn){ unsigned char tmp_buf[2048]; /* got enough ptrs for you? */ char *start_ptr; char *end_ptr; char *idx; char *dummy_idx; char *dummy_end; char hex_buf[3]; u_int dummy_size = 0; int size; int hexmode = 0; int hexsize = 0; int pending = 0; int cnt = 0; int literal = 0; int exception_flag = 0; PatternMatchData *ds_idx; /* clear out the temp buffer */ bzero(tmp_buf, 2048); while(isspace((int)*rule)) rule++; if(*rule == '!') { exception_flag = 1; } /* find the start of the data */ start_ptr = index(rule, '"'); if(start_ptr == NULL) { FatalError("ERROR %s Line %d => Replace data needs to be " "enclosed in quotation marks (\")!\n", file_name, file_line); } /* move the start up from the beggining quotes */ start_ptr++; /* find the end of the data */ end_ptr = strrchr(start_ptr, '"'); if(end_ptr == NULL) { FatalError("ERROR %s Line %d => Replace data needs to be enclosed " "in quotation marks (\")!\n", file_name, file_line); } /* set the end to be NULL */ *end_ptr = '\0'; /* how big is it?? */ size = end_ptr - start_ptr; /* uh, this shouldn't happen */ if(size <= 0) { FatalError("ERROR %s Line %d => Bad pattern length!\n", file_name, file_line); } /* set all the pointers to the appropriate places... */ idx = start_ptr; /* set the indexes into the temp buffer */ dummy_idx = tmp_buf; dummy_end = (dummy_idx + size); /* why is this buffer so small? */ bzero(hex_buf, 3); memset(hex_buf, '0', 2); /* BEGIN BAD JUJU..... */ while(idx < end_ptr) { DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "processing char: %c\n", *idx);); switch(*idx) { case '|': DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Got bar... ");); if(!literal) { DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "not in literal mode... ");); if(!hexmode) { DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Entering hexmode\n");); hexmode = 1; } else { DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Exiting hexmode\n");); hexmode = 0; pending = 0; } if(hexmode) hexsize = 0; } else { DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "literal set, Clearing\n");); literal = 0; tmp_buf[dummy_size] = start_ptr[cnt]; dummy_size++; } break; case '\\': DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Got literal char... ");); if(!literal) { DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Setting literal\n");); literal = 1; } else { DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Clearing literal\n");); tmp_buf[dummy_size] = start_ptr[cnt]; literal = 0; dummy_size++; } break; default: if(hexmode) { if(isxdigit((int) *idx)) { hexsize++; if(!pending) { hex_buf[0] = *idx; pending++; } else { hex_buf[1] = *idx; pending--; if(dummy_idx < dummy_end) { tmp_buf[dummy_size] = (u_char) strtol(hex_buf, (char **) NULL, 16)&0xFF; dummy_size++; bzero(hex_buf, 3); memset(hex_buf, '0', 2); } else { FatalError("ERROR => ParsePattern() dummy " "buffer overflow, make a smaller " "pattern please! (Max size = 2048)\n"); } } } else { if(*idx != ' ') { FatalError("ERROR Line %d => What is this " "\"%c\"(0x%X) doing in your binary " "buffer? Valid hex values only please! " "(0x0 -0xF) Position: %d\n", file_line, (char) *idx, (char) *idx, cnt); } } } else { if(*idx >= 0x1F && *idx <= 0x7e) { if(dummy_idx < dummy_end) { tmp_buf[dummy_size] = start_ptr[cnt]; dummy_size++; } else { FatalError("ERROR Line %d=> ParsePattern() dummy " "buffer overflow!\n", file_line); } if(literal) { literal = 0; } } else { if(literal) { tmp_buf[dummy_size] = start_ptr[cnt]; dummy_size++; DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Clearing literal\n");); literal = 0; } else { FatalError("%s(%d)=> character value out " "of range, only hex characters allowed in binary content buffers\n", file_name, file_line); } } } break; } /* end switch */ dummy_idx++; idx++; cnt++; } /* ...END BAD JUJU */ /* error prunning */ if (literal) { FatalError("%s(%d)=> backslash escape is not " "completed\n", file_name, file_line); } if (hexmode) { FatalError("%s(%d)=> hexmode is not " "completed\n", file_name, file_line); } ds_idx = (PatternMatchData *) otn->ds_list[PLUGIN_PATTERN_MATCH]; while(ds_idx->next != NULL) ds_idx = ds_idx->next; if((ds_idx->replace_buf = (char *) calloc(dummy_size+1, sizeof(char))) == NULL) { FatalError("ERROR => ParsePattern() pattern_buf malloc filed!\n"); } //memcpy(ds_idx->replace_buf, tmp_buf, dummy_size); SafeMemcpy(ds_idx->replace_buf, tmp_buf, dummy_size, ds_idx->replace_buf, (ds_idx->replace_buf+dummy_size+1)); ds_idx->replace_size = dummy_size; DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "ds_idx (%p) replace_size(%d) replace_buf(%s)\n", ds_idx, ds_idx->replace_size, ds_idx->replace_buf);); return ds_idx;}int PayloadReplace(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list, int depth){ struct pseudoheader { u_int32_t sip, dip; u_int8_t zero; u_int8_t protocol; u_int16_t len; }; PatternMatchData *idx; struct pseudoheader ph; unsigned int ip_len; unsigned int hlen; //idx = (PatternMatchData *)otn->ds_list[PLUGIN_PATTERN_MATCH]; idx = (PatternMatchData *)fp_list->context; if (depth >= 0) { //memcpy(p->data+depth, idx->replace_buf, strlen(idx->replace_buf)); SafeMemcpy( (p->data + depth), idx->replace_buf, strlen(idx->replace_buf), p->data, (p->data + p->dsize + 1) );#ifdef GIDS InlineReplace();#endif /* calculate new checksum */ p->iph->ip_csum=0; hlen = IP_HLEN(p->iph) << 2; ip_len=ntohs(p->iph->ip_len); ip_len -= hlen; p->iph->ip_csum = in_chksum_ip((u_short *)p->iph, hlen); if (p->tcph) { p->tcph->th_sum = 0; ph.sip = (u_int32_t)(p->iph->ip_src.s_addr); ph.dip = (u_int32_t)(p->iph->ip_dst.s_addr); ph.zero = 0; ph.protocol = p->iph->ip_proto; ph.len = htons((u_short)ip_len); p->tcph->th_sum = in_chksum_tcp((u_short *)&ph, (u_short *)(p->tcph), ip_len); } else if (p->udph) { p->udph->uh_chk = 0; ph.sip = (u_int32_t)(p->iph->ip_src.s_addr); ph.dip = (u_int32_t)(p->iph->ip_dst.s_addr); ph.zero = 0; ph.protocol = p->iph->ip_proto; ph.len = htons((u_short)ip_len); p->udph->uh_chk = in_chksum_udp((u_short *)&ph, (u_short *)(p->udph), ip_len); } else if (p->icmph) { p->icmph->csum = 0; ph.sip = (u_int32_t)(p->iph->ip_src.s_addr); ph.dip = (u_int32_t)(p->iph->ip_dst.s_addr); ph.zero = 0; ph.protocol = p->iph->ip_proto; ph.len = htons((u_short)ip_len); p->icmph->csum = in_chksum_icmp((u_int16_t *)(p->icmph), ip_len); } } return 1;}static inline int computeDepth(int dlen, PatternMatchData * pmd) { /* do some tests to make sure we stay in bounds */ if((pmd->depth + pmd->offset) > dlen) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -