CVE-2019-0708(BlueKeep)Windows远程桌面RDP
import socket import struct import sys def create_rdp_connection_request(): """ 构建一个基础的 RDP Connection Request PDU。 注意:这只是一个合法的、标准的 RDP 握手包,不包含任何漏洞利用载荷。 """ # RDP 协议版本 (5.0) rdp_version = 0x00080001 # 构建 RDP Negotiation Request (可选,简化版直接发 Connection Request) # 这里我们构建一个最简化的 Initial Client Data PDU # TPKT (Transport Protocol Data Unit) # Length: 可变,稍后计算 # Type: 0x0E (X.224 Connection Request) # X.224 Connection Request PDU # Length: 可变 # Type: 0xE0 # dst_ref, src_ref, class: 0x0000, 0x0000, 0x00 # RDP Core Data # version: 0x00080001 # clientName: 固定填充 client_name = "TESTCLIENT\x00" * 2 # 填充至足够长度 client_name_bytes = client_name.encode('ascii')[:32].ljust(32, b'\x00') # 构造一个简单的 RDP 初始包 (简化版,仅用于演示 TCP 连通性和端口识别) # 真实的 RDP 握手非常复杂,包含加密协商等步骤 # 为了演示目的,我们发送一个符合 TPKT + X.224 CR 结构的包 # 实际漏洞触发需要极其复杂的 Channel Definition 和 Memory Corruption 逻辑,此处省略 # 这是一个标准的 X.224 Connection Request 头部 x224_cr = bytearray() x224_cr.append(0x0e) # Length MSB (will be updated) x224_cr.append(0x00) # Length LSB x224_cr.append(0xe0) # Type: Connection Request x224_cr.append(0x00) # dst_ref x224_cr.append(0x00) # src_ref x224_cr.append(0x00) # class # RDP Negotiation Request (可选,通常用于协商 SSL/TLS) # 如果目标是旧系统且未强制 NLA,可能直接接受 RDP 加密 # 组合包 packet = bytes(x224_cr) # 更新长度 (TPKT length includes itself) # TPKT Header: 4 bytes (Length 2, Type 1, Reserved 1) - 但 X.224 CR 通常直接跟在 TCP 后或作为 TPKT 负载 # 标准 TPKT: # Byte 0-1: Length (Big Endian) # Byte 2: Type (0x0E for CR if using X.224 directly over TCP without TPKT wrapper in some contexts, # but usually TPKT wraps it. Let's use standard TPKT wrapping X.224 CR) # 重新构建:TPKT -> X.224 CR tpkt_length = len(x224_cr) + 4 # TPKT header is 4 bytes? No, TPKT is 4 bytes total including length field? # TPKT Format: # Version (1 byte): 0x03 # Reserved (1 byte): 0x00 # Length (2 bytes): Total length of TPKT including header # Let's stick to the most common raw RDP probe which is just checking if port is open and responds. # For a true protocol interaction, we need to send a valid RDP PDU. # Simplified valid RDP Initial PDU structure for detection # This is a non-exploit, standard handshake attempt. buf = bytearray() # TPKT Header buf.append(0x03) # Version buf.append(0x00) # Reserved # Length will be filled later # X.224 Connection Request buf.append(0x00) # Length MSB (placeholder) buf.append(0x00) # Length LSB (placeholder) buf.append(0xe0) # Type buf.append(0x00) # dst_ref buf.append(0x00) # src_ref buf.append(0x00) # class # RDP Negotiation Request (Optional, but good for modern servers) # Type: 0x01 (RDP_NEG_REQ) # Flags: 0x00 # Length: 0x08 # Protocols: 0x03 (SSL | HYBRID) or 0x00 (Standard RDP) neg_req = bytearray() neg_req.append(0x01) # Type neg_req.append(0x00) # Flags neg_req.append(0x08) # Length (LSB) neg_req.append(0x00) # Length (MSB) neg_req.append(0x03) # Protocols (SSL | HYBRID) - Try to negotiate secure neg_req.append(0x00) neg_req.append(0x00) neg_req.append(0x00) buf.extend(neg_req) # Update lengths total_len = len(buf) # TPKT Length (bytes 2-3 of TPKT, which are indices 2 and 3 in our buf if we started with version/reserved) # Wait, my buf structure: # 0: Ver # 1: Res # 2: Len MSB # 3: Len LSB # ... buf[2] = (total_len >> 8) & 0xFF buf[3] = total_len & 0xFF return bytes(buf) def scan_rdp(target_ip, port=3389, timeout=5): """ 尝试连接目标 RDP 端口并发送基础握手包。 """ print(f"[*] 正在扫描 {target_ip}:{port} ...") try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(timeout) sock.connect((target_ip, port)) print("[+] 端口开放,正在发送 RDP 握手请求...") request = create_rdp_connection_request() sock.send(request) # 接收响应 response = sock.recv(1024) if response: print("[+] 收到响应:") print(f" Hex: {response.hex()}") # 简单的响应解析 if len(response) >= 4: if response[0] == 0x03 and response[2] == 0x00: # TPKT if response[4] == 0x0e: # X.224 Connect Confirm print(" 类型: X.224 Connect Confirm (连接成功)") elif response[4] == 0x02: # X.224 Disconnect print(" 类型: X.224 Disconnect (连接被拒绝/断开)") else: print("[-] 未收到响应") sock.close() return True except socket.timeout: print("[-] 连接超时") return False except ConnectionRefusedError: print("[-] 连接被拒绝") return False except Exception as e: print(f"[-] 发生错误: {e}") return False if __name__ == "__main__": if len(sys.argv) < 2: print("用法: python rdp_scanner.py <target_ip>") sys.exit(1) target = sys.argv[1] scan_rdp(target)
CVE-2019-0708 的根本原因在于 Windows RDP 服务在处理特定虚拟通道(MS_T120)请求时存在“释放后重用”(Use-After-Free)漏洞。攻击者通过发送特制的 RDP 连接请求,在身份验证之前即可触发该漏洞。
nmap --script rdp-ntlm-info -p 3389 <目标IP> - 如果输出中包含
NTLM相关信息且表明支持CredSSP或NLA,则说明目标支持并可能启用了网络级身份验证。 - 如果响应显示仅支持
Standard RDP Security而不提及 NLA/CredSSP,则可能未启用。
浙公网安备 33010602011771号