Пример #1
0
/* 
 *  Content Option processing function
 * 
 *       p: packet data structure, same as the one found in snort.
 * content: data defined in the detection plugin for this rule content option
 *  cursor: updated to point the 1st byte after the match
 *
 * Returns: 
 *    > 0 : match found
 *    = 0 : no match found
 *    < 0 : error
 *
 * Predefined constants: 
 *    (see sf_snort_plugin_api.h for more values)
 *    CONTENT_MATCH   -  if content specifier is found within buffer 
 *    CONTENT_NOMATCH -  if content specifier is not found within buffer 
 * 
 * Notes:
 *   For multiple URI buffers, we scan each buffer, if any one of them 
 *   contains the content we return a match. This is essentially an OR
 *   operation.
 *
 *   Currently support:
 *    options:
 *      nocase
 *      offset
 *      depth
 *    buffers:
 *      normalized(alt-decode)
 *      raw
 *      uri
 *      post
 *      
 */
ENGINE_LINKAGE int contentMatch(void *p, ContentInfo* content, const u_int8_t **cursor)
{
    const u_int8_t * q = NULL;
    const u_int8_t * buffer_start;
    const u_int8_t * buffer_end = NULL;
    u_int  buffer_len;
    int    length;
    int    i;
    char   relative = 0;
    SFSnortPacket *sp = (SFSnortPacket *) p;

    if (content->flags & CONTENT_RELATIVE)
    {
        if( !cursor || !(*cursor) )
        {
            return CONTENT_NOMATCH;
        } 
        relative = 1;
    }

    if (content->flags & (CONTENT_BUF_URI | CONTENT_BUF_POST))
    {
        for (i=0;i<sp->num_uris; i++)
        {
            if ((content->flags & CONTENT_BUF_URI) && (i != HTTP_BUFFER_URI))
            {
                /* Not looking at the "URI" buffer...
                 * keep going. */
                continue;
            }

            if ((content->flags & CONTENT_BUF_POST) && (i != HTTP_BUFFER_CLIENT_BODY))
            {
                /* Not looking at the "POST" buffer...
                 * keep going. */
                continue;
            }

            if (relative)
            {
                if (checkCursorInternal(p, content->flags, content->offset, *cursor) <= 0)
                {
                    /* Okay, cursor is NOT within this buffer... */
                    continue;
                }
                buffer_start = *cursor + content->offset;
            }
            else
            {
                buffer_start = _ded.uriBuffers[i]->uriBuffer + content->offset;
            }

            if (_uri_buffer_end)
            {
                buffer_end = _uri_buffer_end;
            }
            else
            {
                buffer_end = _ded.uriBuffers[i]->uriBuffer + _ded.uriBuffers[i]->uriLength;
            }

            length = buffer_len = buffer_end - buffer_start;

            if (length <= 0)
            {
                continue;
            }
            
            /* Don't bother looking deeper than depth */
            if ( content->depth != 0 && content->depth < buffer_len )
            {
                buffer_len = content->depth;
            }

            q = hbm_match((HBM_STRUCT*)content->boyer_ptr,buffer_start,buffer_len);

            if (q)
            {
                if (content->flags & CONTENT_END_BUFFER)
                {
                    _uri_buffer_end = q;
                }
                if (cursor)
                {
                    *cursor = q + content->patternByteFormLength;
                }
                return CONTENT_MATCH;
            }
        }

        return CONTENT_NOMATCH;
    }

    if (relative)
    {
        if (checkCursorInternal(p, content->flags, content->offset, *cursor) <= 0)
        {
            return CONTENT_NOMATCH;
        }

        if ((content->flags & CONTENT_BUF_NORMALIZED) && (sp->flags & FLAG_ALT_DECODE))
        {
            if (_alt_buffer_end)
            {
                buffer_end = _alt_buffer_end;
            }
            else
            {         
                buffer_end = _ded.altBuffer + sp->normalized_payload_size;
            }
        }
        else
        {
            if (_buffer_end)
            {
                buffer_end = _buffer_end;
            }
            else
            {
                buffer_end = sp->payload + sp->payload_size;
            }
        }
        buffer_start = *cursor + content->offset;
    }
    else
    {
        if ((content->flags & CONTENT_BUF_NORMALIZED) && (sp->flags & FLAG_ALT_DECODE))
        {
            buffer_start = _ded.altBuffer + content->offset;
            if (_alt_buffer_end)
            {
                buffer_end = _alt_buffer_end;
            }
            else
            {
                buffer_end = _ded.altBuffer + sp->normalized_payload_size;
            }
        }
        else
        {
            buffer_start = sp->payload + content->offset;
            if (_buffer_end)
            {
                buffer_end = _buffer_end;
            }
            else
            {
                buffer_end = sp->payload + sp->payload_size;
            }
        }
    }
    length = buffer_len = buffer_end - buffer_start;

    if (length <= 0)
    {
        return CONTENT_NOMATCH;
    }

    /* Don't bother looking deeper than depth */
    if ( content->depth != 0 && content->depth < buffer_len )
    {
        buffer_len = content->depth;
    }

    q = hbm_match((HBM_STRUCT*)content->boyer_ptr,buffer_start,buffer_len);

    if (q)
    {
        if (content->flags & CONTENT_END_BUFFER)
        {
            if ((content->flags & CONTENT_BUF_NORMALIZED) && (sp->flags & FLAG_ALT_DECODE))
            {
                _alt_buffer_end = q;
            }
            else
            {
                _buffer_end = q;
            }
        }
        if (cursor)
        {
            *cursor = q + content->patternByteFormLength;
        }
        return CONTENT_MATCH;
    }

    return CONTENT_NOMATCH;
}
Пример #2
0
/*
** Search a body of text or data for paterns 
*/
int mwmSearch( void * pv,
               unsigned char * T, int n,
  int(*match)( void * id,  int index, void * data ),
               void * data )
{

      MWM_STRUCT * ps = (MWM_STRUCT*)pv;
      unsigned char *s;
      iPatCount += n;


      ConvCaseToUpperEx( S, T, n ); /* Copy and Convert to Upper Case */


      if( ps->msMethod == MTH_BM )
      {
         /* Boyer-Moore  */

         int i,nfound=0;
         unsigned char * Tx = NULL;

         for( i=0; i<ps->msNumPatterns; i++ )
         {
            s = &S[0];  /* Init this for each pattern we search */
            do
            {
                Tx = hbm_match( ps->msPatArray[i].psBmh, s, n );

                if( Tx )
                {
                   /* If we are case sensitive, do a final exact match test */
                   if( !ps->msPatArray[i].psNoCase )
                   {
                     if( memcmp(ps->msPatArray[i].psPatCase,&T[Tx-S],ps->msPatArray[i].psLen) )
                     {
                         if (++Tx < s + n)
                         {
                            n--;
                            s++;
                         }
                         else
                         {
                             n = 0;
                         }
                         continue; /* no match, continue with this pattern,
                                      or next if n == 0 */
                     }
                   }

                   nfound++;
  
                   if( match(ps->msPatArray[i].psID, (int)(Tx-S),data) )
                      return nfound;
                }

                break; /* on to next pattern */
            } while (n >= 0);
         }

         return nfound;

      }
      else /* MTH_MWM */
      {
         /* Wu-Manber */

         return ps->search( ps, S, n, T, match, data );
      }
}
static int contentMatchCommon(ContentInfo* content,
        const uint8_t *start_ptr, int dlen, const uint8_t **cursor)
{
    const uint8_t *q;
    const uint8_t *base_ptr;
    const uint8_t *end_ptr = start_ptr + dlen;
    int depth;
    char relative = (content->flags & CONTENT_RELATIVE) ? 1 : 0;

    if (relative)
    {
        // Sanity check to make sure the cursor isn't NULL and is within the
        // buffer we're searching.  It could be at the very end of the buffer
        // due to a previous match, but may have a negative offset here.
        if ((cursor == NULL) || (*cursor == NULL)
                || (*cursor < start_ptr) || (*cursor > end_ptr))
            return CONTENT_CURSOR_ERROR;

        base_ptr = *cursor;
        depth = dlen - (*cursor - start_ptr);
    }
    else
    {
        base_ptr = start_ptr;
        depth = dlen;
    }

    // Adjust base_ptr and depth based on offset/depth parameters.
    if (relative && ((content->offset != 0) || (content->depth != 0)))
    {
        if (content->offset != 0)
        {
            base_ptr += content->offset;
            depth -= content->offset;
        }

        // If the offset is negative and puts us before start_ptr
        // set base_ptr to start_ptr and adjust depth based on depth.
        if (base_ptr < start_ptr)
        {
            int delta = (int)content->depth - (start_ptr - base_ptr);
            base_ptr = start_ptr;
            depth = ((content->depth == 0) || (delta > dlen)) ? dlen : delta;
        }
        else if ((content->depth != 0) && ((int)content->depth < depth))
        {
            depth = (int)content->depth;
        }
    }
    else if ((content->offset != 0) || (content->depth != 0))
    {
        if (content->offset != 0)
        {
            base_ptr += content->offset;
            depth -= content->offset;
        }

        if ((content->depth != 0) && ((int)content->depth < depth))
            depth = content->depth;
    }

    // If the pattern size is greater than the amount of data we have to
    // search, there's no way we can match, so return error, however, return
    // CONTENT_NOMATCH here for the case where the match is inverted and there
    // is at least some data.
    if ((int)content->patternByteFormLength > depth)
    {
        if ((content->flags & NOT_FLAG) && (depth > 0))
            return CONTENT_NOMATCH;  // This will get inverted on return
        return CONTENT_CURSOR_ERROR;
    }

    q = hbm_match((HBM_STRUCT*)content->boyer_ptr, base_ptr, depth);

    if (q)
    {
        if (content->flags & CONTENT_END_BUFFER)
        {
            if ( HTTP_CONTENT(content->flags) )
                _uri_buffer_end = q;
            else if ((content->flags & CONTENT_BUF_NORMALIZED)
                    && _ded.Is_DetectFlag(SF_FLAG_ALT_DETECT) )
                _alt_detect_end = q;
            else if ((content->flags & CONTENT_BUF_NORMALIZED)
                    && _ded.Is_DetectFlag(SF_FLAG_ALT_DECODE) )
                _alt_buffer_end = q;
            else
                _buffer_end = q;
        }

        if (cursor)
            *cursor = q + content->patternByteFormLength;

        return CONTENT_MATCH;
    }

    return CONTENT_NOMATCH;
}
/*
 *  Content Option processing function
 *
 *       p: packet data structure, same as the one found in snort.
 * content: data defined in the detection plugin for this rule content option
 *  cursor: updated to point the 1st byte after the match
 *
 * Returns:
 *    > 0 : match found
 *    = 0 : no match found
 *    < 0 : error
 *
 * Predefined constants:
 *    (see sf_snort_plugin_api.h for more values)
 *    CONTENT_MATCH   -  if content specifier is found within buffer
 *    CONTENT_NOMATCH -  if content specifier is not found within buffer
 *
 * Notes:
 *   For multiple URI buffers, we scan each buffer, if any one of them
 *   contains the content we return a match. This is essentially an OR
 *   operation.
 *
 *   Currently support:
 *    options:
 *      nocase
 *      offset
 *      depth
 *    buffers:
 *      normalized(alt-decode)
 *      raw
 *      uri
 *      post
 *
 */
static int contentMatchInternal(void *p, ContentInfo* content, const uint8_t **cursor)
{
    const uint8_t * q = NULL;
    const uint8_t * buffer_start = NULL;
    const uint8_t * buffer_end = NULL;
    u_int  buffer_len;
    int    length;
    int    i;
    char   relative = 0;
    SFSnortPacket *sp = (SFSnortPacket *) p;

    /* This content is only used for fast pattern matching and
     * should not be evaluated */
    if (content->flags & CONTENT_FAST_PATTERN_ONLY)
        return CONTENT_MATCH;

    if (content->flags & CONTENT_RELATIVE)
    {
        if( !cursor || !(*cursor) )
        {
            return CONTENT_NOMATCH;
        }
        relative = 1;
    }

    /* Check for byte_extract variables and use them if present. */
    if (content->offset_location)
    {
        content->offset = *content->offset_location;
    }
    if (content->depth_location)
    {
        content->depth = *content->depth_location;
    }

    if (content->flags & URI_CONTENT_BUFS)
    {
        for (i=0; i<sp->num_uris; i++)
        {
            switch (i)
            {
                case HTTP_BUFFER_URI:
                    if (!(content->flags & CONTENT_BUF_URI))
                        continue; /* Go to next, not looking at URI buffer */
                    break;
                case HTTP_BUFFER_HEADER:
                    if (!(content->flags & CONTENT_BUF_HEADER))
                        continue; /* Go to next, not looking at HEADER buffer */
                    break;
                case HTTP_BUFFER_CLIENT_BODY:
                    if (!(content->flags & CONTENT_BUF_POST))
                        continue; /* Go to next, not looking at POST buffer */
                    break;
                case HTTP_BUFFER_METHOD:
                    if (!(content->flags & CONTENT_BUF_METHOD))
                        continue; /* Go to next, not looking at METHOD buffer */
                    break;
                case HTTP_BUFFER_COOKIE:
                    if (!(content->flags & CONTENT_BUF_COOKIE))
                        continue; /* Go to next, not looking at COOKIE buffer */
                    break;
                case HTTP_BUFFER_RAW_URI:
                    if (!(content->flags & CONTENT_BUF_RAW_URI))
                        continue; /* Go to next, not looking at RAW URI buffer */
                    break;
                case HTTP_BUFFER_RAW_HEADER:
                    if (!(content->flags & CONTENT_BUF_RAW_HEADER))
                        continue; /* Go to next, not looking at RAW HEADER buffer */
                    break;
                case HTTP_BUFFER_RAW_COOKIE:
                    if (!(content->flags & CONTENT_BUF_RAW_COOKIE))
                        continue; /* Go to next, not looking at RAW COOKIE buffer */
                    break;
                case HTTP_BUFFER_STAT_CODE:
                    if (!(content->flags & CONTENT_BUF_STAT_CODE))
                        continue; /* Go to next, not looking at STAT CODE buffer */
                    break;
                case HTTP_BUFFER_STAT_MSG:
                    if (!(content->flags & CONTENT_BUF_STAT_MSG))
                        continue; /* Go to next, not looking at STAT MSG buffer */
                    break;
                default:
                    /* Uh, what buffer is this? */
                    return CONTENT_NOMATCH;
            }

            if (!_ded.uriBuffers[i]->uriBuffer || (_ded.uriBuffers[i]->uriLength == 0))
                continue;

            if (relative)
            {
                if (checkCursorInternal(p, content->flags, content->offset, *cursor) <= 0)
                {
                    /* Okay, cursor is NOT within this buffer... */
                    continue;
                }
                buffer_start = *cursor + content->offset;
            }
            else
            {
                buffer_start = _ded.uriBuffers[i]->uriBuffer + content->offset;
            }

            buffer_end = _ded.uriBuffers[i]->uriBuffer + _ded.uriBuffers[i]->uriLength;

            length = buffer_len = buffer_end - buffer_start;

            if (length <= 0)
            {
                continue;
            }

            /* Don't bother looking deeper than depth */
            if ( content->depth != 0 && content->depth < buffer_len )
            {
                buffer_len = content->depth;
            }

            q = hbm_match((HBM_STRUCT*)content->boyer_ptr,buffer_start,buffer_len);

            if (q)
            {
                if (content->flags & CONTENT_END_BUFFER)
                {
                    _uri_buffer_end = q;
                }
                if (cursor)
                {
                    *cursor = q + content->patternByteFormLength;
                }
                return CONTENT_MATCH;
            }
        }

        return CONTENT_NOMATCH;
    }

    if (relative)
    {
        if (checkCursorInternal(p, content->flags, content->offset, *cursor) <= 0)
        {
            return CONTENT_NOMATCH;
        }

        if ((content->flags & CONTENT_BUF_NORMALIZED) && _ded.Is_DetectFlag(SF_FLAG_DETECT_ALL))
        {
            if(_ded.Is_DetectFlag(SF_FLAG_ALT_DETECT))
            {
                if (_alt_detect_end)
                {
                    buffer_end = _alt_detect_end;
                }
                else
                {
                    buffer_end = _ded.altDetect->data + _ded.altDetect->len;
                }
            }
            else if(_ded.Is_DetectFlag(SF_FLAG_ALT_DECODE))
            {
                if (_alt_buffer_end)
                {
                    buffer_end = _alt_buffer_end;
                }
                else
                {
                    buffer_end = _ded.altBuffer->data + _ded.altBuffer->len;
                }
            }
        }
        else
        {
            if(sp->normalized_payload_size)
            {
                buffer_end = sp->payload + sp->normalized_payload_size;
            }
            else if (_buffer_end)
            {
                buffer_end = _buffer_end;
            }
            else
            {
                buffer_end = sp->payload + sp->payload_size;
            }
        }
        buffer_start = *cursor + content->offset;
    }
    else
    {
        if ((content->flags & CONTENT_BUF_NORMALIZED) && _ded.Is_DetectFlag(SF_FLAG_DETECT_ALL))
        {
            if(_ded.Is_DetectFlag(SF_FLAG_ALT_DETECT))
            {
                buffer_start = _ded.altDetect->data + content->offset;
                if (_alt_detect_end)
                {
                    buffer_end = _alt_detect_end;
                }
                else
                {
                    buffer_end = _ded.altDetect->data + _ded.altDetect->len;
                }
            }
            else if(_ded.Is_DetectFlag(SF_FLAG_ALT_DECODE))
            {
                buffer_start = _ded.altBuffer->data + content->offset;
                if (_alt_buffer_end)
                {
                    buffer_end = _alt_buffer_end;
                }
                else
                {
                    buffer_end = _ded.altBuffer->data + _ded.altBuffer->len;
                }
            }
        }
        else
        {
            buffer_start = sp->payload + content->offset;
            if(sp->normalized_payload_size)
            {
                buffer_end = sp->payload + sp->normalized_payload_size;
            }
            else if (_buffer_end)
            {
                buffer_end = _buffer_end;
            }
            else
            {
                buffer_end = sp->payload + sp->payload_size;
            }
        }
    }
    length = buffer_len = buffer_end - buffer_start;

    if (length <= 0)
    {
        return CONTENT_NOMATCH;
    }

    /* Don't bother looking deeper than depth */
    if ( content->depth != 0 && content->depth < buffer_len )
    {
        buffer_len = content->depth;
    }

    q = hbm_match((HBM_STRUCT*)content->boyer_ptr,buffer_start,buffer_len);

    if (q)
    {
        if (content->flags & CONTENT_END_BUFFER)
        {
            if((content->flags & CONTENT_BUF_NORMALIZED) && _ded.Is_DetectFlag(SF_FLAG_ALT_DETECT))
            {
                _alt_detect_end = q;
            }
            else if ((content->flags & CONTENT_BUF_NORMALIZED) && _ded.Is_DetectFlag(SF_FLAG_ALT_DECODE))
            {
                _alt_buffer_end = q;
            }
            else
            {
                _buffer_end = q;
            }
        }
        if (cursor)
        {
            *cursor = q + content->patternByteFormLength;
        }
        return CONTENT_MATCH;
    }

    return CONTENT_NOMATCH;
}