From: Shivani Bhardwaj Date: Sat, 20 Feb 2021 06:32:28 +0000 (+0530) Subject: dcerpc: add probe function X-Git-Tag: suricata-7.0.0-beta1~1779 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3641f1b52256b7eb289048d6b83e660fe4907aaf;p=thirdparty%2Fsuricata.git dcerpc: add probe function --- diff --git a/rust/src/dcerpc/dcerpc.rs b/rust/src/dcerpc/dcerpc.rs index 62a899df90..203d9377b8 100644 --- a/rust/src/dcerpc/dcerpc.rs +++ b/rust/src/dcerpc/dcerpc.rs @@ -16,7 +16,7 @@ */ use std::mem::transmute; -use crate::applayer::{AppLayerResult, AppLayerTxData}; +use crate::applayer::*; use crate::core::{self, sc_detect_engine_state_free}; use crate::dcerpc::parser; use nom::error::ErrorKind; @@ -1318,6 +1318,46 @@ pub unsafe extern "C" fn rs_dcerpc_get_stub_data( *endianness = tx.get_endianness(); } +/// Probe input to see if it looks like DCERPC. +fn probe(input: &[u8]) -> (bool, bool) { + match parser::parse_dcerpc_header(input) { + Ok((_, hdr)) => { + let is_request = hdr.hdrtype == 0x00; + let is_dcerpc = hdr.rpc_vers == 0x05 && hdr.rpc_vers_minor == 0x00; + return (is_dcerpc, is_request); + }, + Err(_) => (false, false), + } +} + +#[no_mangle] +pub extern "C" fn rs_dcerpc_probe_tcp(direction: u8, input: *const u8, + len: u32, rdir: *mut u8) -> i32 +{ + SCLogDebug!("Probing packet for DCERPC"); + if len == 0 { + return core::ALPROTO_UNKNOWN; + } + let slice: &[u8] = unsafe { + std::slice::from_raw_parts(input as *mut u8, len as usize) + }; + //is_incomplete is checked by caller + let (is_dcerpc, is_request, ) = probe(slice); + if is_dcerpc { + let dir = if is_request { + core::STREAM_TOSERVER + } else { + core::STREAM_TOCLIENT + }; + if direction & (core::STREAM_TOSERVER|core::STREAM_TOCLIENT) != dir { + unsafe { *rdir = dir }; + } + return 1; + } + return 0; + +} + #[cfg(test)] mod tests { use crate::applayer::AppLayerResult; diff --git a/rust/src/dcerpc/dcerpc_udp.rs b/rust/src/dcerpc/dcerpc_udp.rs index 14a09be94b..0f86404048 100644 --- a/rust/src/dcerpc/dcerpc_udp.rs +++ b/rust/src/dcerpc/dcerpc_udp.rs @@ -289,6 +289,47 @@ pub extern "C" fn rs_dcerpc_udp_get_tx_cnt(vtx: *mut std::os::raw::c_void) -> u6 dce_state.tx_id } +/// Probe input to see if it looks like DCERPC. +fn probe(input: &[u8]) -> (bool, bool) { + match parser::parse_dcerpc_udp_header(input) { + Ok((_, hdr)) => { + let is_request = hdr.pkt_type == 0x00; + let is_dcerpc = hdr.rpc_vers == 0x04; + return (is_dcerpc, is_request); + }, + Err(_) => (false, false), + } +} + +#[no_mangle] +pub extern "C" fn rs_dcerpc_probe_udp(direction: u8, input: *const u8, + len: u32, rdir: *mut u8) -> i32 +{ + SCLogDebug!("Probing the packet for DCERPC/UDP"); + if len == 0 { + return core::ALPROTO_UNKNOWN; + } + let slice: &[u8] = unsafe { + std::slice::from_raw_parts(input as *mut u8, len as usize) + }; + //is_incomplete is checked by caller + let (is_dcerpc, is_request) = probe(slice); + if is_dcerpc { + let dir = if is_request { + core::STREAM_TOSERVER + } else { + core::STREAM_TOCLIENT + }; + if direction & (core::STREAM_TOSERVER|core::STREAM_TOCLIENT) != dir { + unsafe { *rdir = dir }; + } + return 1; + } + return 0; + +} + + #[cfg(test)] mod tests { use crate::applayer::AppLayerResult; diff --git a/src/app-layer-dcerpc-udp.c b/src/app-layer-dcerpc-udp.c index bc03e8b8c9..d47fa4dda5 100644 --- a/src/app-layer-dcerpc-udp.c +++ b/src/app-layer-dcerpc-udp.c @@ -97,11 +97,27 @@ static int RustDCERPCUDPGetAlstateProgress(void *tx, uint8_t direction) return rs_dcerpc_get_alstate_progress(tx, direction); } +static uint16_t DCERPCUDPProbe( + Flow *f, uint8_t direction, const uint8_t *input, uint32_t len, uint8_t *rdir) +{ + SCLogDebug("DCERPCUDPProbe"); + + const int r = rs_dcerpc_probe_udp(direction, input, len, rdir); + switch (r) { + case 1: + return ALPROTO_DCERPC; + case 0: + return ALPROTO_UNKNOWN; + case -1: + default: + return ALPROTO_FAILED; + } +} + static int DCERPCUDPRegisterPatternsForProtocolDetection(void) { - if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_DCERPC, - "|04 00|", 2, 0, STREAM_TOSERVER) < 0) - { + if (AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_UDP, ALPROTO_DCERPC, "|04 00|", 2, 0, + STREAM_TOSERVER, DCERPCUDPProbe, 0, 0) < 0) { return -1; } diff --git a/src/app-layer-dcerpc.c b/src/app-layer-dcerpc.c index 334ab952ca..2373722108 100644 --- a/src/app-layer-dcerpc.c +++ b/src/app-layer-dcerpc.c @@ -121,16 +121,31 @@ static int DCERPCGetAlstateProgress(void *tx, uint8_t direction) return rs_dcerpc_get_alstate_progress(tx, direction); } +static uint16_t DCERPCTCPProbe( + Flow *f, uint8_t direction, const uint8_t *input, uint32_t len, uint8_t *rdir) +{ + SCLogDebug("DCERPCTCPProbe"); + + const int r = rs_dcerpc_probe_tcp(direction, input, len, rdir); + switch (r) { + case 1: + return ALPROTO_DCERPC; + case 0: + return ALPROTO_UNKNOWN; + case -1: + default: + return ALPROTO_FAILED; + } +} + static int DCERPCRegisterPatternsForProtocolDetection(void) { - if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_DCERPC, - "|05 00|", 2, 0, STREAM_TOSERVER) < 0) - { + if (AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP, ALPROTO_DCERPC, "|05 00|", 2, 0, + STREAM_TOSERVER, DCERPCTCPProbe, 0, 0) < 0) { return -1; } - if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_DCERPC, - "|05 00|", 2, 0, STREAM_TOCLIENT) < 0) - { + if (AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP, ALPROTO_DCERPC, "|05 00|", 2, 0, + STREAM_TOCLIENT, DCERPCTCPProbe, 0, 0) < 0) { return -1; }