-
Notifications
You must be signed in to change notification settings - Fork 1
rdp snoop
RDP runs on TCP/3389 and is the Windows lateral-movement and
remote-administration substrate. The connection setup is cleartext
even when CredSSP/NLA is negotiated — the TPKT envelope (RFC 1006),
the X.224 Class 0 Connection Request TPDU, the optional cookie
Cookie: mstshash=USERNAME\r\n, and the RDP Negotiation Request
(MS-RDPBCGR §2.2.1.1) all sit ahead of the TLS/CredSSP wrap.
Sloth's first RDP pass is narrow: count X.224 Connection Request
TPDUs per (client_ip, server_ip), pull the username out of the
mstshash cookie when present, OR-accumulate the requested-protocol
bitmask, and fire RDP_BRUTE_FORCE when one client opens ≥10 CRs
to one server inside the active window. Same shape as
ssh-snoop — the encrypted auth itself is invisible, but brute
force is a connection-cadence signal, not a payload signal.
The TPKT envelope (RFC 1006 §6):
0 1 2 3
+-------+-------+---+---+
| ver=3 | rsvd | length |
+-------+-------+---+---+
Carrying an X.224 (T.0) Class 0 Connection Request TPDU:
0 1 2 3 4 5 6 ... user data ...
+-----+-----+--+--+--+--+----+----------------------------+
| LI | 0xE0| 0000 | SRC| co | cookie | RDP_NEG_REQ TLV |
+-----+-----+--+--+--+--+----+----------------------------+
| Byte/field | Meaning |
|---|---|
| TPKT byte 0 | version, always 0x03
|
| TPKT bytes 2-3 | total length, big-endian |
| X.224 byte 0 | length indicator (LI) — bytes that follow |
| X.224 byte 1 | TPDU code; 0xE0 = Connection Request |
| X.224 bytes 2-3 | DST-REF, always 0x0000 in Class 0 |
| Cookie field |
Cookie: mstshash=USERNAME\r\n (optional) |
| RDP_NEG_REQ | 0x01 flags 0x0008 protos(LE u32) |
protos is a bitmask: 0x01 = vanilla RDP, 0x02 = SSL/TLS, 0x04 =
HYBRID (CredSSP/NLA), 0x08 = HYBRID_EX. Sloth OR-accumulates what
it sees across all CRs on a flow.
Per-(client_ip, server_ip) aggregation: 64 flows tracked, oldest-by-last-seen evicted on overflow.
RDP_BRUTE_FORCE: 203.0.113.7->10.0.0.20: 47 RDP CRs
(brute-force; user=administrator)
| Field | Value |
|---|---|
| Severity | CRIT |
| Threshold |
connect_req_count ≥ 10 per (client_ip, server_ip) |
| Dedup key | rdp-brute:<client>-><server> |
match_ip |
src_ip (the attacking client) |
match_port |
3389 |
Why 10: matches the SSH threshold. Both protocols share the same brute-force shape (one TCP connection per credential attempt) and both have similar legitimate-reconnect baselines (a handful per session for users behind NAT or VPN with sleep/wake cycles). Ten distinct CRs to one server in the active window is unambiguous.
-
connect_req_countlow — typically 1–3 per legitimate user session per server. -
proto_maskcontainingHYBRID(0x04) — modern Windows defaults to NLA. -
last_cookieconsistent across observations (the user's own account or no cookie at all when client doesn't send one). - Few flows per active user.
-
connect_req_count ≥ 10from one source to one server — fires the alert. -
last_cookiecycling through different usernames against the samedst_ip— password spray. Therdp_flowrecord only remembers the last cookie; a SIEM-side rule walking the record stream catches the rotation. -
proto_maskcontaining only legacy RDP (0x01) — client refuses NLA, possibly because it's an attack tool that doesn't bother implementing the modern auth. - High flow count from one source to many servers — a
sweep-style scan trying RDP on every reachable host.
Not currently a dedicated alert; the
rdp_flowrecords expose the pattern for SIEM rules. -
last_cookie=administrator,admin, or any of the classic guess-list usernames. Worth surfacing on its own even below the count threshold; not currently a dedicated alert.
-
RDP Negotiation Response. The server's response carries
selectedProtocolplus failure codes if it rejects the client's request. Currently not parsed; would let us distinguish accepted from rejected CRs. - NLA / CredSSP user enumeration. Some CredSSP failure paths leak which usernames exist. Beyond Tier 1 scope.
- Connection-rate / per-second cadence. A flow that crams 20 CRs into 5 seconds is more brute-force-shaped than one that does it over an hour. The current count threshold catches both but doesn't differentiate.
- MS-RDPEDC client-channel inspection. Once TLS wraps the session, the DRDYNVC virtual channels are opaque to a passive observer.
- RFC 1006 — ISO Transport Service on top of TCP (TPKT).
- ITU-T X.224 — Connection-oriented Transport Protocol specification.
- [MS-RDPBCGR] — Microsoft Remote Desktop Protocol: Basic Connectivity and Graphics Remoting.
- MITRE ATT&CK T1110.001 — Brute Force: Password Guessing (RDP variant).
- MITRE ATT&CK T1021.001 — Remote Services: Remote Desktop Protocol.
- alerts — the rule that fires on the tracker's state.
-
jsonl-schema —
rdp_flowwire format. - ssh-snoop — the sibling remote-access brute-force observable. The detection model is the same.
Mirrored from docs/wiki/ on main by .github/scripts/wiki_sync.sh. Edit there, not here — hand edits to this wiki are overwritten on the next push.
Read this first — the complete reference
- what-sloth-does
- how-wifi-works
- monitor-mode
- where-exploits-happen
- wifi-sigint-techniques
- cli-reference
- wifi-state-of-the-art
Start here
Engines
WiFi SIGINT
- wifi-sigint
- non-ip-sensors
- mac-randomisation
- evil-twin-reproducer
- btm-abuse
- action-frames
- research-corpus
- captive-portal
- fragattacks
- tool-fingerprints
- enterprise-rogue
- ipv6-ndp
- smb-snoop
- kerberos-snoop
- ldap-snoop
- bgp-snoop
- ssh-snoop
- rdp-snoop
- snmp-snoop
- mqtt-snoop
UI and infrastructure
- ip-palette
- platform-vtable
- version-checkin
- manifest-format
- pcap-export
- jsonl-schema
- data-socket-exposure
- sqlite-schema
- ring-buffers
Factory infrastructure
Reference
Source material
Maintenance