📄 dce2_co.c
字号:
} }}/******************************************************************** * Function: DCE2_CoHandleFrag() * * Handles adding a fragment to the defragmentation buffer. * Does overflow checking. Maximum length of fragmentation buffer * is based on the maximum packet length Snort can handle. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_CoTracker * * Pointer to the relevant connection-oriented tracker. * DceRpcCoHdr * * Pointer to the main header in the packet data. * const uint8_t * * Pointer to the current processing point of the DCE/RPC * pdu in the packet data. * uint16_t * Fragment length left in the pdu. * * Returns: None * ********************************************************************/static void DCE2_CoHandleFrag(DCE2_SsnData *sd, DCE2_CoTracker *cot, const DceRpcCoHdr *co_hdr, const uint8_t *frag_ptr, uint16_t frag_len){ DCE2_CoFragTracker *ft = &cot->frag_tracker; uint32_t size = (frag_len < DCE2_FRAG__MIN_ALLOC_SIZE) ? DCE2_FRAG__MIN_ALLOC_SIZE : frag_len; uint16_t max_frag_data; DCE2_BufferMinAddFlag mflag = DCE2_BUFFER_MIN_ADD_FLAG__USE; DCE2_Ret status; if (frag_len > dce2_stats.co_max_frag_size) dce2_stats.co_max_frag_size = frag_len; if (ft->frag_buf == NULL) { ft->frag_buf = DCE2_BufferNew(size, DCE2_FRAG__MIN_ALLOC_SIZE, DCE2_MEM_TYPE__CO_FRAG); if (ft->frag_buf == NULL) return; } /* If there's already data in the buffer and this is a first frag * we probably missed packets */ if (DceRpcCoFirstFrag(co_hdr) && !DCE2_BufferIsEmpty(ft->frag_buf)) DCE2_BufferEmpty(ft->frag_buf); /* Check for potential overflow */ if (sd->trans == DCE2_TRANS_TYPE__SMB) max_frag_data = DCE2_GetRpktMaxData(sd, DCE2_RPKT_TYPE__SMB_CO_FRAG); else max_frag_data = DCE2_GetRpktMaxData(sd, DCE2_RPKT_TYPE__TCP_CO_FRAG); if (DCE2_GcMaxFrag() && (frag_len > DCE2_GcMaxFragLen())) frag_len = DCE2_GcMaxFragLen(); if ((DCE2_BufferLength(ft->frag_buf) + frag_len) > max_frag_data) frag_len = max_frag_data - (uint16_t)DCE2_BufferLength(ft->frag_buf); if (frag_len != 0) { /* If it's the last fragment we're going to flush so just alloc * exactly what we need ... or if there is more data than can fit * in the reassembly buffer */ if (DceRpcCoLastFrag(co_hdr) || (DCE2_BufferLength(ft->frag_buf) == max_frag_data)) mflag = DCE2_BUFFER_MIN_ADD_FLAG__IGNORE; status = DCE2_BufferAddData(ft->frag_buf, frag_ptr, frag_len, mflag); if (status != DCE2_RET__SUCCESS) { /* Either hit memcap or a memcpy failed - reassemble */ DCE2_CoFragReassemble(sd, cot); DCE2_BufferEmpty(cot->frag_tracker.frag_buf); return; } } /* Reassemble if we got a last frag ... */ if (DceRpcCoLastFrag(co_hdr)) { DCE2_CoFragReassemble(sd, cot); DCE2_BufferEmpty(cot->frag_tracker.frag_buf); DCE2_CoResetTracker(cot); /* Return early - rule opts will be set in reassembly handler */ return; } else if (DCE2_BufferLength(ft->frag_buf) == max_frag_data) { /* ... or can't fit any more data in the buffer * Don't reset frag tracker */ DCE2_CoFragReassemble(sd, cot); DCE2_BufferEmpty(cot->frag_tracker.frag_buf); return; }}/******************************************************************** * Function: DCE2_CoFragReassemble() * * Wrapper for the generic reassembly function. Calls generic * reassembly function specifying that we want to do fragmentation * reassembly. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_CoTracker * * Pointer to the relevant connection-oriented tracker. * * Returns: None * ********************************************************************/static INLINE void DCE2_CoFragReassemble(DCE2_SsnData *sd, DCE2_CoTracker *cot){ DCE2_CoReassemble(sd, cot, DCE2_CO_RPKT_TYPE__FRAG);}/******************************************************************** * Function: DCE2_CoSegReassemble() * * Wrapper for the generic reassembly function. Calls generic * reassembly function specifying that we want to do segmentation * reassembly. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_CoTracker * * Pointer to the relevant connection-oriented tracker. * * Returns: None * ********************************************************************/static INLINE void DCE2_CoSegReassemble(DCE2_SsnData *sd, DCE2_CoTracker *cot){ DCE2_CoReassemble(sd, cot, DCE2_CO_RPKT_TYPE__SEG);}/******************************************************************** * Function: DCE2_CoReassemble() * * Gets a reassemly packet based on the transport and the type of * reassembly we want to do. Sets rule options and calls detect * on the reassembled packet. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_CoTracker * * Pointer to the relevant connection-oriented tracker. * DCE2_CoRpktType * Specifies whether we want to do segmenation, fragmentation * or fragmentation and segmentation reassembly. * * Returns: None * ********************************************************************/static void DCE2_CoReassemble(DCE2_SsnData *sd, DCE2_CoTracker *cot, DCE2_CoRpktType co_rtype){ DCE2_RpktType rpkt_type; DceRpcCoHdr *co_hdr; SFSnortPacket *rpkt = DCE2_CoGetRpkt(sd, cot, co_rtype, &rpkt_type); if (rpkt == NULL) return; switch (rpkt_type) { case DCE2_RPKT_TYPE__SMB_CO_FRAG: case DCE2_RPKT_TYPE__SMB_CO_SEG: DCE2_SmbSetRdata((DCE2_SmbSsnData *)sd, (uint8_t *)rpkt->payload, (uint16_t)(rpkt->payload_size - DCE2_MOCK_HDR_LEN__SMB)); if (rpkt_type == DCE2_RPKT_TYPE__SMB_CO_FRAG) { DCE2_CoSetRdata(cot, (uint8_t *)rpkt->payload + DCE2_MOCK_HDR_LEN__SMB, (uint16_t)(rpkt->payload_size - (DCE2_MOCK_HDR_LEN__SMB + DCE2_MOCK_HDR_LEN__CO))); } co_hdr = (DceRpcCoHdr *)(rpkt->payload + DCE2_MOCK_HDR_LEN__SMB); cot->stub_data = rpkt->payload + DCE2_MOCK_HDR_LEN__SMB + DCE2_MOCK_HDR_LEN__CO; break; case DCE2_RPKT_TYPE__TCP_CO_FRAG: case DCE2_RPKT_TYPE__TCP_CO_SEG: if (rpkt_type == DCE2_RPKT_TYPE__TCP_CO_FRAG) { DCE2_CoSetRdata(cot, (uint8_t *)rpkt->payload, (uint16_t)(rpkt->payload_size - DCE2_MOCK_HDR_LEN__CO)); } co_hdr = (DceRpcCoHdr *)rpkt->payload; cot->stub_data = rpkt->payload + DCE2_MOCK_HDR_LEN__CO; break; default: DCE2_Log("%s(%d) => Invalid transport type\n", __FILE__, __LINE__); return; } /* Push packet onto stack */ if (DCE2_PushPkt(rpkt) != DCE2_RET__SUCCESS) { DCE2_Log("%s(%d) => Failed to push packet onto packet stack\n", __FILE__, __LINE__); return; } DCE2_CoSetRopts(sd, cot, co_hdr); DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "Reassembled CO fragmented packet:\n"); DCE2_DEBUG_CODE(DCE2_DEBUG__CO, DCE2_PrintPktData(rpkt->payload, rpkt->payload_size);); DCE2_Detect(sd); DCE2_PopPkt(); dce2_stats.co_reassembled++;}/******************************************************************** * Function: DCE2_CoSetIface() * * Sets the interface UUID for the rules options. Looks in the * context id list. If nothing found there, it looks in the pending * list (in case we never saw the server response because of * missed packets) to see if something is there. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_CoTracker * * Pointer to the relevant connection-oriented tracker. * uint16_t * The context id to use for the lookup. * * Returns: * DCE2_Ret * DCE2_RET__ERROR if the interface UUID could not be found * based on the context id passed in. * DCE2_RET__SUCESS if the interface UUID could be found and * the appropriate rule options could be set. * ********************************************************************/static DCE2_Ret DCE2_CoSetIface(DCE2_SsnData *sd, DCE2_CoTracker *cot, uint16_t ctx_id){ DCE2_CoCtxIdNode *ctx_id_node; /* This should be set if we've gotten a Bind */ if (cot->ctx_ids == NULL) return DCE2_RET__ERROR; ctx_id_node = (DCE2_CoCtxIdNode *)DCE2_ListFind(cot->ctx_ids, (void *)(uintptr_t)ctx_id); if (ctx_id_node == NULL) /* context id not found in list */ { /* See if it's in the queue. An easy evasion would be to stagger the writes * and reads such that we see a request before seeing the server bind ack */ if (cot->pending_ctx_ids != NULL) { for (ctx_id_node = (DCE2_CoCtxIdNode *)DCE2_QueueFirst(cot->pending_ctx_ids); ctx_id_node != NULL; ctx_id_node = (DCE2_CoCtxIdNode *)DCE2_QueueNext(cot->pending_ctx_ids)) { if (ctx_id_node->ctx_id == ctx_id) break; } } if (ctx_id_node == NULL) return DCE2_RET__ERROR; } if (ctx_id_node->state == DCE2_CO_CTX_STATE__REJECTED) return DCE2_RET__ERROR; DCE2_CopyUuid(&sd->ropts.iface, &ctx_id_node->iface, DCERPC_BO_FLAG__NONE); sd->ropts.iface_vers_maj = ctx_id_node->iface_vers_maj; sd->ropts.iface_vers_min = ctx_id_node->iface_vers_min; return DCE2_RET__SUCCESS;}/******************************************************************** * Function: DCE2_CoCtxCompare() * * Callback to context id list for finding the right interface * UUID node. Values passed in are context ids which are used as * the keys for the list. * * Arguments: * const void * * First context id to compare. * const void * * Second context id to compare. * * Returns: * int * 0 if first value equals second value * -1 if first value does not equal the second value * ********************************************************************/static int DCE2_CoCtxCompare(const void *a, const void *b){ int x = (int)(uintptr_t)a; int y = (int)(uintptr_t)b; if (x == y) return 0; /* Only care about equality for finding */ return -1;}/******************************************************************** * Function: DCE2_CoCtxFree() * * Callback to context id list for freeing context id nodes in * the list. * * Arguments: * void * * Context id node to free. * * Returns: None * ********************************************************************/static void DCE2_CoCtxFree(void *data){ if (data == NULL) return; DCE2_Free(data, sizeof(DCE2_CoCtxIdNode), DCE2_MEM_TYPE__CO_CTX);}/******************************************************************** * Function: DCE2_CoInitTracker() * * Initializes fields in the connection-oriented tracker to * sentinels. Many decisions are made based on whether or not * these fields have been set. * * Arguments: * DCE2_CoTracker * * Pointer to the relevant connection-oriented tracker. * * Returns: None * ********************************************************************/void DCE2_CoInitTracker(DCE2_CoTracker *cot){ if (cot == NULL) return; cot->max_xmit_frag = DCE2_SENTINEL; cot->data_byte_order = DCE2_SENTINEL; cot->ctx_id = DCE2_SENTINEL; cot->opnum = DCE2_SENTINEL; cot->call_id = DCE2_SENTINEL; cot->stub_data = NULL; cot->got_bind = 0; cot->frag_tracker.opnum = DCE2_SENTINEL; cot->frag_tracker.ctx_id = DCE2_SENTINEL; cot->frag_tracker.expected_call_id = DCE2_SENT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -