📄 dce2_smb.c
字号:
/**************************************************************************** * Copyright (C) 2008-2008 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. * **************************************************************************** * ****************************************************************************/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "dce2_smb.h"#include "dce2_tcp.h"#include "dce2_co.h"#include "snort_dce2.h"#include "dce2_config.h"#include "dce2_memory.h"#include "dce2_utils.h"#include "dce2_debug.h"#include "dce2_stats.h"#include "dce2_event.h"#include "smb.h"#include "sf_snort_packet.h"#include "sf_types.h"#include "debug.h"#include "sf_dynamic_preprocessor.h"#ifndef WIN32#include <arpa/inet.h> /* for ntohl */#endif /* WIN32 *//******************************************************************** * Global variables ********************************************************************//* There are some static variables in DCE2_SmbChained() *//******************************************************************** * Extern variables ********************************************************************/extern DCE2_Stats dce2_stats;extern DynamicPreprocessorData _dpd;extern char *dce2_smb_coms[];extern uint8_t dce2_smb_rbuf[];/******************************************************************** * Macros ********************************************************************/#define DCE2_TC__QUEUE_SIZE 10#define DCE2_TC__NOT_IPC DCE2_SENTINEL#define DCE2_TC__IPC 1#define DCE2_READ__QUEUE_SIZE 10#define DCE2_TRANS__QUEUE_SIZE 10/******************************************************************** * Private function prototypes ********************************************************************/static DCE2_Ret DCE2_NbssHdrChecks(DCE2_SmbSsnData *, const NbssHdr *);static DCE2_Ret DCE2_SmbHdrChecks(DCE2_SmbSsnData *, const SmbNtHdr *);static int DCE2_SmbInspect(DCE2_SmbSsnData *, const SmbNtHdr *);static void DCE2_SmbProcessData(DCE2_SmbSsnData *, const uint8_t *, uint32_t);static void DCE2_SmbHandleCom(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbHandleRawData(DCE2_SmbSsnData *, const uint8_t *, uint32_t);static void DCE2_SmbSessSetupAndX(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbLogoffAndX(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t, int);static DCE2_Ret DCE2_SmbTreeConnect(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbTreeConnectEnqueue(DCE2_SmbSsnData *, const SmbNtHdr *, const DCE2_Ret);static void DCE2_SmbTreeConnectAndX(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbTreeDisconnect(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbOpen(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbOpenAndX(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbNtCreateAndX(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbClose(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t, int);static void DCE2_SmbWrite(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbWriteBlockRaw(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbWriteAndClose(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbWriteAndX(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbTrans(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbTransSec(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbRead(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbReadBlockRaw(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbReadAndX(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static void DCE2_SmbRename(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static int DCE2_SmbGetComSize(DCE2_SmbSsnData *, const SmbNtHdr *, const SmbCommon *, const int);static int DCE2_SmbGetBcc(DCE2_SmbSsnData *, const SmbNtHdr *, const SmbCommon *, const uint16_t, const int);static INLINE DCE2_Ret DCE2_SmbCheckComSize(DCE2_SmbSsnData *, const uint32_t, const uint16_t, const int);static INLINE DCE2_Ret DCE2_SmbCheckBcc(DCE2_SmbSsnData *, const uint32_t, const uint16_t, const int);static INLINE DCE2_Ret DCE2_SmbCheckDsize(DCE2_SmbSsnData *, const uint32_t, const uint16_t, const uint16_t, const int);static INLINE DCE2_Ret DCE2_SmbCheckTotDcnt(DCE2_SmbSsnData *, const uint16_t, const uint16_t, const int);static INLINE DCE2_Ret DCE2_SmbCheckOffset(DCE2_SmbSsnData *, const uint8_t *, const uint8_t *, const uint32_t, const int);static INLINE void DCE2_SmbInvalidShareCheck(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);static INLINE void DCE2_SmbSetReadFidNode(DCE2_SmbSsnData *, uint16_t, uint16_t, uint16_t, int);static INLINE DCE2_SmbFidTrackerNode * DCE2_SmbGetReadFidNode(DCE2_SmbSsnData *);static void DCE2_SmbChained(DCE2_SmbSsnData *, const SmbNtHdr *, const SmbAndXCommon *, const int, const uint8_t *, uint32_t);static void DCE2_SmbIncComStat(const SmbNtHdr *);static void DCE2_SmbIncChainedStat(const SmbNtHdr *, const int, const SmbAndXCommon *);static void DCE2_WriteCoProcess(DCE2_SmbSsnData *, const SmbNtHdr *, const uint16_t, const uint8_t *, uint16_t);static void DCE2_SmbInsertUid(DCE2_SmbSsnData *, const uint16_t);static DCE2_Ret DCE2_SmbFindUid(DCE2_SmbSsnData *, const uint16_t);static void DCE2_SmbRemoveUid(DCE2_SmbSsnData *ssd, const uint16_t);static void DCE2_SmbInsertTid(DCE2_SmbSsnData *, const uint16_t);static DCE2_Ret DCE2_SmbFindTid(DCE2_SmbSsnData *, const uint16_t);static void DCE2_SmbRemoveTid(DCE2_SmbSsnData *, const uint16_t);static DCE2_SmbUTNode * DCE2_SmbFindUTNode(DCE2_SmbSsnData *, const uint16_t, const uint16_t);static void DCE2_SmbInsertFid(DCE2_SmbSsnData *, const uint16_t, const uint16_t, const uint16_t);static DCE2_SmbFidTrackerNode * DCE2_SmbFindFid(DCE2_SmbSsnData *, const uint16_t, const uint16_t, const uint16_t);static void DCE2_SmbRemoveFid(DCE2_SmbSsnData *, const uint16_t, const uint16_t, const uint16_t);static INLINE DCE2_SmbPMNode * DCE2_SmbInsertPMNode(DCE2_SmbSsnData *, const SmbNtHdr *, DCE2_SmbFidNode *, const uint16_t);static INLINE void DCE2_SmbRemovePMNode(DCE2_SmbSsnData *, const SmbNtHdr *);static INLINE DCE2_SmbPMNode * DCE2_SmbFindPMNode(DCE2_SmbSsnData *, const SmbNtHdr *);static INLINE DCE2_Ret DCE2_SmbAddDataToPMNode(DCE2_SmbSsnData *, DCE2_SmbPMNode *, const uint8_t *, uint16_t, uint16_t);static void DCE2_SmbQueueTmpFid(DCE2_SmbSsnData *);static void DCE2_SmbInsertFidNode(DCE2_SmbSsnData *, const uint16_t, const uint16_t, const uint16_t, DCE2_SmbFidTrackerNode *);static INLINE void DCE2_SmbCleanFidNode(DCE2_SmbFidTrackerNode *);static INLINE void DCE2_SmbCleanUTNode(DCE2_SmbUTNode *);static INLINE void DCE2_SmbCleanPMNode(DCE2_SmbPMNode *);static int DCE2_SmbUTFCompare(const void *, const void *);static int DCE2_SmbUTPtreeCompare(const void *, const void *);static int DCE2_SmbPMCompare(const void *a, const void *b);static void DCE2_SmbFidDataFree(void *);static void DCE2_SmbUTDataFree(void *);static void DCE2_SmbFidTrackerDataFree(void *);static void DCE2_SmbPMDataFree(void *);static INLINE void DCE2_SmbResetForMissedPkts(DCE2_SmbSsnData *);static void DCE2_SmbSetMissedFids(DCE2_SmbSsnData *);static INLINE DCE2_Ret DCE2_SmbHandleSegmentation(DCE2_SmbSeg *, const uint8_t *, uint16_t, uint32_t, uint16_t *);static INLINE int DCE2_SmbIsSegBuf(DCE2_SmbSsnData *, const uint8_t *);static INLINE void DCE2_SmbSegAlert(DCE2_SmbSsnData *, DCE2_Event);static INLINE int DCE2_SmbIsRawData(DCE2_SmbSsnData *);static INLINE DCE2_SmbSeg * DCE2_SmbGetSegPtr(DCE2_SmbSsnData *);static INLINE uint32_t * DCE2_SmbGetIgnorePtr(DCE2_SmbSsnData *);/******************************************************************** * Function: * * Purpose: * * Arguments: * * Returns: * ********************************************************************/void DCE2_SmbInitRdata(uint8_t *nb_ptr){ NbssHdr *nb_hdr = (NbssHdr *)nb_ptr; SmbNtHdr *smb_hdr = (SmbNtHdr *)((uint8_t *)nb_hdr + sizeof(NbssHdr)); SmbLm10_WriteAndXReq *writex = (SmbLm10_WriteAndXReq *)((uint8_t *)smb_hdr + sizeof(SmbNtHdr)); nb_hdr->type = NBSS_SESSION_TYPE__MESSAGE; memcpy((void *)smb_hdr->smb_idf, (void *)"\xffSMB", sizeof(smb_hdr->smb_idf)); smb_hdr->smb_com = SMB_COM_WRITE_ANDX; writex->smb_wct = 12; writex->smb_com2 = SMB_COM_NO_ANDX_COMMAND; writex->smb_doff = SmbHtons(sizeof(SmbNtHdr) + sizeof(SmbLm10_WriteAndXReq));}/******************************************************************** * Function: * * Purpose: * * Arguments: * * Returns: * ********************************************************************/void DCE2_SmbSetRdata(DCE2_SmbSsnData *ssd, uint8_t *nb_ptr, uint16_t co_len){ NbssHdr *nb_hdr = (NbssHdr *)nb_ptr; SmbNtHdr *smb_hdr = (SmbNtHdr *)((uint8_t *)nb_hdr + sizeof(NbssHdr)); SmbLm10_WriteAndXReq *writex = (SmbLm10_WriteAndXReq *)((uint8_t *)smb_hdr + sizeof(SmbNtHdr)); uint32_t nb_len = sizeof(SmbNtHdr) + sizeof(SmbLm10_WriteAndXReq) + co_len; /* The data will get truncated anyway since we can only fit * 64K in the reassembly buffer */ if (nb_len > UINT16_MAX) nb_len = UINT16_MAX; nb_hdr->length = htons((uint16_t)nb_len); smb_hdr->smb_uid = SmbHtons(ssd->uid); smb_hdr->smb_tid = SmbHtons(ssd->tid); writex->smb_fid = SmbHtons(ssd->fid); writex->smb_countleft = SmbHtons(co_len); writex->smb_dsize = SmbHtons(co_len); writex->smb_bcc = SmbHtons(co_len);}/******************************************************************** * Function: * * Purpose: * * Arguments: * * Returns: * ********************************************************************/DCE2_SmbSsnData * DCE2_SmbSsnInit(void){ DCE2_SmbSsnData *ssd = (DCE2_SmbSsnData *)DCE2_Alloc(sizeof(DCE2_SmbSsnData), DCE2_MEM_TYPE__SMB_SSN); if (ssd == NULL) return NULL; ssd->req_uid = DCE2_SENTINEL; ssd->req_tid = DCE2_SENTINEL; ssd->read_fid_node.fid = DCE2_SENTINEL; ssd->br.smb_com = DCE2_SENTINEL; ssd->sst.uid = DCE2_SENTINEL; ssd->sst.tid = DCE2_SENTINEL; ssd->sst.ft_node.fid_node.uid = DCE2_SENTINEL; ssd->sst.ft_node.fid_node.tid = DCE2_SENTINEL; ssd->sst.ft_node.fid_node.fid = DCE2_SENTINEL; DCE2_CoInitTracker(&ssd->sst.ft_node.co_tracker); ssd->sst.ptree.ut_node.uid = DCE2_SENTINEL; ssd->sst.ptree.ut_node.tid = DCE2_SENTINEL; ssd->sst.ptree.ut_node.ft_node.fid_node.uid = DCE2_SENTINEL; ssd->sst.ptree.ut_node.ft_node.fid_node.tid = DCE2_SENTINEL; ssd->sst.ptree.ut_node.ft_node.fid_node.fid = DCE2_SENTINEL; DCE2_CoInitTracker(&ssd->sst.ptree.ut_node.ft_node.co_tracker); ssd->pm_node.pid = DCE2_SENTINEL; ssd->pm_node.mid = DCE2_SENTINEL; ssd->pm_node.fid_node.uid = DCE2_SENTINEL; ssd->pm_node.fid_node.tid = DCE2_SENTINEL; ssd->pm_node.fid_node.fid = DCE2_SENTINEL; DCE2_ResetRopts(&ssd->sd.ropts); dce2_stats.smb_sessions++; return ssd;}/******************************************************************** * Function: * * Purpose: * * Arguments: * * Returns: * ********************************************************************/void DCE2_SmbProcess(DCE2_SmbSsnData *ssd){ const SFSnortPacket *p = ssd->sd.wire_pkt; const uint8_t *data_ptr = p->payload; uint16_t data_len = p->payload_size; uint32_t *ignore_bytes = DCE2_SmbGetIgnorePtr(ssd); DCE2_SmbSeg *seg = DCE2_SmbGetSegPtr(ssd); uint32_t missed_bytes = DCE2_SsnGetMissedBytes(&ssd->sd); uint16_t overlap_bytes = DCE2_SsnGetOverlap(&ssd->sd); uint16_t nb_hdr_need = sizeof(NbssHdr); uint16_t smb_hdr_need = nb_hdr_need + sizeof(SmbNtHdr); DCE2_Ret status; DCE2_DEBUG_MSG(DCE2_DEBUG__SMB, "Processing SMB packet.\n"); dce2_stats.smb_pkts++; if (DCE2_SsnMissedPkts(&ssd->sd)) { if (*ignore_bytes != 0) { if (*ignore_bytes > missed_bytes) *ignore_bytes -= missed_bytes; else *ignore_bytes = 0; } DCE2_SmbResetForMissedPkts(ssd); } if (overlap_bytes != 0) { *ignore_bytes += overlap_bytes; } else if (*ignore_bytes != 0) { if (DCE2_SmbAutodetect(p) == DCE2_TRANS_TYPE__SMB) { DCE2_DEBUG_MSG(DCE2_DEBUG__SMB, "Autodetected SMB - " "resetting ignored bytes\n", *ignore_bytes); *ignore_bytes = 0; } } /* Have to account for segmentation. Even though stream will give * us larger chunks, we might end up in the middle of something */ while (data_len > 0) { if (*ignore_bytes) { DCE2_DEBUG_MSG(DCE2_DEBUG__SMB, "Ignoring %u bytes\n", *ignore_bytes); if (data_len <= *ignore_bytes) { *ignore_bytes -= data_len; return; } else { /* ignore bytes is less than UINT16_MAX */ DCE2_MOVE(data_ptr, data_len, (uint16_t)*ignore_bytes); *ignore_bytes = 0; } } if (ssd->br.smb_com != DCE2_SENTINEL) { /* If we never get responses to the raw commands, reset them */ if (((ssd->br.smb_com == SMB_COM_WRITE_BLOCK_RAW) && DCE2_SsnFromServer(ssd->sd.wire_pkt)) || ((ssd->br.smb_com == SMB_COM_READ_BLOCK_RAW) && DCE2_SsnFromClient(ssd->sd.wire_pkt))) { ssd->br.smb_com = DCE2_SENTINEL; } } if (DCE2_BufferIsEmpty(seg->buf)) { const SmbNtHdr *smb_hdr = NULL; uint32_t nb_len; uint16_t data_used; uint32_t nb_need; /* Not enough data for NetBIOS header ... add data to segmentation buffer */ if (data_len < nb_hdr_need) { DCE2_DEBUG_MSG(DCE2_DEBUG__SMB, "Data len(%u) < NetBIOS SS header(%u). " "Queueing data.\n", data_len, nb_hdr_need); DCE2_SmbHandleSegmentation(seg, data_ptr, data_len, nb_hdr_need, &data_used); return; } nb_len = NbssLen((NbssHdr *)data_ptr); nb_need = nb_hdr_need + nb_len; DCE2_DEBUG_MSG(DCE2_DEBUG__SMB, "NetBIOS SS len: %u\n", nb_len); /* Only look at session messages - these contain SMBs */ if (DCE2_NbssHdrChecks(ssd, (NbssHdr *)data_ptr) != DCE2_RET__SUCCESS) { DCE2_DEBUG_MSG(DCE2_DEBUG__SMB, "Not a NetBIOS Session Message. " "Ignoring %u bytes.\n", nb_need); *ignore_bytes = nb_need; dce2_stats.smb_ignored_bytes += *ignore_bytes; continue; } /* If we're not in block raw mode or we're waiting for server block raw response */ if (!DCE2_SmbIsRawData(ssd)) { /* Not enough data for SMB header ... add data to segmentation buffer */ if (data_len < smb_hdr_need) { DCE2_DEBUG_MSG(DCE2_DEBUG__SMB, "Data len(%u) < NetBIOS SS header + SMB header(%u). " "Queueing data.\n", data_len, smb_hdr_need); seg->nb_len = nb_len; DCE2_SmbHandleSegmentation(seg, data_ptr, data_len, smb_hdr_need, &data_used); return; } smb_hdr = (SmbNtHdr *)(data_ptr + sizeof(NbssHdr));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -