CVE-2019-1453
An exploitable denial-of-service vulnerability exists in the RDP8 implementation of Microsoft’s Remote Desktop Services. A certain component of license negotiation can allow a remote client to read an amount of memory that is controlled by the client. Due to this, a client can coerce the component to read from memory that is unmapped, resulting in a denial-of-service condition. An attacker can negotiate capabilities and then send a particular packet type in order to trigger this vulnerability.
Microsoft’s Remote Desktop Services – Windows 7: RdpCoreTS.dll 6.2.9200.22828
https://docs.microsoft.com/en-us/windows/win32/termserv/terminal-services-portal
7.5 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CWE-126: Buffer Over-read
Remote Desktop Services allow a user or administrator to take control of a remote computer over a network connection. This allows the user to utilize a familiar graphical user interface to interact with said remote machine which provides a thin-client architecture on the Windows platform. These capabilities are accomplished using the Remote Desktop Protocol which is built on top of the X.224, T.124, T.125, T.128 protocols. Remote Desktop Services is a common service within the enterprise and is commonly used as a work-around on a network with otherwise minimalistic remote administration capabilities.
When a client initializes a connection via the RDP protocol, the client must first go through a number of stages in order to setup each of the individual layers that are used by the RDS platform. During setup of the T.125 layer, a client may announce a number of channels by name that the server is expected to connect to an endpoint. After establishing this and performing the rest of the required negotiations, the client will then perform a security exchange which is required to complete the initialization of the T.128 protocol which will provide the Multipoint Application Sharing component as mentioned in the T.128 specification. After performing this security exchange, the client will then need to negotiate capabilities with the remote server. This is done by first receiving a packet from the server containing the supported capabilities, followed by a response from the client with the capabilities that it will use. After this has been accomplished, the server will then connect the channel names requested by the client to their endpoints and then perform the license exchange. Due to the server using the same channel protocol for things such as the license exchange, and a number of other capabilities, a remote client can establish a connection to these internal channels and interact with the logic of their endpoint. One of the packet types parsed by its endpoint allows a user to specify a length that will be used to make an allocation, and use it as a length when copying data from the packet into the buffer. Due to the client controlling the length, this can enable the client to specify a length that is larger than the packet resulting in potentially reading an unmapped memory resulting in a denial of service condition.
When establishing a connection, the server will instantiate a CUMRDPConnection
object. This object appears to be an abbreviation of “User-mode RDP Connection”. Once this object has been constructed to manage the connection from the client, the CUMRDPConnection::CreateVirtualChannel
method will be called for each channel. This method will eventually check its parameter using stricmp()
to see if the channel name that was passed to it is one of the strings listed. At [1], if the channel name is “rdplic” the application will go down a branch where a failure should be returned. Nonetheless, this list contains a number of channel endpoints that the remote client is able to communicate with by writing to the channel via the T.125 protocol. It is assumed by the author that these endpoints are not intended to be reachable by a remote client as the implementation in RdpCoreTS.dll
seems to write undocumented structures to these different channel endpoints.
rdpcorets!CUMRDPConnection::CreateVirtualChannel:
000007fe`f9ae191c 48895c2410 mov qword ptr [rsp+10h],rbx
000007fe`f9ae1921 4489442418 mov dword ptr [rsp+18h],r8d
000007fe`f9ae1926 55 push rbp
000007fe`f9ae1927 56 push rsi
000007fe`f9ae1928 57 push rdi
000007fe`f9ae1929 4154 push r12
000007fe`f9ae192b 4155 push r13
000007fe`f9ae192d 4156 push r14
000007fe`f9ae192f 4157 push r15
000007fe`f9ae1931 4883ec40 sub rsp,40h
...
rdpcorets!CUMRDPConnection::CreateVirtualChannel+0x212:
000007fe`f9ae1b2e 488d0d932df7ff lea rcx,[rdpcorets!`string' (000007fe`f9a548c8)] ; "DRDYNVC"
000007fe`f9ae1b35 498bd7 mov rdx,r15
000007fe`f9ae1b38 ff15ca822700 call qword ptr [rdpcorets!_imp__stricmp (000007fe`f9d59e08)]
000007fe`f9ae1b3e 85c0 test eax,eax
000007fe`f9ae1b40 0f840c010000 je rdpcorets!CUMRDPConnection::CreateVirtualChannel+0x336 (000007fe`f9ae1c52)
...
000007fe`f9ae1b46 488d0d832df7ff lea rcx,[rdpcorets!`string' (000007fe`f9a548d0)] ; "rdpgrfx"
000007fe`f9ae1b4d 498bd7 mov rdx,r15
000007fe`f9ae1b50 ff15b2822700 call qword ptr [rdpcorets!_imp__stricmp (000007fe`f9d59e08)]
000007fe`f9ae1b56 85c0 test eax,eax
000007fe`f9ae1b58 0f84f4000000 je rdpcorets!CUMRDPConnection::CreateVirtualChannel+0x336 (000007fe`f9ae1c52)
...
000007fe`f9ae1b5e 488d0d732df7ff lea rcx,[rdpcorets!`string' (000007fe`f9a548d8)] ; "rdpinpt"
000007fe`f9ae1b65 498bd7 mov rdx,r15
000007fe`f9ae1b68 ff159a822700 call qword ptr [rdpcorets!_imp__stricmp (000007fe`f9d59e08)]
000007fe`f9ae1b6e 85c0 test eax,eax
000007fe`f9ae1b70 0f84dc000000 je rdpcorets!CUMRDPConnection::CreateVirtualChannel+0x336 (000007fe`f9ae1c52)
...
000007fe`f9ae1b76 488d0d632df7ff lea rcx,[rdpcorets!`string' (000007fe`f9a548e0)] ; "rdpcmd"
000007fe`f9ae1b7d 498bd7 mov rdx,r15
000007fe`f9ae1b80 ff1582822700 call qword ptr [rdpcorets!_imp__stricmp (000007fe`f9d59e08)]
000007fe`f9ae1b86 85c0 test eax,eax
000007fe`f9ae1b88 0f84c4000000 je rdpcorets!CUMRDPConnection::CreateVirtualChannel+0x336 (000007fe`f9ae1c52)
...
000007fe`f9ae1b8e 488d0d532df7ff lea rcx,[rdpcorets!`string' (000007fe`f9a548e8)] ; [1] "rdplic"
000007fe`f9ae1b95 498bd7 mov rdx,r15
000007fe`f9ae1b98 ff156a822700 call qword ptr [rdpcorets!_imp__stricmp (000007fe`f9d59e08)]
000007fe`f9ae1b9e 85c0 test eax,eax
000007fe`f9ae1ba0 0f84ac000000 je rdpcorets!CUMRDPConnection::CreateVirtualChannel+0x336 (000007fe`f9ae1c52)
...
000007fe`f9ae1ba6 488d0d432df7ff lea rcx,[rdpcorets!`string' (000007fe`f9a548f0)] ; "Microsoft::Windows::RDS::Graphics"
000007fe`f9ae1bad 498bd7 mov rdx,r15
000007fe`f9ae1bb0 ff1552822700 call qword ptr [rdpcorets!_imp__stricmp (000007fe`f9d59e08)]
000007fe`f9ae1bb6 85c0 test eax,eax
000007fe`f9ae1bb8 0f8494000000 je rdpcorets!CUMRDPConnection::CreateVirtualChannel+0x336 (000007fe`f9ae1c52)
...
000007fe`f9ae1bbe 488d0d4f2df7ff lea rcx,[rdpcorets!`string' (000007fe`f9a54914)] ; "RDPSND"
000007fe`f9ae1bc5 498bd7 mov rdx,r15
000007fe`f9ae1bc8 ff153a822700 call qword ptr [rdpcorets!_imp__stricmp (000007fe`f9d59e08)]
000007fe`f9ae1bce 85c0 test eax,eax
000007fe`f9ae1bd0 7504 jne rdpcorets!CUMRDPConnection::CreateVirtualChannel+0x2ba (000007fe`f9ae1bd6)
When creating the endpoint for the “rdplic” channel, the service will first call the CUMRDPLicPluginFactory_CreateInstance
function. This object is responsible for creating instances of the CUMRDPLicPlugin
object as needed. This is done with the IRDPCOREChannelPluginFactory
interface. One of the methods within this interface is the CUMRDPLicPluginFactory::CreateConnectionChannel
method and is shown in the following disassembly. When creating an instance for the channel, this method will create a COM interface by calling the __RDPAPIDLL__CreateInstance
function with the CLSID and IID (Interface ID) specified at [2]. Once finally calling __RDPAPIDLL__CreateInstance
at [3], the CUMRDPLicPlugin_CreateInstance
function will then be called. This is the function that’s actually responsible for creating an instance of a CUMRDLicPlugin
. First at [4], the function will allocate 0xd8 bytes for the object. Afterwards, the object’s virtual method tables will be populated by the function. One of the method tables at [5], IRDPCoreVirtualChannelEvents
, is responsible for actually receiving events as a channel endpoint and is implemented by a number of other objects for the channel names that were prior mentioned.
rdpcorets!CUMRDPLicPluginFactory::CreateConnectionChannels:
000007fe`f9ae8930 4055 push rbp
000007fe`f9ae8932 53 push rbx
000007fe`f9ae8933 56 push rsi
000007fe`f9ae8934 57 push rdi
000007fe`f9ae8935 4156 push r14
000007fe`f9ae8937 488bec mov rbp,rsp
000007fe`f9ae893a 4883ec40 sub rsp,40h
...
rdpcorets!CUMRDPLicPluginFactory::CreateConnectionChannels+0x197:
000007fe`f9ae8ac7 488b4e40 mov rcx,qword ptr [rsi+40h]
000007fe`f9ae8acb 4c8d4d30 lea r9,[rbp+30h]
000007fe`f9ae8acf 4c8d0592b1f6ff lea r8,[rdpcorets!IID_IUMTSLicensePlugin (000007fe`f9a53c68)] ; [2] IID_IUMTSLicensePlugin
000007fe`f9ae8ad6 488d158b98f6ff lea rdx,[rdpcorets!CLSID_UMRDPLICPlugin (000007fe`f9a52368)] ; [2] CLSID_UMRDPLICPlugin
000007fe`f9ae8add e8e2c80000 call rdpcorets!__RDPAPIDLL__CreateInstance (000007fe`f9af53c4) ; [3] \\
000007fe`f9ae8ae2 8bd8 mov ebx,eax
000007fe`f9ae8ae4 85c0 test eax,eax
000007fe`f9ae8ae6 7944 jns rdpcorets!CUMRDPLicPluginFactory::CreateConnectionChannels+0x1fc (000007fe`f9ae8b2c)
\\
rdpcorets!CUMRDPLicPlugin_CreateInstance:
000007fe`f9ae8ed8 488bc4 mov rax,rsp
000007fe`f9ae8edb 48895808 mov qword ptr [rax+8],rbx
000007fe`f9ae8edf 48896810 mov qword ptr [rax+10h],rbp
000007fe`f9ae8ee3 48897018 mov qword ptr [rax+18h],rsi
000007fe`f9ae8ee7 48897820 mov qword ptr [rax+20h],rdi
000007fe`f9ae8eeb 4156 push r14
000007fe`f9ae8eed 4883ec30 sub rsp,30h
...
000007fe`f9ae8ef1 488bf9 mov rdi,rcx
000007fe`f9ae8ef4 b9d8000000 mov ecx,0D8h
000007fe`f9ae8ef9 498bf0 mov rsi,r8
000007fe`f9ae8efc 488bea mov rbp,rdx
000007fe`f9ae8eff ff158b0f2700 call qword ptr [rdpcorets!_imp_??2YAPEAX_KZ (000007fe`f9d59e90)] ; [4] allocate 0xd8 bytes
000007fe`f9ae8f05 4533f6 xor r14d,r14d
000007fe`f9ae8f08 488bd8 mov rbx,rax
000007fe`f9ae8f0b 4885c0 test rax,rax
000007fe`f9ae8f0e 0f84b4000000 je rdpcorets!CUMRDPLicPlugin_CreateInstance+0xf0 (000007fe`f9ae8fc8)
...
000007fe`f9ae8f14 c74030cdabcadb mov dword ptr [rax+30h],0DBCAABCDh
000007fe`f9ae8f1b c7403401000000 mov dword ptr [rax+34h],1
000007fe`f9ae8f22 4883c020 add rax,20h
000007fe`f9ae8f26 48894018 mov qword ptr [rax+18h],rax
000007fe`f9ae8f2a 488d0d3740fcff lea rcx,[rdpcorets!CCaRdpGfxEncoderRaw::`vftable' (000007fe`f9aacf68)] ; Default INonDelegatingUnknown
000007fe`f9ae8f31 458d4640 lea r8d,[r14+40h]
000007fe`f9ae8f35 488908 mov qword ptr [rax],rcx
000007fe`f9ae8f38 488d0dc9aff6ff lea rcx,[rdpcorets!CTSUnknown::`vftable' (000007fe`f9a53f08)] ; Default CTSObject
000007fe`f9ae8f3f 33d2 xor edx,edx
000007fe`f9ae8f41 48894808 mov qword ptr [rax+8],rcx
000007fe`f9ae8f45 44897020 mov dword ptr [rax+20h],r14d
000007fe`f9ae8f49 488d0da0cbfbff lea rcx,[rdpcorets!CUMRDPLicPlugin::`vftable' (000007fe`f9aa5af0)] ; [5] Implementation of IRDPCoreVirtualChannelEvents
000007fe`f9ae8f50 48890b mov qword ptr [rbx],rcx
000007fe`f9ae8f53 488d0d66cbfbff lea rcx,[rdpcorets!CUMRDPLicPlugin::`vftable' (000007fe`f9aa5ac0)] ; Implementation of IRDPCOREChannelPlugin
000007fe`f9ae8f5a 48894b08 mov qword ptr [rbx+8],rcx
000007fe`f9ae8f5e 488d0d3bcbfbff lea rcx,[rdpcorets!CUMRDPLicPlugin::`vftable' (000007fe`f9aa5aa0)] ; Implementation of IUMTSLicensePlugin
000007fe`f9ae8f65 48894b10 mov qword ptr [rbx+10h],rcx
000007fe`f9ae8f69 488d0df8cafbff lea rcx,[rdpcorets!CUMRDPLicPlugin::`vftable' (000007fe`f9aa5a68)] ; Implementation of IWRdsProtocolLicenseConnection
000007fe`f9ae8f70 48894b18 mov qword ptr [rbx+18h],rcx
000007fe`f9ae8f74 488d0dd5cafbff lea rcx,[rdpcorets!CUMRDPLicPlugin::`vftable' (000007fe`f9aa5a50)] ; Implementation of INonDelegatingUnknown
000007fe`f9ae8f7b 488908 mov qword ptr [rax],rcx
000007fe`f9ae8f7e 488d05abcafbff lea rax,[rdpcorets!CUMRDPLicPlugin::`vftable' (000007fe`f9aa5a30)] ; Implementation of CTSObject
000007fe`f9ae8f85 488d8b88000000 lea rcx,[rbx+88h]
000007fe`f9ae8f8c 48894328 mov qword ptr [rbx+28h],rax
The implementation of the IRDPCoreVirtualChannelEvents
method table is as follows. When receiving data on the “rdplic” channel, the CUMRDPLicPlugin::OnDataReceived
method at [6] will be called with the channel data and its length as its parameters.
000007fe`f9aa5af0 000007fe`f9c1126c rdpcorets!CUMRDPLicPlugin::QueryInterface
000007fe`f9aa5af8 000007fe`f9ae84b0 rdpcorets!CRDPGfxPlugin::AddRef
000007fe`f9aa5b00 000007fe`f9ae84c4 rdpcorets!CUMTSCommandPlugin::Release
000007fe`f9aa5b08 000007fe`f9ae95f0 rdpcorets!CUMRDPLicPlugin::OnDataReceived ; [6]
000007fe`f9aa5b10 000007fe`f9ae9570 rdpcorets!CUMRDPLicPlugin::OnClose
000007fe`f9aa5b18 000007fe`f9ae9560 rdpcorets!CUMRDPLicPlugin::OnChannelOpened
000007fe`f9aa5b20 000007fe`f9ae95d0 rdpcorets!CUMRDPLicPlugin::OnDataSent
000007fe`f9aa5b28 000007fe`f9aea544 rdpcorets!CFakeGfxProvider::HandleSHMUpdate
000007fe`f9aa5b30 000007fe`f9ae924c rdpcorets!CUMRDPLicPlugin::Initialize
As was prior mentioned, data written to the “rdplic” channel will result in the server executing the following method to handle its endpoint. This method takes two parameters at [7] representing the channel data and its length. This data is taken directly from the client and is intended to be processed by this method. Once these values are loaded into the %r8
and %r15d
registers, the method will continue and then check the first 16-bits of the channel data at [8] to see if they’re one of 3 possible values. Depending on the value, one of the cases listed will be entered. At [9] when the first 16-bits are set to 0x1630, the handler for its case will be entered. This handler will simply hand-off the channel data and its length to the CUMRDPLicPlugin::HandleClientLicensePdu
method at [10]. As this method is called anytime data is written to the channel, these cases can be called repeatedly and at anytime the remote client chooses.
rdpcorets!CUMRDPLicPlugin::OnDataReceived:
000007fe`f9ae95f0 48895c2408 mov qword ptr [rsp+8],rbx
000007fe`f9ae95f5 48896c2410 mov qword ptr [rsp+10h],rbp
000007fe`f9ae95fa 4889742418 mov qword ptr [rsp+18h],rsi
000007fe`f9ae95ff 57 push rdi
000007fe`f9ae9600 4156 push r14
000007fe`f9ae9602 4157 push r15
000007fe`f9ae9604 4883ec20 sub rsp,20h
000007fe`f9ae9608 33f6 xor esi,esi
000007fe`f9ae960a 4d8bf0 mov r14,r8 ; [7] Channel Data
000007fe`f9ae960d 448bfa mov r15d,edx ; [7] Channel Data Length
000007fe`f9ae9610 488be9 mov rbp,rcx ; CUMRDPLicPlugin*
000007fe`f9ae9613 4d85c0 test r8,r8
000007fe`f9ae9616 7543 jne rdpcorets!CUMRDPLicPlugin::OnDataReceived+0x6b (000007fe`f9ae965b)
...
rdpcorets!CUMRDPLicPlugin::OnDataReceived+0x6b:
000007fe`f9ae965b b301 mov bl,1
000007fe`f9ae965d 488d3dbc0a2100 lea rdi,[rdpcorets!WPP_GLOBAL_Control (000007fe`f9cfa120)]
000007fe`f9ae9664 83fa04 cmp edx,4
000007fe`f9ae9667 732b jae rdpcorets!CUMRDPLicPlugin::OnDataReceived+0xa4 (000007fe`f9ae9694)
...
rdpcorets!CUMRDPLicPlugin::OnDataReceived+0xa4:
000007fe`f9ae9694 488b0d850a2100 mov rcx,qword ptr [rdpcorets!WPP_GLOBAL_Control (000007fe`f9cfa120)]
000007fe`f9ae969b 410fb706 movzx eax,word ptr [r14] ; [8] Read 16-bits from beginning of ChannelData packet
000007fe`f9ae969f 3d30130000 cmp eax,1330h
000007fe`f9ae96a4 0f8493000000 je rdpcorets!CUMRDPLicPlugin::OnDataReceived+0x14d (000007fe`f9ae973d)
...
000007fe`f9ae96aa 3d30160000 cmp eax,1630h ; [9] Check if 16-bits are 0x1630
000007fe`f9ae96af 747a je rdpcorets!CUMRDPLicPlugin::OnDataReceived+0x13b (000007fe`f9ae972b)
...
000007fe`f9ae96b1 3d30190000 cmp eax,1930h
000007fe`f9ae96b6 7425 je rdpcorets!CUMRDPLicPlugin::OnDataReceived+0xed (000007fe`f9ae96dd)
...
rdpcorets!CUMRDPLicPlugin::OnDataReceived+0x13b:
000007fe`f9ae972b 4d8bc6 mov r8,r14 ; [10] Channel Data
000007fe`f9ae972e 418bd7 mov edx,r15d ; Channel Data Length
000007fe`f9ae9731 488bcd mov rcx,rbp ; CUMRDPLicPlugin*
000007fe`f9ae9734 e8fb0a0000 call rdpcorets!CUMRDPLicPlugin::HandleClientLicensePdu (000007fe`f39ca234)
000007fe`f9ae9739 8bf0 mov esi,eax
000007fe`f9ae973b eb45 jmp rdpcorets!CUMRDPLicPlugin::OnDataReceived+0x192 (000007fe`f39c9782)
After the channel data and its length are passed to the CUMRDPLicPlugin::HandleClientLicensePdu
method, these values are then loaded into registers at [11] with the channel data being loaded from the %r8
register into %rbp
, and the channel data’s length left in %edx
. At [12], the channel data’s length will be checked to see if it’s larger than 9. If so, then the code at [13] will be executed. This will read 32-bits from the channel data at [13], and then use the 32-bits directly as a parameter to the allocation that follows (operator new
). As the remote client controls the length that is being used, this allows the client to make arbitrarily sized allocations. Once the allocation has been made at [14], the result will then be written into offset 0x78 of the CUMRDPLicPlugin
object. As a result of this property being overwritten, the previous value of the property is removed from the scope of the object before being properly released which can allow the remote client to repeatedly make controlled allocations to trigger memory exhaustion. Afterwards at [15], the channel data at offset +0x8 of the packet will be copied into the buffer that was allocated. As the client controls the length of this allocated buffer and the length used while copying channel data from the packet, a remote client can specify a length that is larger than the source packet data resulting in the memcpy()
function reading from unmapped memory while trying to copy data. This can result in a denial of service condition.
rdpcorets!CUMRDPLicPlugin::HandleClientLicensePdu:
000007fe`f9aea234 48895c2408 mov qword ptr [rsp+8],rbx
000007fe`f9aea239 48896c2410 mov qword ptr [rsp+10h],rbp
000007fe`f9aea23e 4889742418 mov qword ptr [rsp+18h],rsi
000007fe`f9aea243 57 push rdi
000007fe`f9aea244 4883ec30 sub rsp,30h
000007fe`f9aea248 33db xor ebx,ebx
000007fe`f9aea24a 498be8 mov rbp,r8 ; [11] Channel Data
000007fe`f9aea24d 488bf1 mov rsi,rcx ; CUMRDPLicPlugin*
000007fe`f9aea250 4d85c0 test r8,r8
000007fe`f9aea253 0f8426010000 je rdpcorets!CUMRDPLicPlugin::HandleClientLicensePdu+0x14b (000007fe`f9aea37f)
000007fe`f9aea259 83fa09 cmp edx,9 ; [12] Channel Length
000007fe`f9aea25c 0f821d010000 jb rdpcorets!CUMRDPLicPlugin::HandleClientLicensePdu+0x14b (000007fe`f9aea37f)
000007fe`f9aea262 488d3db7fe2000 lea rdi,[rdpcorets!WPP_GLOBAL_Control (000007fe`f9aea120)]
000007fe`f9aea269 41395804 cmp dword ptr [r8+4],ebx
000007fe`f9aea26d 7545 jne rdpcorets!CUMRDPLicPlugin::HandleClientLicensePdu+0x80 (000007fe`f9aea2b4)
...
rdpcorets!CUMRDPLicPlugin::HandleClientLicensePdu+0x80:
000007fe`f9aea2b4 418b4804 mov ecx,dword ptr [r8+4] ; [13] 32-bits from offset +0x4 of Channel Data
000007fe`f9aea2b8 ff15c2fb2600 call qword ptr [rdpcorets!_imp_??_UYAPEAX_KZ (000007fe`f9ae9e80)]
000007fe`f9aea2be 48894678 mov qword ptr [rsi+78h],rax ; [14] Overwrite value at offset +0x78 of Object
000007fe`f9aea2c2 4885c0 test rax,rax
000007fe`f9aea2c5 7555 jne rdpcorets!CUMRDPLicPlugin::HandleClientLicensePdu+0xe8 (000007fe`f9aea31c)
...
rdpcorets!CUMRDPLicPlugin::HandleClientLicensePdu+0xe8:
000007fe`f9aea31c 448b4504 mov r8d,dword ptr [rbp+4]
000007fe`f9aea320 488d5508 lea rdx,[rbp+8] ; [15] Copy data from packet into allocation
000007fe`f9aea324 488bc8 mov rcx,rax
000007fe`f9aea327 e8c4951f00 call rdpcorets!memcpy (000007fe`f9ce38f0)
The base addresses of the functions described in the details are as follows:
0:032> lm vm rdpcorets
Browse full module list
start end module name
000007fe`f9a50000 000007fe`f9d72000 rdpcorets (pdb symbols) c:\mss\RdpCoreTS.pdb\31C641C49232486FB999919FB0EBFC611\RdpCoreTS.pdb
Loaded symbol image file: rdpcorets.dll
Image path: C:\Windows\system32\rdpcorets.dll
Image name: rdpcorets.dll
Browse all global symbols functions data
Timestamp: Thu Jun 4 22:28:31 2015 (5571175F)
CheckSum: 003110B6
ImageSize: 00322000
File version: 6.2.9200.21506
Product version: 6.2.9200.21506
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 1.0 App
File date: 00000000.00000000
Translations: 0409.04b0
Information from resource tables:
CompanyName: Microsoft Corporation
ProductName: Microsoft® Windows® Operating System
InternalName: RdpCoreTS.dll
OriginalFilename: RdpCoreTS.dll
ProductVersion: 6.2.9200.21506
FileVersion: 6.2.9200.21506 (win8_ldr.150604-1607)
FileDescription: TS RDPCore DLL
LegalCopyright: © Microsoft Corporation. All rights reserved.
To run the provided proof-of-concept, Python2 and the six
module must be installed. To install the six
module, one can simply use pip
as follows:
$ pip install six
After installing the required modules, the proof-of-concept can then be run with the following command against RDS. To use the provided vulnerability to make a number of controlled allocations with the vulnerability, one may specify the size to use and the number of times to make it via the following parameters.
$ python poc.zip $host --size=$size --count=$count
In order to make the memcpy()
operation read from an unmapped page at the end of the channel data, a large length will be needed as long as it is small enough to satisfy the memory allocation. Something similar to the following may be used to trigger a crash with the vulnerability.
$ python poc.zip $host --size=0x100000 --count=0x10
For further help, the --help
parameter has also been implemented.
This denial-of-service vulnerability exist only on RDP8. RDP7, which is implemented in kernel-space, does not use the channels described within this document, and therefore is not vulnerable.
2019-09-19 - Vendor Disclosure
2019-10-29 - 30 day follow up
2019-10-29 - Vendor assigned CVE
2019-12-10 - Public Release
Discovered by a member of Cisco Talos.