⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smb_andx_decode.c

📁 著名的入侵检测系统snort的最新版本的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * smb_andx_decode.c * * Copyright (C) 2004-2006 Sourcefire,Inc * * 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. * * Description: * * This performs the decoding of SMB AndX commands. * * NOTES: * - 08.12.04:  Initial Development.  SAS * */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdlib.h>#ifdef HAVE_WCHAR_H#include <wchar.h>#endif#include <string.h>#include "debug.h"#include "bounds.h"#include "snort_dcerpc.h"#include "smb_structs.h"#include "smb_andx_structs.h"#include "smb_andx_decode.h"#include "dcerpc_util.h"#include "dcerpc.h"#define FIELD_ACCT_NAME 0#define FIELD_PRIM_DOMAIN 1#define SESS_AUTH_FIELD(i) ((i == FIELD_ACCT_NAME) ? "AccountName" : ((i == FIELD_PRIM_DOMAIN) ? "PrimaryDomain"  : "Unknown"))#define FIELD_NATIVE_OS 0#define FIELD_NATIVE_LANMAN 1#define SESS_NATIVE_FIELD(i) ((i == FIELD_NATIVE_OS) ? "NativeOS" : ((i == FIELD_NATIVE_LANMAN) ? "NativeLanMan" : "Unknown"))/* Externs */extern DCERPC         *_dcerpc;extern SFSnortPacket  *_dcerpc_pkt;extern u_int8_t        _disable_smb_fragmentation;extern u_int16_t       _max_frag_size;static void ReassembleSMBWriteX(SMB_WRITEX_REQ *writeX, u_int8_t *smb_data);static int SMB_Fragmentation(u_int8_t *smb_hdr, SMB_WRITEX_REQ *writeX,                               u_int8_t *smb_data, u_int16_t data_size);static int GetSMBStringLength(u_int8_t *data, u_int16_t data_size, int unicode);#ifdef DEBUG_DCERPC_PRINTstatic void PrintSMBString(char *pre, u_int8_t *str, u_int16_t str_len, int unicode);#endif/* smb_data is guaranteed to be at least an SMB_WRITEX_REQ length away from writeX * if it's farther it's because there was padding */static void ReassembleSMBWriteX(SMB_WRITEX_REQ *writeX, u_int8_t *smb_data){    SMB_WRITEX_REQ temp_writeX;    u_int16_t      smb_hdr_len = sizeof(SMB_HDR) + sizeof(NBT_HDR);    u_int16_t      writeX_len = (u_int16_t)(smb_data - (u_int8_t *)writeX);    u_int32_t      check_len;    int            ret;    int            padding = writeX_len - sizeof(SMB_WRITEX_REQ);    check_len = (u_int32_t)smb_hdr_len + (u_int32_t)writeX_len + (u_int32_t)_dcerpc->write_andx_buf_len;    /* Make sure we have room to fit into alternate buffer */    if ( check_len > _dpd.altBufferLen )    {        DEBUG_WRAP(DebugMessage(DEBUG_DCERPC, "Reassembled SMB packet greater than %d bytes, skipping.",															_dpd.altBufferLen));        goto dcerpc_fragfree;    }    /* Mock up header */    ret = SafeMemcpy(&temp_writeX, writeX, sizeof(SMB_WRITEX_REQ), &temp_writeX, (u_int8_t *)&temp_writeX + sizeof(SMB_WRITEX_REQ));    if (ret == 0)    {        DEBUG_WRAP(DebugMessage(DEBUG_DCERPC, "WriteAndX header too big: %u, skipping SMB reassembly.",                                 _dpd.altBufferLen));        goto dcerpc_fragfree;    }    temp_writeX.remaining = smb_htons(_dcerpc->write_andx_buf_len);    temp_writeX.dataLength = smb_htons(_dcerpc->write_andx_buf_len);    temp_writeX.dataOffset = smb_htons(sizeof(SMB_HDR) + sizeof(SMB_WRITEX_REQ) + padding);    temp_writeX.andXCommand = 0xFF;    temp_writeX.andXOffset = 0x0000;    /* Copy headers into buffer */    /* SMB Header */    ret = SafeMemcpy(_dpd.altBuffer, _dcerpc_pkt->payload, smb_hdr_len,                            _dpd.altBuffer, _dpd.altBuffer + _dpd.altBufferLen);    if ( ret == 0 )    {        DEBUG_WRAP(DebugMessage(DEBUG_DCERPC, "WriteAndX header too big: %u, skipping SMB reassembly.",															_dpd.altBufferLen));        goto dcerpc_fragfree;    }    _dcerpc_pkt->normalized_payload_size = smb_hdr_len;        /* Write AndX header */    ret = SafeMemcpy(_dpd.altBuffer + _dcerpc_pkt->normalized_payload_size, &temp_writeX,                     sizeof(SMB_WRITEX_REQ), _dpd.altBuffer, _dpd.altBuffer + _dpd.altBufferLen);    if ( ret == 0 )    {        DEBUG_WRAP(DebugMessage(DEBUG_DCERPC, "WriteAndX header too big: %u, skipping SMB reassembly.",															_dpd.altBufferLen));        goto dcerpc_fragfree;    }    _dcerpc_pkt->normalized_payload_size += sizeof(SMB_WRITEX_REQ);    /* Account for optional padding byte in WriteAndX header.  It is never used so we don't write it. */    _dcerpc_pkt->normalized_payload_size += padding;        /* Copy data into buffer */    ret = SafeMemcpy(_dpd.altBuffer + _dcerpc_pkt->normalized_payload_size, _dcerpc->write_andx_buf,                    _dcerpc->write_andx_buf_len, _dpd.altBuffer, _dpd.altBuffer + _dpd.altBufferLen);    if ( ret == 0 )    {        DEBUG_WRAP(DebugMessage(DEBUG_DCERPC, "WriteAndX header too big: %u, skipping SMB reassembly.",															_dpd.altBufferLen));        goto dcerpc_fragfree;    }    _dcerpc_pkt->normalized_payload_size += _dcerpc->write_andx_buf_len;    _dcerpc_pkt->flags |= FLAG_ALT_DECODE;    if (_dcerpc->write_andx_buf_len > 0)        ProcessDCERPCMessage(_dcerpc_pkt->payload + sizeof(NBT_HDR),                             sizeof(SMB_HDR) + writeX_len,                             _dcerpc->write_andx_buf, _dcerpc->write_andx_buf_len);dcerpc_fragfree:    /* Get ready for next write */    DCERPC_FragFree(_dcerpc->write_andx_buf, _dcerpc->write_andx_buf_size);    _dcerpc->write_andx_buf = NULL;    _dcerpc->write_andx_buf_len = 0;    _dcerpc->write_andx_buf_size = 0;    _dcerpc->fragmentation &= ~SMB_FRAGMENTATION;    _dcerpc->fragmentation &= ~SUSPEND_FRAGMENTATION;}int SMB_Fragmentation(u_int8_t *smb_hdr, SMB_WRITEX_REQ *writeX, u_int8_t *smb_data, u_int16_t data_size){    u_int16_t writeX_length, temp_len;    int       success = 0;    int ret = 0;    /* Check for fragmentation */    if ( _disable_smb_fragmentation )        return 0;    /* If not yet reassembling, attempt to parse as full DCE/RPC packet */    if ( !(_dcerpc->fragmentation & SMB_FRAGMENTATION) )    {        success = ProcessDCERPCMessage(smb_hdr, smb_data - smb_hdr, smb_data, data_size);        if ( success )            return 0;    }    /* Set up writeX buffer to save SMB data.  Ignore dataLengthHigh, since we won't        handle fragments that big.  */    writeX_length = data_size;    /* Allocate space for buffer        For now, ignore offset, since servers seem to */    if ( _dcerpc->fragmentation & SUSPEND_FRAGMENTATION )        return 0;    if ( _dcerpc->write_andx_buf == NULL )    {        if ( writeX_length > _max_frag_size )            writeX_length = _max_frag_size;        _dcerpc->write_andx_buf = (u_int8_t *) DCERPC_FragAlloc(NULL, 0, &writeX_length);        if ( writeX_length == 0 )        {            DEBUG_WRAP(DebugMessage(DEBUG_DCERPC, "Memcap reached, ignoring SMB fragmentation reassembly.\n"););            DCERPC_FragFree(_dcerpc->write_andx_buf, 0);            _dcerpc->write_andx_buf = NULL;            _dcerpc->fragmentation |= SUSPEND_FRAGMENTATION;            return 0;        }                if ( !_dcerpc->write_andx_buf )            DynamicPreprocessorFatalMessage("Failed to allocate space for first SMB Write AndX\n");        _dcerpc->write_andx_buf_size = writeX_length;        _dcerpc->write_andx_buf_len  = 0;    }    else    {        u_int16_t new_size;        if ( writeX_length > _max_frag_size )            writeX_length = _max_frag_size;        if ( _dcerpc->write_andx_buf_size >= (0xFFFF - writeX_length) )        {            DEBUG_WRAP(DebugMessage(DEBUG_DCERPC, "SMB fragmentation overflow.\n"););            _dcerpc->fragmentation |= SUSPEND_FRAGMENTATION;                        DCERPC_FragFree(_dcerpc->write_andx_buf, _dcerpc->write_andx_buf_size);            _dcerpc->write_andx_buf = NULL;            _dcerpc->write_andx_buf_len = 0;            _dcerpc->write_andx_buf_size = 0;            return 0;        }        new_size = _dcerpc->write_andx_buf_size + writeX_length;        _dcerpc->write_andx_buf = (u_int8_t *) DCERPC_FragAlloc(_dcerpc->write_andx_buf,                                             _dcerpc->write_andx_buf_size, &new_size);                    if ( new_size == _dcerpc->write_andx_buf_size )        {            DEBUG_WRAP(DebugMessage(DEBUG_DCERPC, "Memcap reached, suspending SMB fragmentation reassembly.\n"););            _dcerpc->fragmentation |= SUSPEND_FRAGMENTATION;                        DCERPC_FragFree(_dcerpc->write_andx_buf, _dcerpc->write_andx_buf_size);            _dcerpc->write_andx_buf = NULL;            _dcerpc->write_andx_buf_len = 0;            _dcerpc->write_andx_buf_size = 0;            return 0;        }        if ( !_dcerpc->write_andx_buf )            DynamicPreprocessorFatalMessage("Failed to reallocate space for SMB Write AndX\n");        _dcerpc->write_andx_buf_size = new_size;    }    /* SMB frag */    if ( writeX_length > (_dcerpc->write_andx_buf_size - _dcerpc->write_andx_buf_len) )    {        writeX_length = _dcerpc->write_andx_buf_size - _dcerpc->write_andx_buf_len;    }    /* Make sure data to be copied is within source buffer */    if ( (smb_data + writeX_length) > (_dcerpc_pkt->payload + _dcerpc_pkt->payload_size) )    {        temp_len = _dcerpc_pkt->payload + _dcerpc_pkt->payload_size - smb_data;        if ( writeX_length > temp_len )        {            writeX_length = temp_len;        }    }    ret = SafeMemcpy(_dcerpc->write_andx_buf + _dcerpc->write_andx_buf_len, smb_data, writeX_length,                     _dcerpc->write_andx_buf, _dcerpc->write_andx_buf + _dcerpc->write_andx_buf_size);    if (ret == 0)    {        DCERPC_FragFree(_dcerpc->write_andx_buf, _dcerpc->write_andx_buf_size);        _dcerpc->write_andx_buf = NULL;        _dcerpc->write_andx_buf_len = 0;        _dcerpc->write_andx_buf_size = 0;        _dcerpc->fragmentation |= SUSPEND_FRAGMENTATION;        return 0;    }    _dcerpc->write_andx_buf_len += writeX_length;    _dcerpc->fragmentation |= SMB_FRAGMENTATION;    if ( IsCompleteDCERPCMessage(_dcerpc->write_andx_buf, _dcerpc->write_andx_buf_len) )    {        ReassembleSMBWriteX(writeX, smb_data);        _dcerpc->fragmentation &= ~SMB_FRAGMENTATION;    }    return 0;}/* IPC$ has to occur at the end of this path - path_len should include null termination */static int IsIPC(u_int8_t *path, int path_len, u_int32_t isUnicode){    const u_int8_t ipc[] = {'I', 'P', 'C', '$', '\0'};    const u_int16_t ipc_len = 5;    const u_int8_t unicode_ipc[] = {'I', '\0', 'P', '\0', 'C', '\0', '$', '\0', '\0', '\0'};    const u_int16_t unicode_ipc_len = 10;    if (isUnicode)    {        if (path_len < unicode_ipc_len)            return 0;        /* go to end of path then back up the length of the          * unicode_ipc string */        path = (path + path_len) - unicode_ipc_len;        if (memcmp(path, unicode_ipc, unicode_ipc_len) == 0)            return 1;    }    else    {        if (path_len < ipc_len)            return 0;        /* go to end of path and back up the length of the         * ipc string */        path = (path + path_len) - ipc_len;        if (memcmp(path, ipc, ipc_len) == 0)            return 1;    }            return 0;}/* returns -1 if not null terminated  * returns -2 for other error * otherwise returns length of null terminated string * including null terminating bytes */static int GetSMBStringLength(u_int8_t *data, u_int16_t data_size, int unicode){    u_int16_t size_left;    if (data == NULL)        return -2;    size_left = data_size;    if (unicode)    {        while (size_left >= sizeof(uni_char_t))        {            size_left -= sizeof(uni_char_t);            if (*((uni_char_t *)data) == 0x0000)            {                return (int)(data_size - size_left);            }            data += sizeof(uni_char_t);        }    }    else    {        while (size_left >= sizeof(char))        {            size_left -= sizeof(char);            if (*((char *)data) == 0x00)            {                return (int)(data_size - size_left);            }            data += sizeof(char);        }    }    return -1;}#ifdef DEBUG_DCERPC_PRINTstatic void PrintSMBString(char *pre, u_int8_t *str, u_int16_t str_len, int unicode){    if (pre == NULL || str == NULL || str_len == 0)        return;    printf("%s", pre);    if (unicode)    {        int i = 0;        while (i < str_len)        {            printf("%c", str[i]);            i += sizeof(uni_char_t);        }    }    else    {        printf("%.*s", str_len, str);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -