diff --git a/scripts/base/protocols/dce-rpc/dpd.sig b/scripts/base/protocols/dce-rpc/dpd.sig index 2894af805b..fc8c897b1a 100644 --- a/scripts/base/protocols/dce-rpc/dpd.sig +++ b/scripts/base/protocols/dce-rpc/dpd.sig @@ -1,6 +1,5 @@ signature dpd_dce_rpc { - ip-proto == tcp - payload /^\x05[\x00\x01][\x00-\x13]\x03/ + payload /\x05[\x00\x01][\x00-\x13]/ enable "DCE_RPC" -} \ No newline at end of file +} diff --git a/scripts/base/protocols/dce-rpc/main.bro b/scripts/base/protocols/dce-rpc/main.bro index 2f8efd1659..5ec5ded2d8 100644 --- a/scripts/base/protocols/dce-rpc/main.bro +++ b/scripts/base/protocols/dce-rpc/main.bro @@ -204,4 +204,4 @@ event connection_state_remove(c: connection) Log::write(LOG, c$dce_rpc); } } - } \ No newline at end of file + } diff --git a/src/analyzer/protocol/dce-rpc/dce_rpc-analyzer.pac b/src/analyzer/protocol/dce-rpc/dce_rpc-analyzer.pac index d663db9f8b..53402fd9a0 100644 --- a/src/analyzer/protocol/dce-rpc/dce_rpc-analyzer.pac +++ b/src/analyzer/protocol/dce-rpc/dce_rpc-analyzer.pac @@ -118,36 +118,6 @@ refine connection DCE_RPC_Conn += { }; - -refine flow DCE_RPC_Flow += { - #%member{ - #FlowBuffer frag_reassembler_; - #%} - - # Fragment reassembly. - #function reassemble_fragment(frag: bytestring, lastfrag: bool): bool - # %{ - # int orig_data_length = frag_reassembler_.data_length(); - # - # frag_reassembler_.NewData(frag.begin(), frag.end()); - # - # int new_frame_length = orig_data_length + frag.length(); - # if ( orig_data_length == 0 ) - # frag_reassembler_.NewFrame(new_frame_length, false); - # else - # frag_reassembler_.GrowFrame(new_frame_length); - # - # return lastfrag; - # %} - - #function reassembled_body(): const_bytestring - # %{ - # return const_bytestring( - # frag_reassembler_.begin(), - # frag_reassembler_.end()); - # %} -}; - refine typeattr DCE_RPC_PDU += &let { proc = $context.connection.proc_dce_rpc_pdu(this); } diff --git a/src/analyzer/protocol/dce-rpc/dce_rpc-protocol.pac b/src/analyzer/protocol/dce-rpc/dce_rpc-protocol.pac index 06cba61471..826abd954d 100644 --- a/src/analyzer/protocol/dce-rpc/dce_rpc-protocol.pac +++ b/src/analyzer/protocol/dce-rpc/dce_rpc-protocol.pac @@ -1,5 +1,7 @@ # Definitions for DCE RPC. + + enum dce_rpc_ptype { DCE_RPC_REQUEST, DCE_RPC_PING, @@ -30,19 +32,14 @@ type context_handle = record { }; type DCE_RPC_PDU(is_orig: bool) = record { - # Set header's byteorder to little-endian (or big-endian) to - # avoid cyclic dependency. header : DCE_RPC_Header(is_orig); - # TODO: bring back reassembly. It was having trouble. - #frag : bytestring &length = body_length; - body : DCE_RPC_Body(header); + frag : bytestring &length=body_length; auth : DCE_RPC_Auth_wrapper(header); } &let { - #body_length : int = header.frag_length - sizeof(header) - header.auth_length; - #frag_reassembled : bool = $context.flow.reassemble_fragment(frag, header.lastfrag); - #body : DCE_RPC_Body(header) - # withinput $context.flow.reassembled_body() - # &if frag_reassembled; + # Subtract an extra 8 when there is an auth section because we have some "auth header" fields in that structure. + body_length : int = header.frag_length - sizeof(header) - header.auth_length - (header.auth_length > 0 ? 8 : 0); + frag_reassembled : bool = $context.flow.reassemble_fragment(header, frag); + body : DCE_RPC_Body(header) withinput $context.flow.reassembled_body(header, frag) &if(header.lastfrag); } &byteorder = header.byteorder, &length = header.frag_length; type NDR_Format = record { @@ -53,9 +50,6 @@ type NDR_Format = record { byteorder = (intchar >> 4) ? littleendian : bigendian; }; -# There might be a endianness problem here: the frag_length -# causes problems despite the NDR_Format having a byteorder set. - type DCE_RPC_Header(is_orig: bool) = record { rpc_vers : uint8 &check(rpc_vers == 5); rpc_vers_minor : uint8; @@ -66,8 +60,9 @@ type DCE_RPC_Header(is_orig: bool) = record { auth_length : uint16; call_id : uint32; } &let { - frag = pfc_flags & 4; - lastfrag = (! frag) || (pfc_flags & 2); + firstfrag = pfc_flags & 1; + lastfrag = (pfc_flags >> 1) & 1; + object = (pfc_flags >> 7) & 1; } &byteorder = packed_drep.byteorder; type Syntax = record { @@ -116,12 +111,15 @@ type DCE_RPC_Bind_Ack = record { contexts : ContextList(0); }; -type DCE_RPC_Request = record { +type DCE_RPC_Request(h: DCE_RPC_Header) = record { alloc_hint : uint32; context_id : uint16; opnum : uint16; - # object : uuid; - # stub_pad_0 : padding align 8; + has_object : case h.object of { + true -> uuid : uuid; + false -> no_uuid : empty; + }; + stub_pad : padding align 8; stub : bytestring &restofdata; }; @@ -130,7 +128,7 @@ type DCE_RPC_Response = record { context_id : uint16; cancel_count : uint8; reserved : uint8; - # stub_pad_0 : padding align 8; + stub_pad : padding align 8; stub : bytestring &restofdata; }; @@ -152,13 +150,13 @@ type DCE_RPC_AlterContext_Resp = record { type DCE_RPC_Body(header: DCE_RPC_Header) = case header.PTYPE of { DCE_RPC_BIND -> bind : DCE_RPC_Bind; DCE_RPC_BIND_ACK -> bind_ack : DCE_RPC_Bind_Ack; - DCE_RPC_REQUEST -> request : DCE_RPC_Request; + DCE_RPC_REQUEST -> request : DCE_RPC_Request(header); DCE_RPC_RESPONSE -> response : DCE_RPC_Response; # TODO: Something about the two following structures isn't being handled correctly. #DCE_RPC_ALTER_CONTEXT -> alter_context : DCE_RPC_AlterContext; #DCE_RPC_ALTER_CONTEXT_RESP -> alter_resp : DCE_RPC_AlterContext_Resp; default -> other : bytestring &restofdata; -} &length=header.frag_length - 16 - header.auth_length - (header.auth_length==0 ? 0 : 8); +}; type DCE_RPC_Auth_wrapper(header: DCE_RPC_Header) = case header.auth_length of { 0 -> none : empty; @@ -173,3 +171,41 @@ type DCE_RPC_Auth(header: DCE_RPC_Header) = record { context_id : uint32; blob : bytestring &length=header.auth_length; }; + +flow DCE_RPC_Flow(is_orig: bool) { + flowunit = DCE_RPC_PDU(is_orig) withcontext(connection, this); + + %member{ + std::map fb; + %} + + # Fragment reassembly. + function reassemble_fragment(header: DCE_RPC_Header, frag: bytestring): bool + %{ + if ( ${header.firstfrag} && !${header.lastfrag} && + fb.count(${header.call_id}) == 0 ) + fb[${header.call_id}] = new FlowBuffer(); + + if ( fb.count(${header.call_id}) == 0 ) + return false; + + auto frag_reassembler_ = fb[${header.call_id}]; + frag_reassembler_->BufferData(frag.begin(), frag.end()); + + return (!${header.firstfrag} && ${header.lastfrag}); + %} + + function reassembled_body(h: DCE_RPC_Header, body: bytestring): const_bytestring + %{ + const_bytestring bd = body; + + if ( fb.count(${h.call_id}) > 0 ) + { + bd = const_bytestring(fb[${h.call_id}]->begin(), fb[${h.call_id}]->end()); + delete fb[${h.call_id}]; + fb.erase(${h.call_id}); + } + + return bd; + %} +}; diff --git a/src/analyzer/protocol/dce-rpc/dce_rpc.pac b/src/analyzer/protocol/dce-rpc/dce_rpc.pac index 532e50bffb..f4a54a1e62 100644 --- a/src/analyzer/protocol/dce-rpc/dce_rpc.pac +++ b/src/analyzer/protocol/dce-rpc/dce_rpc.pac @@ -15,12 +15,8 @@ connection DCE_RPC_Conn(bro_analyzer: BroAnalyzer) { upflow = DCE_RPC_Flow(true); downflow = DCE_RPC_Flow(false); }; -%include dce_rpc-protocol.pac -# Now we define the flow: -flow DCE_RPC_Flow(is_orig: bool) { - flowunit = DCE_RPC_PDU(is_orig) withcontext(connection, this); -}; +%include dce_rpc-protocol.pac %include endpoint-atsvc.pac %include endpoint-epmapper.pac diff --git a/testing/btest/Baseline/scripts.base.protocols.dce-rpc.mapi/dce_rpc.log b/testing/btest/Baseline/scripts.base.protocols.dce-rpc.mapi/dce_rpc.log index 8628c63678..578ac1c0d3 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dce-rpc.mapi/dce_rpc.log +++ b/testing/btest/Baseline/scripts.base.protocols.dce-rpc.mapi/dce_rpc.log @@ -3,19 +3,19 @@ #empty_field (empty) #unset_field - #path dce_rpc -#open 2016-08-08-20-13-23 +#open 2016-10-08-03-48-34 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p rtt named_pipe endpoint operation #types time string addr port addr port interval string string string -1056991898.891148 C4J4Th3PJpwUYZZ6gc 192.168.0.173 1066 192.168.0.2 135 0.000375 135 epmapper ept_map -1056991898.895146 CtPZjS20MLrsMUOJi2 192.168.0.173 1067 192.168.0.2 4997 0.000749 4997 nspi NspiBind -1056991898.902393 CUM0KZ3MLUfNB0cl11 192.168.0.173 1068 192.168.0.2 4997 0.026606 4997 nspi NspiBind -1056991898.931248 CmES5u32sYpV7JYN 192.168.0.173 1069 192.168.0.2 135 0.000500 135 epmapper ept_lookup -1056991899.586840 CP5puj4I8PtEU4qzYg 192.168.0.173 1072 192.168.0.2 135 0.000374 135 epmapper ept_map -1056991899.594336 C37jN32gN3y3AZzyf6 192.168.0.173 1073 192.168.0.2 1032 0.031980 1032 exchange_mapi EcDoConnect -1056991899.626566 C37jN32gN3y3AZzyf6 192.168.0.173 1073 192.168.0.2 1032 0.024359 1032 exchange_mapi EcDoRpc -1056991899.652798 C37jN32gN3y3AZzyf6 192.168.0.173 1073 192.168.0.2 1032 0.001374 1032 exchange_mapi EcDoRpc -1056991899.655922 C37jN32gN3y3AZzyf6 192.168.0.173 1073 192.168.0.2 1032 0.000999 1032 exchange_mapi EcDoRpc -1056991899.658670 C37jN32gN3y3AZzyf6 192.168.0.173 1073 192.168.0.2 1032 0.001624 1032 exchange_mapi EcDoRpc -1056991899.660794 C37jN32gN3y3AZzyf6 192.168.0.173 1073 192.168.0.2 1032 0.003998 1032 exchange_mapi EcRRegisterPushNotification -1056991899.707516 C37jN32gN3y3AZzyf6 192.168.0.173 1073 192.168.0.2 1032 0.003998 1032 exchange_mapi EcRRegisterPushNotification -#close 2016-08-08-20-13-23 +1056991898.891148 CmES5u32sYpV7JYN 192.168.0.173 1066 192.168.0.2 135 0.000375 135 epmapper ept_map +1056991898.895146 CP5puj4I8PtEU4qzYg 192.168.0.173 1067 192.168.0.2 4997 0.000749 4997 nspi NspiBind +1056991898.902393 C37jN32gN3y3AZzyf6 192.168.0.173 1068 192.168.0.2 4997 0.026606 4997 nspi NspiBind +1056991898.931248 C3eiCBGOLw3VtHfOj 192.168.0.173 1069 192.168.0.2 135 0.000500 135 epmapper ept_lookup +1056991899.586840 C0LAHyvtKSQHyJxIl 192.168.0.173 1072 192.168.0.2 135 0.000374 135 epmapper ept_map +1056991899.594336 CFLRIC3zaTU1loLGxh 192.168.0.173 1073 192.168.0.2 1032 0.031980 1032 exchange_mapi EcDoConnect +1056991899.626566 CFLRIC3zaTU1loLGxh 192.168.0.173 1073 192.168.0.2 1032 0.024359 1032 exchange_mapi EcDoRpc +1056991899.652798 CFLRIC3zaTU1loLGxh 192.168.0.173 1073 192.168.0.2 1032 0.001374 1032 exchange_mapi EcDoRpc +1056991899.655922 CFLRIC3zaTU1loLGxh 192.168.0.173 1073 192.168.0.2 1032 0.000999 1032 exchange_mapi EcDoRpc +1056991899.658670 CFLRIC3zaTU1loLGxh 192.168.0.173 1073 192.168.0.2 1032 0.001624 1032 exchange_mapi EcDoRpc +1056991899.660794 CFLRIC3zaTU1loLGxh 192.168.0.173 1073 192.168.0.2 1032 0.003998 1032 exchange_mapi EcRRegisterPushNotification +1056991899.707516 CFLRIC3zaTU1loLGxh 192.168.0.173 1073 192.168.0.2 1032 0.003998 1032 exchange_mapi EcRRegisterPushNotification +#close 2016-10-08-03-48-34 diff --git a/testing/btest/Baseline/scripts.base.protocols.dce-rpc.mapi/ntlm.log b/testing/btest/Baseline/scripts.base.protocols.dce-rpc.mapi/ntlm.log index fdccebd649..ffe3248400 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dce-rpc.mapi/ntlm.log +++ b/testing/btest/Baseline/scripts.base.protocols.dce-rpc.mapi/ntlm.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path ntlm -#open 2016-08-08-20-13-23 +#open 2016-10-08-03-48-34 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p username hostname domainname success status #types time string addr port addr port string string string bool string -1056991898.902392 CUM0KZ3MLUfNB0cl11 192.168.0.173 1068 192.168.0.2 4997 ALeonard ALEONARD-XP CNAMIS - - -1056991899.594334 C37jN32gN3y3AZzyf6 192.168.0.173 1073 192.168.0.2 1032 ALeonard ALEONARD-XP CNAMIS - - -#close 2016-08-08-20-13-23 +1056991898.902392 C37jN32gN3y3AZzyf6 192.168.0.173 1068 192.168.0.2 4997 ALeonard ALEONARD-XP CNAMIS - - +1056991899.594334 CFLRIC3zaTU1loLGxh 192.168.0.173 1073 192.168.0.2 1032 ALeonard ALEONARD-XP CNAMIS - - +#close 2016-10-08-03-48-34