From: Bhargava Jandhyala (bjandhya) Date: Mon, 5 Jul 2021 06:47:23 +0000 (+0000) Subject: Merge pull request #2966 in SNORT/snort3 from ~VKAMBALA/snort3:eicar to master X-Git-Tag: 3.1.8.0~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b141714e900dd881ae0badfd5c9066a0b6891dd1;p=thirdparty%2Fsnort3.git Merge pull request #2966 in SNORT/snort3 from ~VKAMBALA/snort3:eicar to master Squashed commit of the following: commit bd1c2d1e18fa3ec4e1efac72f0ea924a9b252407 Author: krishnakanth Date: Thu Jul 1 05:06:31 2021 -0400 dce_rpc: Handling raw packets --- diff --git a/src/file_api/file_lib.cc b/src/file_api/file_lib.cc index 54d58ee02..425b4cab4 100644 --- a/src/file_api/file_lib.cc +++ b/src/file_api/file_lib.cc @@ -450,6 +450,10 @@ bool FileContext::process(Packet* p, const uint8_t* file_data, int data_size, PacketTracer::log("File: Type-%s found\n", file_type_name(get_file_type()).c_str()); config_file_type(false); + + if (PacketTracer::is_active() and (!(is_file_signature_enabled()))) + PacketTracer::log("File: signature config is disabled\n"); + file_stats->files_processed[get_file_type()][get_file_direction()]++; //Check file type based on file policy FileVerdict v = policy->type_lookup(p, this); diff --git a/src/file_api/file_segment.cc b/src/file_api/file_segment.cc index fffcb6074..1a879ba4b 100644 --- a/src/file_api/file_segment.cc +++ b/src/file_api/file_segment.cc @@ -61,14 +61,13 @@ void FileSegments::clear() } // Update the segment list based on new data -void FileSegments::add(const uint8_t* file_data, uint64_t data_size, uint64_t offset) +void FileSegments::add(const uint8_t* file_data, int64_t data_size, uint64_t offset) { - FileSegment* new_segment = new FileSegment(); - new_segment->offset = offset; - new_segment->data = new std::string((const char*)file_data, data_size); - if (!head) { + FileSegment* new_segment = new FileSegment(); + new_segment->offset = offset; + new_segment->data = new std::string((const char*)file_data, data_size); head = new_segment; return; } @@ -80,7 +79,6 @@ void FileSegments::add(const uint8_t* file_data, uint64_t data_size, uint64_t of FileSegment* left = nullptr; FileSegment* previous = nullptr; bool find_left = false; - bool is_overlap = false; // Find left boundary, left points to segment that needs update while (current_segment) @@ -99,41 +97,65 @@ void FileSegments::add(const uint8_t* file_data, uint64_t data_size, uint64_t of // New segment should be at the end of link list if (!find_left) { - previous->next = new_segment; + left = previous; + if (left->offset +left->data->size() >start) + { + offset = left->offset + left->data->size(); + data_size = end -offset; + file_data = file_data + offset - start; + } } // New segment should be at the start of link list else if (!left) { - if (end <= head->offset) + if (end > head->offset) { - new_segment->next = head; - head = new_segment; - } - else - { - is_overlap = true; + /* Overlap, trim off extra data from end */ + data_size = head->offset - offset; } } else { - if ((left->offset + left->data->size() > start) || - (left->next->offset < end)) + //Left Overlap + if ( (left->offset + left->data->size() > start) ) { - is_overlap = true; + offset = left->offset + left->data->size(); + data_size = end - offset; + file_data = file_data + offset - start; } - else + //Right Overlap + if ( (left->next->offset < end) ) { - new_segment->next = left->next; - left->next = new_segment; + data_size = left->next->offset - offset; } + } // ignore overlap case - if (is_overlap) + if (data_size <= 0) { - delete new_segment; return; } + + FileSegment* new_segment = new FileSegment(); + new_segment->offset = offset; + new_segment->data = new std::string((const char*)file_data, data_size); + + if (!find_left) + { + previous->next = new_segment; + + } + else if (!left) + { + new_segment->next = head; + head = new_segment; + } + else + { + new_segment->next = left->next; + left->next = new_segment; + } } FilePosition FileSegments::get_file_position(uint64_t data_size, uint64_t file_size) diff --git a/src/file_api/file_segment.h b/src/file_api/file_segment.h index b52e4214b..39a59e1ea 100644 --- a/src/file_api/file_segment.h +++ b/src/file_api/file_segment.h @@ -62,7 +62,7 @@ private: uint64_t current_offset; snort::FileContext* context = nullptr; - void add(const uint8_t* file_data, uint64_t data_size, uint64_t offset); + void add(const uint8_t* file_data, int64_t data_size, uint64_t offset); FilePosition get_file_position(uint64_t data_size, uint64_t file_size); int process_one(snort::Packet*, const uint8_t* file_data, int data_size, snort::FilePolicyBase*, FilePosition position=SNORT_FILE_POSITION_UNKNOWN); diff --git a/src/service_inspectors/dce_rpc/dce_smb2.cc b/src/service_inspectors/dce_rpc/dce_smb2.cc index 7e985db0d..0fba9cc5c 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2.cc +++ b/src/service_inspectors/dce_rpc/dce_smb2.cc @@ -248,7 +248,7 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr, const Smb2NegotiateResponseHdr* neg_resp_hdr = (const Smb2NegotiateResponseHdr*)smb_data; if (neg_resp_hdr->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL) { - Packet *p = DetectionEngine::get_current_packet(); + Packet* p = DetectionEngine::get_current_packet(); Dce2SmbFlowData* fd = create_expected_smb_flow_data(p, (dce2SmbProtoConf *)sd.config); if (fd) @@ -439,7 +439,9 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr, session->process(command, SMB2_CMD_TYPE_RESPONSE, smb_hdr, end, flow_key); } else + { SMB2_HANDLE_INVALID_STRUC_SIZE(ioctl) + } } break; default: @@ -509,11 +511,16 @@ void Dce2Smb2SessionData::process() else { tcp_file_tracker_mutex.lock(); - if ( tcp_file_tracker and tcp_file_tracker->accepting_raw_data()) + if ( tcp_file_tracker and tcp_file_tracker->accepting_raw_data_from(flow_key)) { debug_logf(dce_smb_trace, p, "processing raw data for file id %" PRIu64 "\n", tcp_file_tracker->get_file_id()); tcp_file_tracker->process_data(flow_key, data_ptr, data_len); + tcp_file_tracker->stop_accepting_raw_data_from(flow_key); + } + else + { + debug_logf(dce_smb_trace, p, "not processing raw data\n"); } tcp_file_tracker_mutex.unlock(); } diff --git a/src/service_inspectors/dce_rpc/dce_smb2_file.cc b/src/service_inspectors/dce_rpc/dce_smb2_file.cc index d74ca11ae..c4e1e9700 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2_file.cc +++ b/src/service_inspectors/dce_rpc/dce_smb2_file.cc @@ -35,14 +35,30 @@ using namespace snort; #define UNKNOWN_FILE_SIZE (~0) -void Dce2Smb2FileTracker::accept_raw_data_from(Dce2Smb2SessionData* flow) +void Dce2Smb2FileTracker::accept_raw_data_from(Dce2Smb2SessionData* flow, uint64_t offset) { if (flow) { - smb2_pdu_state = DCE2_SMB_PDU_STATE__RAW_DATA; + uint32_t current_flow_key = flow->get_flow_key(); + std::lock_guard guard(flow_state_mutex); + tcp_flow_state& current_flow_state = flow_state[current_flow_key]; + if ( (current_flow_state.pdu_state == DCE2_SMB_PDU_STATE__RAW_DATA) and + (current_flow_state.file_offset == current_flow_state.max_offset)) + { + current_flow_state.file_offset = offset; + } + + current_flow_state.pdu_state = DCE2_SMB_PDU_STATE__RAW_DATA; flow->set_tcp_file_tracker(this); } } +void Dce2Smb2FileTracker::stop_accepting_raw_data_from(uint32_t current_flow_key) +{ + std::lock_guard guard(flow_state_mutex); + tcp_flow_state& current_flow_state = flow_state[current_flow_key]; + if(current_flow_state.file_offset == current_flow_state.max_offset) + current_flow_state.pdu_state = DCE2_SMB_PDU_STATE__COMMAND; +} inline void Dce2Smb2FileTracker::file_detect() { @@ -102,7 +118,9 @@ void Dce2Smb2FileTracker::set_info(char* file_name_v, uint16_t name_len_v, uint6 bool Dce2Smb2FileTracker::close(const uint32_t current_flow_key) { - uint64_t file_offset = file_offsets[current_flow_key]; + flow_state_mutex.lock(); + uint64_t file_offset = flow_state[current_flow_key].file_offset; + flow_state_mutex.unlock(); if (!ignore and !file_size and file_offset) { file_size = file_offset; @@ -117,9 +135,13 @@ bool Dce2Smb2FileTracker::close(const uint32_t current_flow_key) } bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const uint8_t* file_data, - uint32_t data_size, const uint64_t offset) + uint32_t data_size, const uint64_t offset, uint64_t max_offset) { - file_offsets[current_flow_key] = offset; + flow_state_mutex.lock(); + tcp_flow_state& current_flow_state = flow_state[current_flow_key]; + current_flow_state.file_offset = offset; + current_flow_state.max_offset = offset + max_offset; + flow_state_mutex.unlock(); return process_data(current_flow_key, file_data, data_size); } @@ -141,7 +163,10 @@ bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const ui int64_t file_detection_depth = current_flow->get_smb_file_depth(); int64_t detection_size = 0; - uint64_t file_offset = file_offsets[current_flow_key]; + Packet* p = DetectionEngine::get_current_packet(); + flow_state_mutex.lock(); + uint64_t file_offset = flow_state[current_flow_key].file_offset; + flow_state_mutex.unlock(); if (file_detection_depth == 0) detection_size = data_size; @@ -163,8 +188,6 @@ bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const ui if (ignore) return true; - Packet* p = DetectionEngine::get_current_packet(); - if (file_size and file_offset > file_size) { debug_logf(dce_smb_trace, p, "file_process: bad offset\n"); @@ -202,7 +225,9 @@ bool Dce2Smb2FileTracker::process_data(const uint32_t current_flow_key, const ui } file_offset += data_size; - file_offsets[current_flow_key] = file_offset; + flow_state_mutex.lock(); + flow_state[current_flow_key].file_offset = file_offset; + flow_state_mutex.unlock(); return true; } diff --git a/src/service_inspectors/dce_rpc/dce_smb2_file.h b/src/service_inspectors/dce_rpc/dce_smb2_file.h index c5aa334d1..55baa7375 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2_file.h +++ b/src/service_inspectors/dce_rpc/dce_smb2_file.h @@ -27,6 +27,13 @@ class Dce2Smb2TreeTracker; +typedef struct _tcp_flow_state +{ + Dce2SmbPduState pdu_state; + uint64_t file_offset; + uint64_t max_offset; +} tcp_flow_state; + class Dce2Smb2FileTracker { public: @@ -38,20 +45,24 @@ public: Dce2Smb2FileTracker(uint64_t file_idv, const uint32_t flow_key, Dce2Smb2TreeTracker* p_tree) : ignore(true), file_name_len(0), file_flow_key(flow_key), file_id(file_idv), file_size(0), file_name_hash(0), file_name(nullptr), - direction(FILE_DOWNLOAD), smb2_pdu_state(DCE2_SMB_PDU_STATE__COMMAND), parent_tree(p_tree) + direction(FILE_DOWNLOAD), parent_tree(p_tree) { debug_logf(dce_smb_trace, GET_CURRENT_PACKET, "file tracker %" PRIu64 " created\n", file_id); } ~Dce2Smb2FileTracker(); - bool process_data(const uint32_t, const uint8_t*, uint32_t, const uint64_t); + bool process_data(const uint32_t, const uint8_t*, uint32_t, const uint64_t, uint64_t); bool process_data(const uint32_t, const uint8_t*, uint32_t); bool close(const uint32_t); void set_info(char*, uint16_t, uint64_t); - void accept_raw_data_from(Dce2Smb2SessionData*); - bool accepting_raw_data() - { return (smb2_pdu_state == DCE2_SMB_PDU_STATE__RAW_DATA); } + void accept_raw_data_from(Dce2Smb2SessionData*, uint64_t = 0); + bool accepting_raw_data_from(uint32_t current_flow_key) + { + std::lock_guard guard(flow_state_mutex); + return (flow_state[current_flow_key].pdu_state == DCE2_SMB_PDU_STATE__RAW_DATA); + } + void stop_accepting_raw_data_from(uint32_t); void set_direction(FileDirection dir) { direction = dir; } Dce2Smb2TreeTracker* get_parent() { return parent_tree; } @@ -68,10 +79,10 @@ private: uint64_t file_name_hash; char* file_name; FileDirection direction; - std::atomic smb2_pdu_state; Dce2Smb2TreeTracker* parent_tree; - std::unordered_map > file_offsets; + std::unordered_map > flow_state; std::mutex process_file_mutex; + std::mutex flow_state_mutex; }; using Dce2Smb2FileTrackerMap = diff --git a/src/service_inspectors/dce_rpc/dce_smb2_tree.cc b/src/service_inspectors/dce_rpc/dce_smb2_tree.cc index 8fa45c417..57582e363 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2_tree.cc +++ b/src/service_inspectors/dce_rpc/dce_smb2_tree.cc @@ -309,8 +309,12 @@ void Dce2Smb2TreeTracker::process_read_response(const uint64_t message_id, { const uint8_t* file_data = (const uint8_t*)read_resp_hdr + SMB2_READ_RESPONSE_STRUC_SIZE - 1; - int data_size = end - file_data; - if (file_tracker->process_data(current_flow_key, file_data, data_size, read_request->get_offset())) + // we may not have enough data in some case, use best effort to process file for whatever + // data we have till now. + int data_size = (read_resp_hdr->length > (end - file_data)) ? + (end - file_data) : read_resp_hdr->length; + if (file_tracker->process_data(current_flow_key, file_data, data_size, + read_request->get_offset(), read_resp_hdr->length)) { if ((uint32_t)data_size < alignedNtohl((const uint32_t*)&(read_resp_hdr->length))) { @@ -338,6 +342,19 @@ void Dce2Smb2TreeTracker::process_read_request(const uint64_t message_id, debug_logf(dce_smb_trace, GET_CURRENT_PACKET, "SMB2_COM_READ_REQ: store failed\n"); delete read_request; } + Dce2Smb2FileTracker* file_tracker = find_file(file_id); + Dce2Smb2SessionData* current_flow = parent_session->get_flow(current_flow_key); + if (file_tracker) + { + debug_logf(dce_smb_trace, GET_CURRENT_PACKET, + "SMB2_COM_READ_REQ: start accepting Raw Data\n"); + file_tracker->accept_raw_data_from(current_flow,offset); + } + else + { + debug_logf(dce_smb_trace, GET_CURRENT_PACKET, + "SMB2_COM_READ_REQ: file tracker missing\n"); + } } void Dce2Smb2TreeTracker::process_write_request(const uint64_t message_id, @@ -365,9 +382,13 @@ void Dce2Smb2TreeTracker::process_write_request(const uint64_t message_id, if (file_tracker) { file_tracker->set_direction(FILE_UPLOAD); - int data_size = end - file_data; + // we may not have enough data in some case, use best effort to process file for whatever + // data we have till now. + int data_size = (write_req_hdr->length > (end - file_data)) ? + (end - file_data) : write_req_hdr->length; uint64_t offset = alignedNtohq((const uint64_t*)(&(write_req_hdr->offset))); - if (file_tracker->process_data(current_flow_key, file_data, data_size, offset)) + if (file_tracker->process_data(current_flow_key, file_data, data_size, offset, + write_req_hdr->length)) { if ((uint32_t)data_size < alignedNtohl((const uint32_t*)&(write_req_hdr->length))) {