From 60644bc85fe5e6c2727c587a0ceba0c7b9525ec8 Mon Sep 17 00:00:00 2001 From: Anthony Kasza Date: Sun, 22 Mar 2020 14:43:54 -0600 Subject: [PATCH] Add RDP over UDP analyzer --- scripts/base/protocols/rdp/dpd.sig | 9 + scripts/base/protocols/rdp/main.zeek | 8 +- src/analyzer/protocol/rdp/CMakeLists.txt | 3 +- src/analyzer/protocol/rdp/Plugin.cc | 2 + src/analyzer/protocol/rdp/RDP.h | 3 - src/analyzer/protocol/rdp/RDPEUDP.cc | 37 +++ src/analyzer/protocol/rdp/RDPEUDP.h | 24 ++ src/analyzer/protocol/rdp/events.bif | 28 +++ .../protocol/rdp/rdpeudp-analyzer.pac | 112 +++++++++ .../protocol/rdp/rdpeudp-protocol.pac | 223 ++++++++++++++++++ src/analyzer/protocol/rdp/rdpeudp.pac | 24 ++ .../rdp/rdp-rdpeudp-handshake-fail.pcap | Bin 0 -> 3894 bytes .../rdp/rdp-rdpeudp-handshake-success.pcap | Bin 0 -> 5197 bytes .../rdp/rdp-rdpeudp-handshake-fail.zeek | 23 ++ .../rdp/rdp-rdpeudp-handshake-success.zeek | 23 ++ 15 files changed, 512 insertions(+), 7 deletions(-) create mode 100644 src/analyzer/protocol/rdp/RDPEUDP.cc create mode 100644 src/analyzer/protocol/rdp/RDPEUDP.h create mode 100644 src/analyzer/protocol/rdp/rdpeudp-analyzer.pac create mode 100644 src/analyzer/protocol/rdp/rdpeudp-protocol.pac create mode 100644 src/analyzer/protocol/rdp/rdpeudp.pac create mode 100644 testing/btest/Traces/rdp/rdp-rdpeudp-handshake-fail.pcap create mode 100644 testing/btest/Traces/rdp/rdp-rdpeudp-handshake-success.pcap create mode 100644 testing/btest/scripts/base/protocols/rdp/rdp-rdpeudp-handshake-fail.zeek create mode 100644 testing/btest/scripts/base/protocols/rdp/rdp-rdpeudp-handshake-success.zeek diff --git a/scripts/base/protocols/rdp/dpd.sig b/scripts/base/protocols/rdp/dpd.sig index f8ebff34b9..a4e6f237bb 100644 --- a/scripts/base/protocols/rdp/dpd.sig +++ b/scripts/base/protocols/rdp/dpd.sig @@ -10,3 +10,12 @@ signature dpd_rdp_server { ip-proto == tcp payload /(.{5}\xd0|.*McDn)/ } + +signature dpd_rdpeudp_syn { + ip-proto == udp + payload-size <= 1232 + payload-size >= 1132 + payload /^\xff{4}.{2}.{1}\x01/ + enable "rdpeudp" +} + diff --git a/scripts/base/protocols/rdp/main.zeek b/scripts/base/protocols/rdp/main.zeek index 2d6fd833f7..536638bc9a 100644 --- a/scripts/base/protocols/rdp/main.zeek +++ b/scripts/base/protocols/rdp/main.zeek @@ -85,13 +85,15 @@ redef record connection += { rdp: Info &optional; }; -const ports = { 3389/tcp }; -redef likely_server_ports += { ports }; +const rdp_ports = { 3389/tcp }; +const rdpeudp_ports = { 3389/udp }; +redef likely_server_ports += { rdp_ports, rdpeudp_ports }; event zeek_init() &priority=5 { Log::create_stream(RDP::LOG, [$columns=RDP::Info, $ev=log_rdp, $path="rdp"]); - Analyzer::register_for_ports(Analyzer::ANALYZER_RDP, ports); + Analyzer::register_for_ports(Analyzer::ANALYZER_RDP, rdp_ports); + Analyzer::register_for_ports(Analyzer::ANALYZER_RDP, rdpeudp_ports); } function write_log(c: connection) diff --git a/src/analyzer/protocol/rdp/CMakeLists.txt b/src/analyzer/protocol/rdp/CMakeLists.txt index 67ad09c18c..7011373593 100644 --- a/src/analyzer/protocol/rdp/CMakeLists.txt +++ b/src/analyzer/protocol/rdp/CMakeLists.txt @@ -3,8 +3,9 @@ include(ZeekPlugin) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) zeek_plugin_begin(Zeek RDP) - zeek_plugin_cc(RDP.cc Plugin.cc) + zeek_plugin_cc(RDPEUDP.cc RDP.cc Plugin.cc) zeek_plugin_bif(events.bif) zeek_plugin_bif(types.bif) zeek_plugin_pac(rdp.pac rdp-analyzer.pac rdp-protocol.pac ../asn1/asn1.pac) + zeek_plugin_pac(rdpeudp.pac rdpeudp-analyzer.pac rdpeudp-protocol.pac) zeek_plugin_end() diff --git a/src/analyzer/protocol/rdp/Plugin.cc b/src/analyzer/protocol/rdp/Plugin.cc index c4771d6a5e..7d07d4c564 100644 --- a/src/analyzer/protocol/rdp/Plugin.cc +++ b/src/analyzer/protocol/rdp/Plugin.cc @@ -1,4 +1,5 @@ #include "RDP.h" +#include "RDPEUDP.h" #include "plugin/Plugin.h" #include "analyzer/Component.h" @@ -10,6 +11,7 @@ public: plugin::Configuration Configure() override { AddComponent(new ::analyzer::Component("RDP", ::analyzer::rdp::RDP_Analyzer::InstantiateAnalyzer)); + AddComponent(new ::analyzer::Component("RDPEUDP", ::analyzer::rdpeudp::RDP_Analyzer::InstantiateAnalyzer)); plugin::Configuration config; config.name = "Zeek::RDP"; diff --git a/src/analyzer/protocol/rdp/RDP.h b/src/analyzer/protocol/rdp/RDP.h index a991e06921..99bad567a2 100644 --- a/src/analyzer/protocol/rdp/RDP.h +++ b/src/analyzer/protocol/rdp/RDP.h @@ -1,11 +1,8 @@ #pragma once #include "events.bif.h" - - #include "analyzer/protocol/tcp/TCP.h" #include "analyzer/protocol/pia/PIA.h" - #include "rdp_pac.h" namespace analyzer { namespace rdp { diff --git a/src/analyzer/protocol/rdp/RDPEUDP.cc b/src/analyzer/protocol/rdp/RDPEUDP.cc new file mode 100644 index 0000000000..a5e81d73ad --- /dev/null +++ b/src/analyzer/protocol/rdp/RDPEUDP.cc @@ -0,0 +1,37 @@ +#include "RDPEUDP.h" +#include "Reporter.h" +#include "events.bif.h" +#include "rdpeudp_pac.h" + +using namespace analyzer::rdpeudp; + +RDP_Analyzer::RDP_Analyzer(Connection* c) +: analyzer::Analyzer("RDPEUDP", c) + { + interp = new binpac::RDPEUDP::RDPEUDP_Conn(this); + } + +RDP_Analyzer::~RDP_Analyzer() + { + delete interp; + } + +void RDP_Analyzer::Done() + { + Analyzer::Done(); + } + +void RDP_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, + uint64_t seq, const IP_Hdr* ip, int caplen) + { + Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen); + + try + { + interp->NewData(orig, data, data + len); + } + catch ( const binpac::Exception& e ) + { + ProtocolViolation(fmt("Binpac exception: %s", e.c_msg())); + } + } diff --git a/src/analyzer/protocol/rdp/RDPEUDP.h b/src/analyzer/protocol/rdp/RDPEUDP.h new file mode 100644 index 0000000000..bd1ff6d0a4 --- /dev/null +++ b/src/analyzer/protocol/rdp/RDPEUDP.h @@ -0,0 +1,24 @@ +#pragma once + +#include "events.bif.h" +#include "analyzer/protocol/udp/UDP.h" +#include "rdpeudp_pac.h" + +namespace analyzer { namespace rdpeudp { +class RDP_Analyzer : public analyzer::Analyzer { + +public: + explicit RDP_Analyzer(Connection* conn); + ~RDP_Analyzer() override; + + void Done() override; + void DeliverPacket(int len, const u_char* data, bool orig, + uint64_t seq, const IP_Hdr* ip, int caplen) override; + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) + { return new RDP_Analyzer(conn); } + +protected: + binpac::RDPEUDP::RDPEUDP_Conn* interp; +}; + +} } diff --git a/src/analyzer/protocol/rdp/events.bif b/src/analyzer/protocol/rdp/events.bif index 178860bd42..7ba5a6a35b 100644 --- a/src/analyzer/protocol/rdp/events.bif +++ b/src/analyzer/protocol/rdp/events.bif @@ -1,3 +1,31 @@ +## Generated for RDPEUDP SYN UDP Datagram +## +## c: The connection record for the underlying transport-layer session/flow. +event rdpeudp_syn%(c: connection%); + +## Generated for RDPEUDP SYNACK UDP Datagram +## +## c: The connection record for the underlying transport-layer session/flow. +event rdpeudp_synack%(c: connection%); + +## Generated when RDPEUDP connections are established (both sides SYN) +## +## c: The connection record for the underlying transport-layer session/flow. +## +## version: Whether the connection is RDPEUDP1 or RDPEUDP2 +event rdpeudp_established%(c: connection, version: count%); + +## Generated when for data messages exchanged after a RDPEUDP connection establishes +## +## c: The connection record for the underlying transport-layer session/flow. +## +## is_orig: Whether the data was sent by the originator or responder of the connection. +## +## version: Whether the connection is RDPEUDP1 or RDPEUDP2 +## +## data: The payload of the packet. This is probably very non-performant. +event rdpeudp_data%(c: connection, is_orig: bool, version: count, data: string%); + ## Generated for each packet after RDP native encryption begins ## ## c: The connection record for the underlying transport-layer session/flow. diff --git a/src/analyzer/protocol/rdp/rdpeudp-analyzer.pac b/src/analyzer/protocol/rdp/rdpeudp-analyzer.pac new file mode 100644 index 0000000000..6bf9c384fa --- /dev/null +++ b/src/analyzer/protocol/rdp/rdpeudp-analyzer.pac @@ -0,0 +1,112 @@ +refine connection RDPEUDP_Conn += { + %member{ + enum RDPEUDP_STATE { + NEED_SYN = 0x1, + NEED_SYNACK = 0x2, + NED_ACK = 0x3, + ESTABLISHED = 0x4, + }; + uint8 state_ = NEED_SYN; + bool orig_rdpeudp2_ = false; + bool resp_rdpeudp2_ = false; + bool orig_lossy_ = false; + bool resp_lossy_ = false; + %} + function get_state(): uint8 + %{ + return state_; + %} + + function get_version(): bool + %{ + return (orig_rdpeudp2_ && resp_rdpeudp2_); + %} + + function proc_rdpeudp_syn(is_orig: bool, uFlags: uint16, snSourceAck: uint32): bool + %{ + if (!is_orig) { + return false; + } + if ((uFlags & 0x01) == 0) { + return false; + } + if (snSourceAck != 0xffffffff) { + return false; + } + + if (uFlags >= 0x1000) { + orig_rdpeudp2_ = true; + } + if ((uFlags & 0x0200) == 0x0200) { + orig_lossy_ = true; + } + if (rdpeudp_syn) { + BifEvent::generate_rdpeudp_syn(bro_analyzer(), bro_analyzer()->Conn()); + } + state_ = NEED_SYNACK; + return true; + %} + + function proc_rdpeudp_synack(is_orig: bool, uFlags: uint16): bool + %{ + if (is_orig) { + return false; + } + if ((uFlags & 0x05) == 0) { + return false; + } + + if (rdpeudp_synack) { + BifEvent::generate_rdpeudp_synack(bro_analyzer(), bro_analyzer()->Conn()); + } + bro_analyzer()->ProtocolConfirmation(); + state_ = NEED_ACK; + if (uFlags >= 0x1000) { + resp_rdpeudp2_ = true; + } + if ((uFlags & 0x0200) == 0x0200) { + resp_lossy_ = true; + } + return true; + %} + + function proc_rdpeudp1_ack(is_orig: bool, data: bytestring): bool + %{ + if (state_ == NEED_ACK) { + state_ = ESTABLISHED; + if (rdpeudp_established) { + BifEvent::generate_rdpeudp_established(bro_analyzer(), bro_analyzer()->Conn(), 1); + } + } + if ( state_ == ESTABLISHED && rdpeudp_data ) + BifEvent::generate_rdpeudp_data(bro_analyzer(), + bro_analyzer()->Conn(), + is_orig, + 1, + new StringVal(data.length(), (const char*) data.data()) + ); + return true; + %} + + function proc_rdpeudp2_ack(is_orig: bool, pkt_type: uint8, data: bytestring): bool + %{ + if (pkt_type == 8) { + // This is a "dummy packet". + return false; + } + if (state_ == NEED_ACK) { + if (rdpeudp_established) { + BifEvent::generate_rdpeudp_established(bro_analyzer(), bro_analyzer()->Conn(), 2); + } + state_ = ESTABLISHED; + } + if ( state_ == ESTABLISHED && rdpeudp_data ) + BifEvent::generate_rdpeudp_data(bro_analyzer(), + bro_analyzer()->Conn(), + is_orig, + 2, + new StringVal(data.length(), (const char*) data.data()) + ); + return true; + %} +}; diff --git a/src/analyzer/protocol/rdp/rdpeudp-protocol.pac b/src/analyzer/protocol/rdp/rdpeudp-protocol.pac new file mode 100644 index 0000000000..5660deb71e --- /dev/null +++ b/src/analyzer/protocol/rdp/rdpeudp-protocol.pac @@ -0,0 +1,223 @@ +# There are basically 5 PDU types for RDUEUDP1 +# 1. SYN - https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeudp/066f9acf-fd57-4f95-ab3f-334e748bab10 +# 2. SYNACK - https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeudp/96eaa81a-ff42-40a2-884c-96b3834db6c8 +# 3. ACK (bare) - https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeudp/facb0b31-63c6-44f4-aeec-03b5163aedae +# 4. ACK + FEC - https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeudp/7eaacd17-7012-468f-aa00-6e629cb88df8 +# 5. ACK + Source - https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeudp/427c5d29-6b08-4cdb-bbdf-a1ed09e76e2d +# There is basically 1 PDU type for RDPEUDP2. It has a bunch of optional fields indicated by flags. + + + +enum RDPEUDP_STATE { + NEED_SYN = 0x1, + NEED_SYNACK = 0x2, + NEED_ACK = 0x3, + ESTABLISHED = 0x4, +}; + +type RDPEUDP_PDU(is_orig: bool) = record { + state: case $context.connection.get_state() of { + NEED_SYN -> need_syn: RDPEUDP_SYN(this, is_orig); + NEED_SYNACK -> need_synack: RDPEUDP_SYNACK(this, is_orig); + NEED_ACK -> need_ack: RDPEUDP_ACK(this, is_orig); + default -> established: RDPEUDP_ACK(this, is_orig); + }; +} &byteorder=bigendian; + +type RDPEUDP_SYN(pdu: RDPEUDP_PDU, is_orig: bool) = record { + fec_header: RDPUDP_FEC_HEADER; + syndata_payload: RDPUDP_SYNDATA_PAYLOAD; +# TODO: parse the rest of the SYN pkt fields +# RDPUDP_CORRELATION_ID_PAYLOAD +# RDPUDP_SYNEX_PAYLOAD +# +} &let { + proc_rdpeudp_syn: bool = $context.connection.proc_rdpeudp_syn(is_orig, fec_header.uFlags, fec_header.snSourceAck); +}; + +type RDPUDP_SYNDATA_PAYLOAD = record { + snInitialSequenceNumber: uint32; + uUpStreamMtu: uint16; + uDownStreamMtu: uint16; +}; + +type RDPEUDP_SYNACK(pdu: RDPEUDP_PDU, is_orig: bool) = record { + fec_header: RDPUDP_FEC_HEADER; +} &let { + proc_rdpeudp_synack: bool = $context.connection.proc_rdpeudp_synack(is_orig, fec_header.uFlags); +}; + +enum RDPUDP_FLAG { + RDPUDP_FLAG_SYN = 0x0001, + RDPUDP_FLAG_FIN = 0x0002, + RDPUDP_FLAG_ACK = 0x0004, + RDPUDP_FLAG_DATA = 0x0008, + RDPUDP_FLAG_FEC = 0x0010, + RDPUDP_FLAG_CN = 0x0020, + RDPUDP_FLAG_CWR = 0x0040, + RDPUDP_FLAG_SACK_OPTION = 0x0080, + RDPUDP_FLAG_ACK_OF_ACKS = 0x0100, + RDPUDP_FLAG_SYNLOSSY = 0x0200, + RDPUDP_FLAG_ACKDELAYED = 0x0400, + RDPUDP_FLAG_CORRELATION_ID = 0x800, + RDPUDP_FLAG_SYNEX = 0x1000 +}; + +type RDPEUDP_ACK(pdu: RDPEUDP_PDU, is_orig: bool) = record { + version: case ($context.connection.get_version()) of { + true -> version2: RDPEUDP2_ACK(pdu, is_orig); + false -> version1: RDPEUDP1_ACK(pdu, is_orig); + }; +}; + +type RDPEUDP1_ACK(pdu: RDPEUDP_PDU, is_orig: bool) = record { + fec_header: RDPUDP_FEC_HEADER; + ack_vec_header: RDPUDP_ACK_VECTOR_HEADER; + ack_of_ackvec_header: case fec_header.uFlags & RDPUDP_FLAG_ACK_OF_ACKS of { + RDPUDP_FLAG_ACK_OF_ACKS -> some: RDPUDP_ACK_OF_ACKVECTOR_HEADER; + default -> no_ack_of_ackvec_header: empty; + }; + # This doesn't handle ACK+FEC packets, which have both RDPUDP_FLAG_DATA and RDPUDP_FLAG_FEC set + source_payload_header: case (fec_header.uFlags & RDPUDP_FLAG_DATA) of { + RDPUDP_FLAG_DATA -> some_source_payload: RDPUDP_SOURCE_PAYLOAD_HEADER; + default -> no_source_payload_header: empty; + }; + data: bytestring &restofdata; +} &let { + proc_rdpeudp1_ack: bool = $context.connection.proc_rdpeudp1_ack(is_orig, data); +}; + +type RDPUDP_SOURCE_PAYLOAD_HEADER = record { + snCoded: uint32; + snSourceStart: uint32; +}; + +type RDPUDP_ACK_OF_ACKVECTOR_HEADER = record { + snAckOfAcksSeqNum: uint32; +}; + +type RDPUDP_FEC_HEADER = record { + snSourceAck: uint32; + uReceiveWindowSize: uint16; + uFlags: uint16; +}; + +type RDPUDP_ACK_VECTOR_HEADER = record { + uAckVectorSize: uint16; + AckVectorElement: uint8[uAckVectorSize]; + pad: padding align 4; +}; + +# version 2 +type RDPEUDP2_ACK(pdu: RDPEUDP_PDU, is_orig: bool) = record { + PacketPrefixByte: uint8; + header: RDPUDP2_PACKET_HEADER; +# TODO: +# ack_payload: case ((header.Flags & ACK) > 0) of { +# true -> has_ack_p: RDPUDP2_ACK_PAYLOAD; +# false -> has_no_ack_p: empty; +# }; +# oversize_payload: case ((header.Flags & 0x040) > OVERHEADSIZE) of { +# true -> has_oversize: RDPUDP2_OVERSIZE_PAYLOAD; +# false -> has_no_oversize: empty; +# }; +# delay_ack_info_payload: case ((header.Flags & DELAYACKINFO) > 0) of { +# true -> has_ack_info_p: RDPUDP2_DELAYACKINFO_PAYLOAD; +# false -> has_no_ack_info_p: empty; +# }; +# ack_of_acks_payload: case ((header.Flags & AOA) > 0) of { +# true -> has_aoa_p: RDPUDP2_ACKOFACKS_PAYLOAD; +# false -> has_no_aoa_p: empty; +# }; +# data_header_payload: case ((header.Flags & DATA) > 0) of { +# true -> has_data_h: RDPUDP2_DATAHEADER_PAYLOAD; +# false -> has_no_data_h: empty; +# }; +# ack_vector_payload: case ((header.Flags & ACKVEC) > 0) of { +# true -> has_av_p: RDPUDP2_ACKVECTOR_PAYLOAD; +# false -> has_no_av_p: empty; +# }; +# data_body_payload: case ((header.Flags & DATA) > 0) of { +# true -> has_data_p: RDPUDP2_DATABODY_PAYLOAD; +# false -> has_no_data_p: empty; +# }; +# data_body_payload: RDPUDP2_DATABODY_PAYLOAD; + data: bytestring &restofdata; +} &let { + Reserved: uint8 = PacketPrefixByte & 0x80; + Packet_Type_Index: uint8 = PacketPrefixByte & 0x78; + Short_Packet_Length: uint8 = PacketPrefixByte & 0x07; +# proc_rdpeudp2_ack: bool = $context.connection.proc_rdpeudp2_ack(is_orig, Packet_Type_Index, data_body_payload.Data); + proc_rdpeudp2_ack: bool = $context.connection.proc_rdpeudp2_ack(is_orig, Packet_Type_Index, data); +}; + +type RDPUDP2_PACKET_HEADER = record { + everything: uint16; +} &let { + Flags: uint16 = everything & 0xfff0; # The high 12 + LogWindowSize: uint8 = everything & 0x000f; # The low 4 +}; + +enum RDPUDP2_PACKET_HEADER_FLAGS { + ACK = 0x001, + DATA = 0x004, + ACKVEC = 0x008, + AOA = 0x010, + OVERHEADSIZE = 0x040, + DELAYACKINFO = 0x100 +}; + +type RDPUDP2_ACK_PAYLOAD = record { + SeqNum: uint16; + tmp1: uint32; + tmp2: uint8; + delayAckTimeAdditions: uint8[numDelayedAcks]; +} &let { + receivedTS: uint8 = tmp1 & 0xffffff00; + sendAckTimeGap: uint8 = tmp1 & 0xff; + numDelayedAcks: uint8 = tmp2 & 0xf0; # top 4 bits + delayAckTimeScale: uint8 = tmp2 & 0x0f; # bottom 4 bits +}; + +type RDPUDP2_OVERSIZE_PAYLOAD = record{ + OverheadSize: uint8; +}; + +type RDPUDP2_DATABODY_PAYLOAD = record { + ChannelSeqNum: uint16; + Data: bytestring &restofdata; +}; + +type RDPUDP2_ACKVECTOR_PAYLOAD = record { + BaseSeqNum: uint16; + tmp1: uint8; + TimeStamp_or_not: case TimeStampPresent of { + 0 -> none: empty; + default -> some: RDPUDP2_ACKVECTOR_PAYLOAD_TimeStamp; + } &requires(TimeStampPresent); + codedAckVector: uint8[codedAckVecSize]; +} &let { + codedAckVecSize: uint8 = tmp1 & 0xfe; + TimeStampPresent: uint8 = tmp1 & 0x01; +}; + +type RDPUDP2_ACKVECTOR_PAYLOAD_TimeStamp = record { + tmp1: uint8; + tmp2: uint8; + tmp3: uint8; +} &let { + TimeStamp: uint32 = tmp3 | (tmp2 << 8) | (tmp1 << 16); +}; + +type RDPUDP2_DATAHEADER_PAYLOAD = record { + DataSeqNum: uint16; +}; + +type RDPUDP2_ACKOFACKS_PAYLOAD = record { + AckOfAcksSeqNum: uint16; +}; + +type RDPUDP2_DELAYACKINFO_PAYLOAD = record { + MaxDelayedAcks: uint8; + DelayedAckTimeoutInMs: uint16; +}; diff --git a/src/analyzer/protocol/rdp/rdpeudp.pac b/src/analyzer/protocol/rdp/rdpeudp.pac new file mode 100644 index 0000000000..525c3b05ee --- /dev/null +++ b/src/analyzer/protocol/rdp/rdpeudp.pac @@ -0,0 +1,24 @@ +%include binpac.pac +%include bro.pac + +%extern{ + #include "events.bif.h" +%} + +analyzer RDPEUDP withcontext { + connection: RDPEUDP_Conn; + flow: RDPEUDP_Flow; +}; + +connection RDPEUDP_Conn(bro_analyzer: BroAnalyzer) { + upflow = RDPEUDP_Flow(true); + downflow = RDPEUDP_Flow(false); +}; + +%include rdpeudp-protocol.pac + +flow RDPEUDP_Flow(is_orig: bool) { + datagram = RDPEUDP_PDU(is_orig) withcontext(connection, this); +}; + +%include rdpeudp-analyzer.pac diff --git a/testing/btest/Traces/rdp/rdp-rdpeudp-handshake-fail.pcap b/testing/btest/Traces/rdp/rdp-rdpeudp-handshake-fail.pcap new file mode 100644 index 0000000000000000000000000000000000000000..253367ac5447b6d3c054a24d1bf76bc4556023f9 GIT binary patch literal 3894 zcmca|c+)~A1{MYcU}0bca`t!|$NgyJVfY1<0$~mY^`+*QxER!davTh<3@mS^CNMD6 z3toP4V1*hZ5U2eJ;I(DB5zF@<2pAkB7~eS*-eI}Ga^XiXbHb^5C&y*QB~KNk5ca@X zj0{Y0_9$aC1V%$(Gz11w2pj;Gghn@5@RWr7e4vsr%6haU97NGJ>XgwC7!3ichQMK9 lNjPmQq&L^7wVv~&Od%@eb?Iinf-g7@BZwW?|#-) zm*!`o00(~-4iNIhtBC7Y)e3+bWmtcH4nTs$pFG8%YsAWrlE<)7zL2i9G$;JI-P<9u z09OxD(cC@;ufnUgcvtZUewp>*YWwH&uX5#EWXA}={$g}=Xq3Pxfl&hgI02ZBLGAx* zI?|lF*5c2XHN#W{Ty+XPxkCk}BblSOdq?nOlG(RZ1V9zeLMEjSln#c0d~)WWG0cx!w7@(%eS_((0Omd{evn%*{p^Mg zcAMPJj%tvDip#CY~r(7E{IAVlBV{lR-L215RKXume^= z83+IuH~<@<1t569=E_e-+ZPvgAQf#5!tb75uLCDI-76n;Fb$JE=CT%30nn)my`Z|L z9tkG|*Ahx4_ickKIzRfA9{M)sG3`I~>eVwoQ zV%GJ_yty2U?7oI4&IC@pS zJoMG$i2vRVH}~WUPcy_PHCys5PWcRu%N~>IcO`Y}`iciHLExdX>NyGHuc@sM+t;%GVJr&q1<2;Bfogr z#>50di+lzKCb%l0te|ABfKVuk7(%GPK{}3OC{D<8Bp)2f5dqA&!&8Fh`(AZ@8Gne= z$<8pybd1<6TybE(UB++h!l|ikFKJ(AC->V5?sSI;#_--nH>f1oH)n&o4kdtF_3wBSMljW7z|D=f*&fRXvapDRb+Rrqs z3>fI8PMWu(@}A^F62av%o$P;ZN#SnfOLRO^Yqj4?Oxdo|&&pceX=h*8tan^`;p14U zO7o`k1cTnr)5_?~;Mvkd#rA?XMOkXZ-CcEgcW9lnVqR`7Q;1yS!b$s=JN4+I`Y@|= zZp&F>VY&Xc+gfpzGm0*?3>Ma$P|>rS_wbGM(Q6~2pO_gH@re9!nPI?y)oS^}DUTKb zwL4{Re|-AVqvw=o_ttHCm0n_6oDx-CqK=ZRg0*%U`1?QK%J1KBAC(N$&PzQ)KM_~> zATnWlIh7^sqYvC%)(~5I(J)Wy!FXRivu*Vuo}qF;xs+Gl_Vi1T3*BLJ33HG$`$Zqs z<=)=e`5KwsQDb$?H0*OlF}uMAmrv$yJHC1ykh)d8*jdu*`+ym6Y-#=O!Nk>Xq}wd` zan;@y z{{`pEcltlo)*oSof8kkOov7Xtd?{!ePjDn};B@rN6@gI-PfNUR<%`Z_S4?R3Suic8 zoVTKNM%1NNpYLsYv=1VyZZ9uoPcA4k%6WW2`bmw9GnjCb)DiFtc?>0AvgnT*IpN^n z1|TZB045q4lQ7|6^y@;w=r>UZz>sxJ@S%4iP-9R7qqW869GHP z1}OQG+4mgTJ`8B!`B4el9S&#&1~d)oFHA`$8z-f9EmgLfvc#w7twyZWIjeYo-KPoB zS*@KNLS6ziWjPxG`$#uX@+C9nJ+i59Ouf~a(8MrP1Txiw(j^($%BDqnL{;03eOJC# z+#Mh6`21=BcS#bn(1wv)9ccRFIQOK-i9G{frmSt5sqd3{2U^?ciGWD58A`rn)|^MS z_KlbGyFO@Tm=_9psX;+&EZMY3>aLsT@sv5bhjV&N*c8!~b03B0vWv@)K^tnf(ErP~ z?imX%J4^_Lg!G}HjioXh=x>Uzd~#|^21=-