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
- func IsDisconnectProviderUltimatum(raw []byte) bool
- func ReadAttachUserConfirm(r io.Reader) (userID uint16, raw []byte, err error)
- func ReadChannelJoinConfirm(r io.Reader) (acceptedChannelID uint16, raw []byte, err error)
- func ReadTPKTPayload(r io.Reader) ([]byte, error)
- func WriteAttachUserRequest(w io.Writer) error
- func WriteChannelJoinRequest(w io.Writer, userID, channelID uint16) error
- func WriteDisconnectProviderUltimatum(w io.Writer) error
- func WriteErectDomainRequest(w io.Writer) error
- func WriteMCSConnectInitial(w io.Writer) error
- func WriteTPKT(w io.Writer, payload []byte) error
- func WriteX224ConnectionRequest(w io.Writer, cookie string, requestedFlags uint32) error
- type ConnectResponse
- type ConnectionConfirm
Constants ¶
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.
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.
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.
const RequestAllProtocols uint32 = ProtocolSSL | ProtocolHybrid | ProtocolHybridEx
All protocols requested in a normal negotiation request.
Variables ¶
This section is empty.
Functions ¶
func IsDisconnectProviderUltimatum ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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.