rdp

package
v0.0.193 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 17, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package rdp implements the minimal MS-RDPBCGR / T.125 / T.124 subset required for pre-auth RDP fingerprinting and the BlueKeep (CVE-2019-0708) precondition validation.

Reference: MS-RDPBCGR (https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/) BlueKeep byte sequences cited from rdpscan by Robert Graham (errata.com/blog/2019/2019-05-22-bluekeep) and the MSRC advisory advisory ADV190005 (https://msrc.microsoft.com/update-guide/vulnerability/CVE-2019-0708).

Index

Constants

View Source
const (
	ProtocolRDP            uint32 = 0x00000000
	ProtocolSSL            uint32 = 0x00000001
	ProtocolHybrid         uint32 = 0x00000002
	ProtocolRDSTLS         uint32 = 0x00000004
	ProtocolHybridEx       uint32 = 0x00000008
	ProtocolHybridRecLimit uint32 = 0x00000010
)

Protocol flag constants per MS-RDPBCGR §2.2.1.1.1 rdpNegReq / §2.2.1.2.1 rdpNegRsp.

View Source
const (
	FailureSSLRequiredByServer             uint32 = 0x00000001
	FailureSSLNotAllowedByServer           uint32 = 0x00000002
	FailureSSLCertNotOnServer              uint32 = 0x00000003
	FailureInconsistentFlags               uint32 = 0x00000004
	FailureHybridRequiredByServer          uint32 = 0x00000005
	FailureSSLWithUserAuthRequiredByServer uint32 = 0x00000006
)

Failure codes per MS-RDPBCGR §2.2.1.2.2 rdpNegFailure.

View Source
const MsT120RebindChannelID uint16 = 1004

MsT120RebindChannelID is the channel ID used for the BlueKeep MS_T120 rebind probe. Per the rdpscan PoC and Metasploit module, this is typically the I/O channel (1003) + 1 (= 1004). Patched servers reject Channel-Join-Request for non-default MS_T120 channel IDs; vulnerable servers reply with Channel-Join-Confirm.

All protocols requested in a normal negotiation request.

Variables

This section is empty.

Functions

func IsDisconnectProviderUltimatum

func IsDisconnectProviderUltimatum(raw []byte) bool

IsDisconnectProviderUltimatum returns true if raw is an MCS Disconnect-Provider-Ultimatum PDU. Per T.125 §10.8, the APER tag for Disconnect-Provider-Ultimatum is 0x21. After the X.224 DT header (3 bytes), the MCS tag appears at offset 3.

func ReadAttachUserConfirm

func ReadAttachUserConfirm(r io.Reader) (userID uint16, raw []byte, err error)

ReadAttachUserConfirm reads an MCS Attach-User-Confirm and extracts the userID. Per T.125 §10.4:

APER AttachUserConfirm: 0x2e result(1) initiator(2)

The initiator (userID) is a uint16 with a base offset of 1001.

func ReadChannelJoinConfirm

func ReadChannelJoinConfirm(r io.Reader) (acceptedChannelID uint16, raw []byte, err error)

ReadChannelJoinConfirm reads an MCS Channel-Join-Confirm. Per T.125 §10.6: APER ChannelJoinConfirm result(1) initiator(2) requested(2) channelId(2). Returns the accepted channelID (0 if result != 0).

func ReadTPKTPayload

func ReadTPKTPayload(r io.Reader) ([]byte, error)

ReadTPKTPayload reads one TPKT frame (RFC 1006) from r, returning the X.224 payload (i.e., the bytes after the 4-byte TPKT header).

func WriteAttachUserRequest

func WriteAttachUserRequest(w io.Writer) error

WriteAttachUserRequest sends an MCS Attach-User-Request PDU. Per T.125 §10.3, the server responds with an Attach-User-Confirm. MCS APER AttachUserRequest = single byte 0x28.

func WriteChannelJoinRequest

func WriteChannelJoinRequest(w io.Writer, userID, channelID uint16) error

WriteChannelJoinRequest sends an MCS Channel-Join-Request PDU. Per T.125 §10.5: APER ChannelJoinRequest initiator(2) channelId(2).

`userID` is the full MCS user channel ID (e.g. 1001) as returned by ReadAttachUserConfirm. T.125 §10.4 encodes UserId on the wire as an offset from the base value 1001, so the initiator field is written as userID - 1001 to match the wire format the server expects (and to stay consistent with the +1001 adjustment ReadAttachUserConfirm applies on the receive side).

func WriteDisconnectProviderUltimatum

func WriteDisconnectProviderUltimatum(w io.Writer) error

WriteDisconnectProviderUltimatum sends an MCS Disconnect-Provider-Ultimatum PDU to cleanly close the session before TCP close. Per T.125 §10.8: APER tag 0x21, reason (4-bit enumerant). Reason 3 = "rn-provider-initiated" — the initiator is disconnecting.

func WriteErectDomainRequest

func WriteErectDomainRequest(w io.Writer) error

WriteErectDomainRequest sends an MCS Erect-Domain-Request PDU. Per T.125 §10.1, no response is expected. BER: APPLICATION 1 (0x28) length=5, subHeight=1, subInterval=1.

Source: T.125 §10.1 ErectDomainRequest, canonical bytes from rdpscan/Metasploit.

func WriteMCSConnectInitial

func WriteMCSConnectInitial(w io.Writer) error

WriteMCSConnectInitial writes an MCS Connect-Initial PDU with a canned GCC Conference Create Request that requests the MS_T120 virtual channel. Framing: TPKT (RFC 1006) → X.224 DT (Data TPDU) → MCS PDU (BER).

func WriteTPKT

func WriteTPKT(w io.Writer, payload []byte) error

WriteTPKT writes a TPKT-framed (RFC 1006) payload to w. TPKT header: version=3, reserved=0, length uint16 BE (includes 4-byte header).

func WriteX224ConnectionRequest

func WriteX224ConnectionRequest(w io.Writer, cookie string, requestedFlags uint32) error

WriteX224ConnectionRequest writes an X.224 Connection Request PDU with an rdpNegReq embedded. cookie is sent as the TPKT routing cookie (e.g. "mstshash=test"). requestedFlags is the 32-bit protocol bitmap sent in rdpNegReq.

Structure per MS-RDPBCGR §2.2.1.1:

TPKT header (4)
X.224 CR (7): LI, CR PDU code (0xe0), DST-REF (2), SRC-REF (2), CLASS (1)
optional cookie
rdpNegReq (8): type(1)=0x01, flags(1), length(2)=0x0008, requestedProtocols(4)

Types

type ConnectResponse

type ConnectResponse struct {
	// MsT120ChannelID is the server-assigned channel ID for MS_T120 virtual channel,
	// extracted from the GCC Conference Create Response user data if available.
	// Zero if not found.
	MsT120ChannelID uint16
	RawPDU          []byte
}

ConnectResponse holds the result of an MCS Connect-Response.

func ReadMCSConnectResponse

func ReadMCSConnectResponse(r io.Reader) (*ConnectResponse, error)

ReadMCSConnectResponse reads and parses an MCS Connect-Response PDU. It returns the raw PDU and attempts to find the server-assigned MS_T120 channel ID from the embedded GCC Conference Create Response user data.

The Connect-Response BER tag for APPLICATION 102 (0x7f66) followed by T.125 ConnectResponse structure. The channel IDs are in the GCC ConferenceCreateResponse user data (which is inside the Connect-Response userData OCTET STRING).

For BlueKeep detection we don't need to fully parse the GCC user data; we use a heuristic: the server normally assigns I/O channel at 1003 and MS_T120 just after. Many PoCs simply hard-code 1004 for the rebind channel ID.

type ConnectionConfirm

type ConnectionConfirm struct {
	NegResponseReceived bool
	NegFailureReceived  bool
	SelectedProtocol    uint32 // valid if NegResponseReceived
	NegFlags            uint8  // valid if NegResponseReceived
	FailureCode         uint32 // valid if NegFailureReceived
	RawPDU              []byte
}

ConnectionConfirm is the result of parsing an X.224 Connection Confirm PDU.

func ReadX224ConnectionConfirm

func ReadX224ConnectionConfirm(r io.Reader) (*ConnectionConfirm, error)

ReadX224ConnectionConfirm reads and parses an X.224 Connection Confirm PDU. It handles optional rdpNegRsp or rdpNegFailure sub-messages.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL