📄 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 Version 2 as** published by the Free Software Foundation. You may not use, modify or** distribute this program under any other version of the GNU General** Public License.**** 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$ *//* * 06/07/2007 - tw * Commented out 'content-list' code since it's considered broken and there * are no plans to fix it */#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"#define MAX_PATTERN_SIZE 2048static 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 PayloadSearchHttpBody(char *, OptTreeNode *, int);static void PayloadSearchHttpUri(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 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(const 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;const 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, OPT_TYPE_DETECTION); //RegisterPlugin("content-list", PayloadSearchListInit, OPT_TYPE_DETECTION); RegisterPlugin("offset", PayloadSearchOffset, OPT_TYPE_DETECTION); RegisterPlugin("depth", PayloadSearchDepth, OPT_TYPE_DETECTION); RegisterPlugin("nocase", PayloadSearchNocase, OPT_TYPE_DETECTION); RegisterPlugin("rawbytes", PayloadSearchRawbytes, OPT_TYPE_DETECTION); RegisterPlugin("uricontent", PayloadSearchUri, OPT_TYPE_DETECTION); RegisterPlugin("http_client_body", PayloadSearchHttpBody, OPT_TYPE_DETECTION); RegisterPlugin("http_uri", PayloadSearchHttpUri, OPT_TYPE_DETECTION); RegisterPlugin("distance", PayloadSearchDistance, OPT_TYPE_DETECTION); RegisterPlugin("within", PayloadSearchWithin, OPT_TYPE_DETECTION); RegisterPlugin("replace", PayloadReplaceInit, OPT_TYPE_DETECTION); 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){ char tmp_buf[MAX_PATTERN_SIZE]; /* got enough ptrs for you? */ char *start_ptr; char *end_ptr; char *idx; const char *dummy_idx; const 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; int ret; /* clear out the temp buffer */ bzero(tmp_buf, MAX_PATTERN_SIZE); 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) { if (dummy_size >= MAX_PATTERN_SIZE-1) { /* Have more data to parse and pattern is about to go beyond end of buffer */ FatalError("ParsePattern() dummy " "buffer overflow, make a smaller " "pattern please! (Max size = %d)\n", MAX_PATTERN_SIZE-1); } 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 = %d)\n", MAX_PATTERN_SIZE-1); } } } 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); ret = SafeMemcpy(ds_idx->replace_buf, tmp_buf, dummy_size, ds_idx->replace_buf, (ds_idx->replace_buf+dummy_size)); if (ret == SAFEMEM_ERROR) { FatalError("ERROR %s Line %d => SafeMemcpy failed\n", file_name, file_line); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -