Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /usr/share/nmap/nselib/ |
Upload File : |
--- -- A minimal RDP (Remote Desktop Protocol) library. Currently has functionality to determine encryption -- and cipher support. -- -- -- @author Patrik Karlsson <patrik@cqure.net> -- @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("<I2I2", userdata, pos) if block_type == 0x0c01 then -- 2.2.1.42 Server Core Data - TS_UD_SC_CORE local proto_ver = string.unpack("<I4",userdata, pos + 4) ccr.proto_version = ("RDP Protocol Version: %s"):format(PROTO_VERSION[proto_ver] or "Unknown") elseif block_type == 0x0c02 then -- 2.2.1.4.3 Server Security Data - TS_UD_SC_SEC1 ccr.enc_level = string.unpack("B", userdata, pos + 8) ccr.enc_cipher= string.unpack("B", userdata, pos + 4) end pos = pos + block_len end return ccr end, }, } Request = { ConnectionRequest = { new = function(self, proto) local o = { proto = proto } setmetatable(o, self) self.__index = self return o end, __tostring = function(self) local cookie = "mstshash=nmap" local data = string.pack(">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("<BBI2I4", 0x01, -- TYPE_RDP_NEG_REQ 0x00, -- flags 0x0008, -- length self.proto -- protocol ) end return tostring(Packet.TPKT:new(Packet.ITUT:new(0xE0, data))) end }, MCSConnectInitial = { new = function(self, cipher, server_proto) local o = { cipher = cipher, server_proto = server_proto } setmetatable(o, self) self.__index = self return o end, __tostring = function(self) local data = stdnse.fromhex( "7f 65" .. -- BER: Application-Defined Type = APPLICATION 101, "82 01 94" .. -- BER: Type Length = 404 bytes "04 01 01" .. -- Connect-Initial::callingDomainSelector "04 01 01" .. -- Connect-Initial::calledDomainSelector "01 01 ff" .. -- Connect-Initial::upwardFlag = TRUE "30 19" .. -- Connect-Initial::targetParameters (25 bytes) "02 01 22" .. -- DomainParameters::maxChannelIds = 34 "02 01 02" .. -- DomainParameters::maxUserIds = 2 "02 01 00" .. -- DomainParameters::maxTokenIds = 0 "02 01 01" .. -- DomainParameters::numPriorities = 1 "02 01 00" .. -- DomainParameters::minThroughput = 0 "02 01 01" .. -- DomainParameters::maxHeight = 1 "02 02 ff ff" .. -- DomainParameters::maxMCSPDUsize = 65535 "02 01 02" .. -- DomainParameters::protocolVersion = 2 "30 19" .. -- Connect-Initial::minimumParameters (25 bytes) "02 01 01" .. -- DomainParameters::maxChannelIds = 1 "02 01 01" .. -- DomainParameters::maxUserIds = 1 "02 01 01" .. -- DomainParameters::maxTokenIds = 1 "02 01 01" .. -- DomainParameters::numPriorities = 1 "02 01 00" .. -- DomainParameters::minThroughput = 0 "02 01 01" .. -- DomainParameters::maxHeight = 1 "02 02 04 20" .. -- DomainParameters::maxMCSPDUsize = 1056 "02 01 02" .. -- DomainParameters::protocolVersion = 2 "30 1c" .. -- Connect-Initial::maximumParameters (28 bytes) "02 02 ff ff" .. -- DomainParameters::maxChannelIds = 65535 "02 02 fc 17" .. -- DomainParameters::maxUserIds = 64535 "02 02 ff ff" .. -- DomainParameters::maxTokenIds = 65535 "02 01 01" .. -- DomainParameters::numPriorities = 1 "02 01 00" .. -- DomainParameters::minThroughput = 0 "02 01 01" .. -- DomainParameters::maxHeight = 1 "02 02 ff ff" .. -- DomainParameters::maxMCSPDUsize = 65535 "02 01 02" .. -- DomainParameters::protocolVersion = 2 "04 82 01 33" .. -- Connect-Initial::userData (307 bytes) "00 05" .. -- object length = 5 bytes "00 14 7c 00 01" .. -- object "81 2a" .. -- ConnectData::connectPDU length = 42 bytes "00 08 00 10 00 01 c0 00 44 75 63 61 81 1c" .. -- PER encoded (ALIGNED variant of BASIC-PER) GCC Conference Create Request PDU "01 c0 d8 00" .. -- TS_UD_HEADER::type = CS_CORE (0xc001), length = 216 bytes "04 00 08 00" .. -- TS_UD_CS_CORE::version = 0x0008004 "00 05" .. -- TS_UD_CS_CORE::desktopWidth = 1280 "20 03" .. -- TS_UD_CS_CORE::desktopHeight = 1024 "01 ca" .. -- TS_UD_CS_CORE::colorDepth = RNS_UD_COLOR_8BPP (0xca01) "03 aa" .. -- TS_UD_CS_CORE::SASSequence "09 04 00 00" .. -- TS_UD_CS_CORE::keyboardLayout = 0x409 = 1033 = English (US) "28 0a 00 00" .. -- TS_UD_CS_CORE::clientBuild = 2600 "45 00 4d 00 50 00 2d 00 4c 00 41 00 50 00 2d 00 " .. "30 00 30 00 31 00 34 00 00 00 00 00 00 00 00 00 " .. -- TS_UD_CS_CORE::clientName = EMP-LAP-0014 "04 00 00 00" .. -- TS_UD_CS_CORE::keyboardType "00 00 00 00" .. -- TS_UD_CS_CORE::keyboardSubtype "0c 00 00 00" .. -- TS_UD_CS_CORE::keyboardFunctionKey "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " .. "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " .. "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " .. "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " .. -- TS_UD_CS_CORE::imeFileName = "" "01 ca" .. -- TS_UD_CS_CORE::postBeta2ColorDepth = RNS_UD_COLOR_8BPP (0xca01) "01 00" .. -- TS_UD_CS_CORE::clientProductId "00 00 00 00" .. -- TS_UD_CS_CORE::serialNumber "18 00" .. -- TS_UD_CS_CORE::highColorDepth = 24 bpp "07 00" .. -- TS_UD_CS_CORE::supportedColorDepths = 24 bpp "01 00" .. -- TS_UD_CS_CORE::earlyCapabilityFlags "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " .. "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " .. "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " .. "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " .. -- TS_UD_CS_CORE::clientDigProductId "00" .. -- TS_UD_CS_CORE::connectionType = 0 (not used as RNS_UD_CS_VALID_CONNECTION_TYPE not set) "00") -- TS_UD_CS_CORE::pad1octet -- TS_UD_CS_CORE::serverSelectedProtocol .. string.pack("<I4", self.server_proto or 0) .. stdnse.fromhex( "04 c0 0c 00" .. -- TS_UD_HEADER::type = CS_CLUSTER (0xc004), length = 12 bytes "09 00 00 00" .. -- TS_UD_CS_CLUSTER::Flags = 0x0d "00 00 00 00" .. -- TS_UD_CS_CLUSTER::RedirectedSessionID "02 c0 0c 00") -- TS_UD_HEADER::type = CS_SECURITY (0xc002), length = 12 bytes -- "1b 00 00 00" .. -- TS_UD_CS_SEC::encryptionMethods .. string.pack("<I4", self.cipher or 0) .. stdnse.fromhex( "00 00 00 00" .. -- TS_UD_CS_SEC::extEncryptionMethods "03 c0 2c 00" .. -- TS_UD_HEADER::type = CS_NET (0xc003), length = 44 bytes "03 00 00 00" .. -- TS_UD_CS_NET::channelCount = 3 "72 64 70 64 72 00 00 00" .. -- CHANNEL_DEF::name = "rdpdr" "00 00 80 80" .. -- CHANNEL_DEF::options = 0x80800000 "63 6c 69 70 72 64 72 00" .. -- CHANNEL_DEF::name = "cliprdr" "00 00 a0 c0" .. -- CHANNEL_DEF::options = 0xc0a00000 "72 64 70 73 6e 64 00 00" .. -- CHANNEL_DEF::name = "rdpsnd" "00 00 00 c0" -- CHANNEL_DEF::options = 0xc0000000 ) return tostring(Packet.TPKT:new(Packet.ITUT:new(0xF0, data))) end }, } Response = { ConnectionConfirm = { new = function(self) local o = { } setmetatable(o, self) self.__index = self return o end, parse = function(data) local cc = Response.ConnectionConfirm:new() cc.tpkt = Packet.TPKT.parse(data) cc.itut = Packet.ITUT.parse(cc.tpkt.data) return cc end, }, MCSConnectResponse = { new = function(self) local o = { } setmetatable(o, self) self.__index = self return o end, parse = function(data) local cr = Response.MCSConnectResponse:new() cr.tpkt = Packet.TPKT.parse(data) cr.itut = Packet.ITUT.parse(cr.tpkt.data) if ( cr.itut.code == 0xF0 ) then -- X.224 - Data TPDU (DT) cr.ccr = Packet.ConfCreateResponse.parse(cr.itut.data) end return cr end } } Comm = { -- Creates a new Comm instance -- @param host table -- @param port table -- @return o instance of Comm new = function(self, host, port) local o = { host = host, port = port } setmetatable(o, self) self.__index = self return o end, -- Connect to the server -- @return status true on success, false on failure -- @return err string containing error message, if status is false connect = function(self) self.socket = nmap.new_socket() self.socket:set_timeout(5000) if ( not(self.socket:connect(self.host, self.port)) ) then return false, "Failed connecting to server" end return true end, -- Close the connection to the server -- @return status true on success, false on failure close = function(self) return self.socket:close() end, -- Sends a message to the server -- @param pkt an instance of Request.* -- @return status true on success, false on failure -- @return err string containing error message, if status is false send = function(self, pkt) return self.socket:send(tostring(pkt)) end, -- Receives a message from the server -- @return status true on success, false on failure -- @return err string containing error message, if status is false recv = function(self) return self.socket:receive() end, -- Sends a message to the server and receives the response -- @param pkt an instance of Request.* -- @return status true on success, false on failure -- @return err string containing error message, if status is false -- pkt instance of Response.* on success exch = function(self, pkt) local status, err = self:send(pkt) if ( not(status) ) then return false, err end local _, data = self:recv() if ( #data< 5 ) then return false, "Packet too short" end local itut_code = string.byte(data, 6) if ( itut_code == 0xD0 ) then stdnse.debug2("RDP: Received ConnectionConfirm response") return true, Response.ConnectionConfirm.parse(data) elseif ( itut_code == 0xF0 ) then return true, Response.MCSConnectResponse.parse(data) elseif itut_code ~= nil then stdnse.debug1(("comm:exch - Unknown itut_code: %s"):format(itut_code)) end return false, "Received unhandled packet" end, } return _ENV;