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 0000000000..253367ac54 Binary files /dev/null and b/testing/btest/Traces/rdp/rdp-rdpeudp-handshake-fail.pcap differ diff --git a/testing/btest/Traces/rdp/rdp-rdpeudp-handshake-success.pcap b/testing/btest/Traces/rdp/rdp-rdpeudp-handshake-success.pcap new file mode 100644 index 0000000000..b6a984f1f5 Binary files /dev/null and b/testing/btest/Traces/rdp/rdp-rdpeudp-handshake-success.pcap differ diff --git a/testing/btest/scripts/base/protocols/rdp/rdp-rdpeudp-handshake-fail.zeek b/testing/btest/scripts/base/protocols/rdp/rdp-rdpeudp-handshake-fail.zeek new file mode 100644 index 0000000000..a0d644211f --- /dev/null +++ b/testing/btest/scripts/base/protocols/rdp/rdp-rdpeudp-handshake-fail.zeek @@ -0,0 +1,23 @@ +# @TEST-EXEC: zeek -r $TRACES/rdp/rdp-rdpeudp-handshake-fail.pcap %INPUT +# @TEST-EXEC: btest-diff conn.log + +@load base/protocols/rdp + +event rdpeudp_syn(c: connection) { + print "rdpeudp_syn"; +} + +event rdpeudp_synack(c: connection) { + print "rdpeudp_synack"; +} + +event rdpeudp_established(c: connection, version: count) { + print "rdpeudp_established"; + print "version", version; +} + +event rdpeudp_data(c: connection, is_orig: bool, version: count, data: string) +{ + print "rdpeudp_data"; + print fmt("is_orig: %s, version %d, data: %s", is_orig, version, data); +} diff --git a/testing/btest/scripts/base/protocols/rdp/rdp-rdpeudp-handshake-success.zeek b/testing/btest/scripts/base/protocols/rdp/rdp-rdpeudp-handshake-success.zeek new file mode 100644 index 0000000000..0bbc86d685 --- /dev/null +++ b/testing/btest/scripts/base/protocols/rdp/rdp-rdpeudp-handshake-success.zeek @@ -0,0 +1,23 @@ +# @TEST-EXEC: zeek -r $TRACES/rdp/rdp-rdpeudp-handshake-success.pcap %INPUT +# @TEST-EXEC: btest-diff conn.log + +@load base/protocols/rdp + +event rdpeudp_syn(c: connection) { + print "rdpeudp_syn"; +} + +event rdpeudp_synack(c: connection) { + print "rdpeudp_synack"; +} + +event rdpeudp_established(c: connection, version: count) { + print "rdpeudp_established"; + print "version", version; +} + +event rdpeudp_data(c: connection, is_orig: bool, version: count, data: string) +{ + print "rdpeudp_data"; + print fmt("is_orig: %s, version %d, data: %s", is_orig, version, data); +}