📄 dcerpc.c
字号:
/* * dcerpc.c * * Copyright (C) 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. * * */#include <stdlib.h>#include <wchar.h>#include "debug.h"#include "sf_snort_packet.h"#include "smb_structs.h"#include "snort_dcerpc.h"#include "dcerpc_util.h"#include "dcerpc.h"extern u_int16_t _max_frag_size;extern DCERPC *_dcerpc;extern SFSnortPacket *_dcerpc_pkt;extern u_int8_t _disable_dcerpc_fragmentation;extern u_int8_t _debug_print;/* Return if amount of data at least as much as DCE frag_length */int IsCompleteDCERPCMessage(u_int8_t *data, u_int16_t size){ DCERPC_HDR *dcerpc; /* Check to see if this is a valid DCE/RPC packet */ dcerpc = (DCERPC_HDR *) data; if ( size < sizeof(DCERPC_REQ) ) { DEBUG_WRAP(_dpd.debugMsg(DEBUG_DCERPC, "Error: Not enough data for DCERPC structure.\n");); return 0; } /* Check for version and packet type - mark as DCERPC session */ if ( dcerpc->version != 5 || (dcerpc->packet_type != DCERPC_REQUEST && dcerpc->packet_type != DCERPC_BIND) ) { DEBUG_WRAP(_dpd.debugMsg(DEBUG_DCERPC, "Error: Not a DCERPC bind or request.\n");); return 0; } /* Wait until we have the whole DCE/RPC message */ if ( dcerpc->frag_length > size ) return 0; return 1;}/* Return 1 if successfully parsed at least one message */int ProcessDCERPCMessage(u_int8_t *smb_hdr, u_int8_t *data, u_int16_t size){ DCERPC_HDR *dcerpc; int16_t current_size = (int16_t) size; u_int8_t *current_data = data; u_int16_t frag_length; if ( !IsCompleteDCERPCMessage(data, size) ) return 0; /* Check to see if this is a valid DCE/RPC packet */ dcerpc = (DCERPC_HDR *) current_data; _dcerpc->state = STATE_IS_DCERPC; /* Check fragmentation */ while (current_size > 0 ) { dcerpc = (DCERPC_HDR *) current_data; frag_length = 0; if ( DCERPC_Fragmentation(current_data, current_size, &frag_length) == 1 ) { ReassembleDCERPCRequest(smb_hdr, current_data, current_size); } /* Sanity checks */ if ( current_size < frag_length ) break; if ( frag_length == 0 ) break; current_size -= frag_length; current_data += frag_length; } return 1;}/* Return 0 if not fragmented OR if fragmented and not last fragment Return 1 if fragmented and last fragment */int DCERPC_Fragmentation(u_int8_t *data, u_int16_t data_size, u_int16_t *frag_length){ DCERPC_HDR *dcerpc_hdr; u_int16_t frag_size; if ( _dcerpc->state && STATE_IS_DCERPC ) { if ( data_size < sizeof(DCERPC_REQ) ) { DEBUG_WRAP(_dpd.debugMsg(DEBUG_DCERPC, "Error: Not a DCERPC request.\n");); return -1; } dcerpc_hdr = (DCERPC_HDR *) data; if ( _disable_dcerpc_fragmentation ) { *frag_length = dcerpc_hdr->frag_length; return 1; } /* Return length out of function */ *frag_length = frag_size = dcerpc_hdr->frag_length; frag_size = dcerpc_hdr->frag_length - sizeof(DCERPC_REQ); if ( frag_size > _max_frag_size ) { frag_size = _max_frag_size; } if ( !(_dcerpc->fragmentation & SUSPEND_FRAGMENTATION) ) { if ( _dcerpc->fragmentation & RPC_FRAGMENTATION ) { /* Already fragmented, get more buffer space if needed */ if ( dcerpc_hdr->packet_type == DCERPC_REQUEST ) { u_int16_t dcerpc_len; u_int16_t old_buf_size = _dcerpc->dcerpc_req_buf_size; dcerpc_len = frag_size; if ( _dcerpc->dcerpc_req_buf_size < (_dcerpc->dcerpc_req_buf_len + dcerpc_len) ) { while ( _dcerpc->dcerpc_req_buf_size < (_dcerpc->dcerpc_req_buf_len + dcerpc_len) ) { if ( _dcerpc->dcerpc_req_buf_size > 0x7FFF ) { _dcerpc->dcerpc_req_buf_size = 0xFFFF; break; } else { _dcerpc->dcerpc_req_buf_size *= 2; } } if ( _dcerpc->dcerpc_req_buf_size > _dpd.altBufferLen ) _dcerpc->dcerpc_req_buf_size = _dpd.altBufferLen; _dcerpc->dcerpc_req_buf = DCERPC_FragAlloc(_dcerpc->dcerpc_req_buf, old_buf_size, &_dcerpc->dcerpc_req_buf_size); if ( !_dcerpc->dcerpc_req_buf ) _dpd.fatalMsg("Failed to allocate space for DCE/RPC fragmented request\n"); if ( _dcerpc->dcerpc_req_buf_size == old_buf_size ) { DEBUG_WRAP(_dpd.debugMsg(DEBUG_DCERPC, "Memcap reached, suspending DCE/RPC fragmentation reassembly.\n");); _dcerpc->fragmentation |= SUSPEND_FRAGMENTATION; } } if ( _dcerpc->dcerpc_req_buf_len < _dcerpc->dcerpc_req_buf_size ) { if ( _dcerpc->dcerpc_req_buf_len + dcerpc_len > _dcerpc->dcerpc_req_buf_size ) { dcerpc_len = _dcerpc->dcerpc_req_buf_size - _dcerpc->dcerpc_req_buf_len; } memcpy(_dcerpc->dcerpc_req_buf + _dcerpc->dcerpc_req_buf_len, data + sizeof(DCERPC_REQ), dcerpc_len); _dcerpc->dcerpc_req_buf_len += dcerpc_len; if ( _debug_print ) PrintBuffer("DCE/RPC fragment", data + sizeof(DCERPC_REQ), dcerpc_len); } } } else { /* Check for DCE/RPC fragmentation */ if ( (dcerpc_hdr->flags & DCERPC_FIRST_FRAG) && !(dcerpc_hdr->flags & DCERPC_LAST_FRAG) ) { u_int16_t alloc_size = DCERPC_FRAG_ALLOC; _dcerpc->dcerpc_req_buf_len = frag_size; if ( _dcerpc->dcerpc_req_buf_len > DCERPC_FRAG_ALLOC ) { alloc_size = _dcerpc->dcerpc_req_buf_len; } _dcerpc->dcerpc_req_buf = (u_int8_t *) DCERPC_FragAlloc(NULL, 0, &alloc_size); if ( !_dcerpc->dcerpc_req_buf ) _dpd.fatalMsg("Failed to allocate space for DCE/RPC fragmented request\n"); if ( alloc_size == 0 ) { DEBUG_WRAP(_dpd.debugMsg(DEBUG_DCERPC, "Memcap reached, ignoring DCE/RPC fragmentation reassembly.\n");); DCERPC_FragFree(_dcerpc->dcerpc_req_buf, 0); _dcerpc->dcerpc_req_buf_len = 0; _dcerpc->dcerpc_req_buf = NULL; _dcerpc->fragmentation |= RPC_FRAGMENTATION; return 0; } else { if ( _dcerpc->dcerpc_req_buf_len > alloc_size ) { _dcerpc->dcerpc_req_buf_len = alloc_size; } _dcerpc->dcerpc_req_buf_size = alloc_size; memcpy(_dcerpc->dcerpc_req_buf, data + sizeof(DCERPC_REQ), _dcerpc->dcerpc_req_buf_len); _dcerpc->fragmentation |= RPC_FRAGMENTATION; if ( _debug_print ) PrintBuffer("DCE/RPC fragment", data + sizeof(DCERPC_REQ), _dcerpc->dcerpc_req_buf_len); } } else { return 0; } } } /* Check for last frag */ if ( (_dcerpc->fragmentation & RPC_FRAGMENTATION) && dcerpc_hdr->flags & DCERPC_LAST_FRAG ) { return 1; } } return 0;}void ReassembleDCERPCRequest(u_int8_t *smb_hdr, u_int8_t *data, u_int16_t data_size){ DCERPC_REQ fake_req; u_int16_t smb_hdr_len = 0; unsigned int dcerpc_req_len= sizeof(DCERPC_REQ); if ( smb_hdr ) { smb_hdr_len = data - smb_hdr; } /* Make sure we have room to fit into alternate buffer */ if ( (smb_hdr_len + dcerpc_req_len + _dcerpc->dcerpc_req_buf_len) > _dpd.altBufferLen ) { _dpd.logMsg("Reassembled DCE/RPC packet greater than %d bytes, skipping.", _dpd.altBufferLen); return; } /* Mock up header */ memcpy(&fake_req, data, dcerpc_req_len); fake_req.dcerpc_hdr.frag_length = dcerpc_req_len + _dcerpc->dcerpc_req_buf_len; fake_req.dcerpc_hdr.flags &= ~DCERPC_FIRST_FRAG; fake_req.dcerpc_hdr.flags &= ~DCERPC_LAST_FRAG; fake_req.alloc_hint = _dcerpc->dcerpc_req_buf_len; /* Copy headers into buffer */ _dcerpc_pkt->normalized_payload_size = 0; if ( smb_hdr ) { memcpy(_dpd.altBuffer, _dcerpc_pkt->payload, sizeof(NBT_HDR)); _dcerpc_pkt->normalized_payload_size = sizeof(NBT_HDR); memcpy(_dpd.altBuffer + _dcerpc_pkt->normalized_payload_size, smb_hdr, smb_hdr_len); _dcerpc_pkt->normalized_payload_size += smb_hdr_len; } memcpy(_dpd.altBuffer + _dcerpc_pkt->normalized_payload_size, &fake_req, dcerpc_req_len); _dcerpc_pkt->normalized_payload_size += dcerpc_req_len; /* Copy data into buffer */ memcpy(_dpd.altBuffer + _dcerpc_pkt->normalized_payload_size, _dcerpc->dcerpc_req_buf, _dcerpc->dcerpc_req_buf_len); _dcerpc_pkt->normalized_payload_size += _dcerpc->dcerpc_req_buf_len; _dcerpc_pkt->flags |= FLAG_ALT_DECODE; if ( _debug_print ) PrintBuffer("DCE/RPC reassembled fragment", _dpd.altBuffer, _dcerpc_pkt->normalized_payload_size); /* Get ready for next write */ DCERPC_FragFree(_dcerpc->dcerpc_req_buf, _dcerpc->dcerpc_req_buf_size); _dcerpc->dcerpc_req_buf = NULL; _dcerpc->dcerpc_req_buf_len = 0; _dcerpc->dcerpc_req_buf_size = 0; _dcerpc->fragmentation &= ~RPC_FRAGMENTATION; _dcerpc->fragmentation &= ~SUSPEND_FRAGMENTATION;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -