From 0d47952611198ef6b1163f366dc03922d20b1475 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 09:42:04 +0200 Subject: Adding upstream version 7.94+git20230807.3be01efb1+dfsg. Signed-off-by: Daniel Baumann --- nselib/rdp.lua | 453 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 453 insertions(+) create mode 100644 nselib/rdp.lua (limited to 'nselib/rdp.lua') diff --git a/nselib/rdp.lua b/nselib/rdp.lua new file mode 100644 index 0000000..e468a96 --- /dev/null +++ b/nselib/rdp.lua @@ -0,0 +1,453 @@ +--- +-- A minimal RDP (Remote Desktop Protocol) library. Currently has functionality to determine encryption +-- and cipher support. +-- +-- +-- @author Patrik Karlsson +-- @copyright Same as Nmap--See https://nmap.org/book/man-legal.html +-- + +local nmap = require("nmap") +local stdnse = require("stdnse") +local string = require "string" +local asn1 = require "asn1" +_ENV = stdnse.module("rdp", stdnse.seeall) + +-- Server Core Data 2.2.1.4.2 +PROTO_VERSION = { + [0x00080001] = " RDP 4.0 server", + [0x00080004] = " RDP 5.x, 6.x, 7.x, or 8.x server", + [0x00080005] = " RDP 10.0 server", + [0x00080006] = " RDP 10.1 server", + [0x00080007] = " RDP 10.2 server", + [0x00080008] = " RDP 10.3 server", + [0x00080009] = " RDP 10.4 server", + [0x0008000A] = " RDP 10.5 server", + [0x0008000B] = " RDP 10.6 server", + [0x0008000C] = " RDP 10.7 server", +} + +-- T.125 Result enumerated type +CONNECT_RESPONSE_RESULT = { + [ 0] = "rt-successful", + [ 1] = "rt-domain-merging", + [ 2] = "rt-domain-not-hierarchical", + [ 3] = "rt-no-such-channel", + [ 4] = "rt-no-such-domain", + [ 5] = "rt-no-such-user", + [ 6] = "rt-not-admitted", + [ 7] = "rt-other-user-id", + [ 8] = "rt-parameters-unacceptable", + [ 9] = "rt-token-not-available", + [10] = "rt-token-not-possessed", + [11] = "rt-too-many-channels", + [12] = "rt-too-many-tokens", + [13] = "rt-too-many-users", + [14] = "rt-unspecified-failure", + [15] = "rt-user-rejected", +} + +-- requestedProtocols - flag - RDP_NEG_REQ - MS-RDPBCGR 2.2.1.1.1 +PROTOCOL_RDP = 0 -- Standard RDP Security +PROTOCOL_SSL = 1 -- TLS 1.0, 1.1, 1.2 +PROTOCOL_HYBRID = 2 -- CredSSP (NLA). TLS flag should be set as well +PROTOCOL_RDSTLS = 4 -- RDSTLS +PROTOCOL_HYBRID_EX = 8 -- CredSSP (NLA) with Early User Auth PDU + +Packet = { + + TPKT = { + + new = function(self, data) + local o = { data = tostring(data), version = 3 } + setmetatable(o, self) + self.__index = self + return o + end, + + __tostring = function(self) + return string.pack(">BBI2", + self.version, + self.reserved or 0, + (self.data and #self.data + 4 or 4)) + ..self.data + end, + + parse = function(data) + local tpkt = Packet.TPKT:new() + local pos + + tpkt.version, tpkt.reserved, tpkt.length, pos = string.unpack(">BBI2", data) + tpkt.data = data:sub(pos) + return tpkt + end + }, + + ITUT = { + + new = function(self, code, data) + local o = { data = tostring(data), code = code } + setmetatable(o, self) + self.__index = self + return o + end, + + parse = function(data) + local itut = Packet.ITUT:new() + local pos + + itut.length, itut.code, pos = string.unpack("BB", data) + + if ( itut.code == 0xF0 ) then + -- X.224 - Data TPDU (DT) + itut.eot, pos = string.unpack("B", data, pos) + elseif ( itut.code == 0xD0 ) then + -- X.224 - Connection Confirm (CC) + itut.dstref, itut.srcref, itut.class, pos = string.unpack(">I2I2B", data, pos) + end + + itut.data = data:sub(pos) + return itut + end, + + __tostring = function(self) + local len, eot + if self.code == 0xF0 then + eot = "\x80" + len = 2 + else + eot = "" + len = #self.data + 1 + end + local data = string.pack("BB", + len, + self.code or 0) + .. eot + .. self.data + + return data + end, + + }, + + ConfCreateResponse = { + + + new = function(self) + local o = {} + setmetatable(o, self) + self.__index = self + return o + end, + + parse = function(data) + + local tag_decoder = {} + + tag_decoder["\x0A"] = function( self, encStr, elen, pos ) + return self.decodeInt(encStr, elen, pos) + end + + local ccr = Packet.ConfCreateResponse:new() + + local decoder = asn1.ASN1Decoder:new() + decoder:registerTagDecoders( tag_decoder ) + + local _, pos = decoder.decodeLength(data, 3) + local response_result, userdata + response_result, pos = decoder:decode(data, pos) + ccr.result = CONNECT_RESPONSE_RESULT[response_result] + + ccr.calledConnectId, pos = decoder:decode(data, pos) + + -- T.125 DomainParameters SEQUENCE + -- Not interested in its values now, just need to correctly parse + -- the block so we can arrive at userData + _, pos = decoder:decode(data, pos) + + -- T.125 userData OCTO string + userdata, _ = decoder:decode(data, pos) + + if userdata == nil then + return ccr + end + + -- Hackery to avoid writing ASN.1 PER decoding. Skip over fixed length + -- T.124 ConnectData header. Decode the length since it can be multiple + -- bytes. Drops us where we need to be. + _, pos = asn1.ASN1Decoder.decodeLength(userdata, 22 ) + local block_type, block_len + while userdata:len() > pos do + block_type, block_len = string.unpack("I2I2B", + 0x0000, -- dst reference + 0x0000, -- src reference + 0x00) -- class and options + .. ("Cookie: %s\r\n"):format(cookie) + + if ( self.proto ) then + data = data .. string.pack("