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

📄 smb_andx_decode.c

📁 Snort为国际上著名的轻量型入侵防御系统,为国内多家著名“自主知识产权”网络安全公司所使用。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 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. * * Description: * * This performs the decoding of SMB AndX commands. * * NOTES: * - 08.12.04:  Initial Development.  SAS * */#include <stdlib.h>#include <wchar.h>#include "debug.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 void ReassembleSMBWriteX(SMB_WRITEX_REQ *writeX, u_int8_t *smb_data){    SMB_WRITEX_REQ temp_writeX;    unsigned int   smb_hdr_len = (u_int8_t *)writeX - _dcerpc_pkt->payload;    unsigned int   writeX_len = smb_data - (u_int8_t *)writeX;    /* Make sure we have room to fit into alternate buffer */    if ( (smb_hdr_len + writeX_len + _dcerpc->write_andx_buf_len) > _dpd.altBufferLen )    {        _dpd.logMsg("Reassembled SMB packet greater than %d bytes, skipping.",															_dpd.altBufferLen);        return;    }    /* Mock up header */    memcpy(&temp_writeX, writeX, writeX_len);    temp_writeX.remaining = _dcerpc->write_andx_buf_len;    temp_writeX.dataLength = _dcerpc->write_andx_buf_len;    /* Copy headers into buffer */    /* SMB Header */    memcpy(_dpd.altBuffer, _dcerpc_pkt->payload, smb_hdr_len);    _dcerpc_pkt->normalized_payload_size = smb_hdr_len;        /* Write AndX header */    memcpy(_dpd.altBuffer + _dcerpc_pkt->normalized_payload_size, &temp_writeX, writeX_len);    _dcerpc_pkt->normalized_payload_size += writeX_len;    /* Copy data into buffer */    memcpy(_dpd.altBuffer + _dcerpc_pkt->normalized_payload_size, _dcerpc->write_andx_buf, _dcerpc->write_andx_buf_len);    _dcerpc_pkt->normalized_payload_size += _dcerpc->write_andx_buf_len;    _dcerpc_pkt->flags |= FLAG_ALT_DECODE;    ProcessDCERPCMessage(_dcerpc_pkt->payload, _dcerpc->write_andx_buf, _dcerpc->write_andx_buf_len);    /* 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_char    fragmented = 0;    u_int16_t writeX_length;    u_char    success = 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, 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 = writeX->dataLength;    /* Allocate space for buffer        For now, ignore offset, since servers seem to */    if ( !(_dcerpc->fragmentation & SUSPEND_FRAGMENTATION) )    {        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 ( !_dcerpc->write_andx_buf )                _dpd.fatalMsg("Failed to allocate space for SMB Write AndX\n");                    if ( writeX_length == 0 )            {                DEBUG_WRAP(_dpd.debugMsg(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;            }            _dcerpc->write_andx_buf_size = writeX_length;            _dcerpc->write_andx_buf_len  = 0;        }        else        {            u_int16_t new_size;            new_size = _dcerpc->write_andx_buf_size + writeX->dataLength;            _dcerpc->write_andx_buf = (u_int8_t *) DCERPC_FragAlloc(_dcerpc->write_andx_buf,                                                 _dcerpc->write_andx_buf_size, &new_size);            if ( !_dcerpc->write_andx_buf )                _dpd.fatalMsg("Failed to allocate space for SMB Write AndX\n");                    if ( new_size == _dcerpc->write_andx_buf_size )            {                DEBUG_WRAP(_dpd.debugMsg(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;            }            _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;    }    memcpy(_dcerpc->write_andx_buf + _dcerpc->write_andx_buf_len, smb_data, writeX_length);    _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;}static int IsIPC(u_int8_t *s, u_int16_t len, u_int32_t isUnicode){    u_int16_t i;    u_int8_t unicode_ipc[] = { 'I', '\0', 'P', '\0', 'C', '\0', '$', '\0' };    if ( isUnicode )    {        if ( len < 8 )            return 0;        for ( i = 0; i < (len - 8)/2; i++ )        {            if ( memcmp(s+(i*2), unicode_ipc, 8) == 0 )                return 1;        }    }    else    {        if ( len < 5 )            return 0;        for ( i = 0; i < (len - 5); i++ )        {            if ( memcmp(s+i, "\\IPC$", 5) == 0 )                return 1;        }    }    return 0;}int SkipBytes(u_int8_t *data, u_int16_t size){    u_int16_t i = 0;    while ( *data != 0 && i < size )    {        data++;        i++;    }    return i;}int SkipBytesWide(u_int8_t *data, u_int16_t size){    u_int16_t i = 0;    while ( *data != 0 && i < size )    {        data += 2;        i += 2;    }    return i;}int ProcessSMBTreeConnXReq(SMB_HDR *smbHdr, u_int8_t *data, u_int16_t size, u_int16_t total_size){    SMB_TREE_CONNECTX_REQ *treeConnX = (SMB_TREE_CONNECTX_REQ *)data;    u_int16_t byteCount = smb_ntohs(treeConnX->byteCount);    u_int16_t passwdLen = smb_ntohs(treeConnX->passwdLen);    unsigned char *smb_data = data + sizeof(SMB_TREE_CONNECTX_REQ);    int skipBytes = 1;    int isIPC = 0;    size -= sizeof(SMB_TREE_CONNECTX_REQ);    /* Sanity check */    if ( byteCount > size )        return 0;    /* Password data */    if (passwdLen > 0 && byteCount > 0)    {        /* This passwd will always be ASCII -- equiv of         * CaseInsensitivePasswd field from SessSetupAndX message */#ifdef DEBUG_DCERPC_PRINT        printf("Password: %.*s\n", passwdLen, smb_data);#endif        /* Skip past the password -- no terminating NULL */        if ( passwdLen > size )            return 0;        smb_data += passwdLen;        if ( byteCount < passwdLen )            return 0;        byteCount -= (passwdLen);    }    /* Get path */    if (HAS_UNICODE_STRINGS(smbHdr)) /* Service field is ALWAYS ascii */    {        if (*smb_data != '\0')        {#ifdef DEBUG_DCERPC_PRINT            wprintf(L"Path: %s\n", smb_data);#endif            skipBytes = SkipBytesWide(smb_data, byteCount) + 2;        }        isIPC = IsIPC(smb_data, byteCount, 1L);    }    else    {        if (*smb_data != '\0')        {#ifdef DEBUG_DCERPC_PRINT            printf("Path: %s\n", smb_data);#endif            skipBytes = SkipBytes(smb_data, size) + 1;        }        isIPC = IsIPC(smb_data, byteCount, 0L);    }    smb_data += skipBytes;    byteCount -= skipBytes;    if ( isIPC && _dcerpc->smb_state == STATE_START )        _dcerpc->smb_state = STATE_GOT_TREE_CONNECT;    /* Print out service field */#ifdef DEBUG_DCERPC_PRINT    if (*smb_data != '\0')    {        printf("Service: %s\n", smb_data);    }#endif    /* Handle next andX command in this packet */    if (treeConnX->andXCommand != SMB_NONE)    {        u_int16_t data_size;        u_int16_t andXOffset = smb_ntohs(treeConnX->andXOffset);        if ( andXOffset > total_size )            return 0;              /* Make sure we don't backtrack or look at the same data again */        if ( andXOffset <= (data - (u_int8_t *)smbHdr) )            return 0;        /* Skip header, get size of remaining data */        data_size = total_size - andXOffset;        /* Next block is at smbHdr + smb_ntohs(sess_setupx_req->andXOffset) */        return ProcessNextSMBCommand(treeConnX->andXCommand, smbHdr,                (u_int8_t *)smbHdr + andXOffset, data_size, total_size);            }    return 0;}int ProcessSMBNTCreateX(SMB_HDR *smbHdr, u_int8_t *data, u_int16_t size, u_int16_t total_size){    SMB_NTCREATEX_REQ *ntCreateX = (SMB_NTCREATEX_REQ *)data;#ifdef DEBUG_DCERPC_PRINT    int byteCount = smb_ntohs(ntCreateX->byteCount);    unsigned char *smb_data = data + sizeof(SMB_NTCREATEX_REQ);        /* Appears to be a pad in there to word-align if unicode */    if (HAS_UNICODE_STRINGS(smbHdr))    {        smb_data++;        byteCount--;    }    if (byteCount > 0)    {        int i=0;        printf("Create/Open: ");        for (i=0;i<byteCount;)        {             if (HAS_UNICODE_STRINGS(smbHdr))            {                wprintf(L"%c", smb_data[i]);                i+=2;            }            else            {                printf("%c", smb_data[i]);                i++;            }        }        printf("\n");    }#endif    if ( _dcerpc->smb_state == STATE_GOT_TREE_CONNECT )        _dcerpc->smb_state = STATE_GOT_NTCREATE;    /* Handle next andX command in this packet */    if (ntCreateX->andXCommand != SMB_NONE)    {        u_int16_t data_size;        u_int16_t andXOffset = smb_ntohs(ntCreateX->andXOffset);        if ( andXOffset >= total_size )            return 0;               /* Make sure we don't backtrack or look at the same data again */        if ( andXOffset <= (data - (u_int8_t *)smbHdr) )            return 0;        /* Skip header, get size of remaining data */        data_size = total_size - andXOffset;        /* Next block is at smbHdr + smb_ntohs(sess_setupx_req->andXOffset) */        return ProcessNextSMBCommand(ntCreateX->andXCommand, smbHdr,            (u_int8_t *)smbHdr + andXOffset, data_size, total_size);            }    return 0;}int ProcessSMBWriteX(SMB_HDR *smbHdr, u_int8_t *data, u_int16_t size, u_int16_t total_size){    SMB_WRITEX_REQ *writeX = (SMB_WRITEX_REQ *)data;    u_int8_t       *dce_stub_data;    u_int16_t       data_size;    /* Only process WriteAndX packet if it is part of a DCE/RPC session */    if ( _dcerpc->smb_state != STATE_GOT_NTCREATE )    {        return 0;    }    if ( writeX->dataOffset >= total_size )    {        return 0;    }    dce_stub_data = (u_int8_t *)smbHdr + writeX->dataOffset;#ifdef DEBUG_DCERPC_PRINT    if (writeX->dataLength > 0)    {        int i=0;        printf("Write: ");        for (i=0;i<writeX->dataLength;i++)        {            printf("%c", dce_stub_data[i]);        }        printf("\n");    }#endif    /* Get size of actual remaining SMB data in packet */    data_size = total_size - (data - (u_int8_t *) smbHdr) - sizeof(SMB_HDR);    SMB_Fragmentation((u_int8_t *) smbHdr, writeX, dce_stub_data, data_size);    /* Handle next andX command in this packet */    if (writeX->andXCommand != SMB_NONE)    {        u_int16_t andXOffset = smb_ntohs(writeX->andXOffset);        if ( andXOffset >= total_size )

⌨️ 快捷键说明

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