Penetration Techniques - Obtaining Remote Desktop Connection History on Windows Systems

Onedaysec
5 min read
0 views
docx image 1770017269400 0 b27dece1db

0x00 Preface

---

In penetration testing, the history of Remote Desktop connections cannot be overlooked. Historical records often help locate critical servers.

A few days ago, an article explained how to clear these records. This article will introduce how to export the connection history.

The article on clearing records is available at:

http://woshub.com/how-to-clear-rdp-connections-history/#h2_3

The initial idea was to achieve this by enumerating the registry. However, further research revealed that to obtain the history of all users, it is necessary to acquire each user's NTUSER.DAT file, load the configuration unit via the registry, import the user configuration information, and then perform enumeration.

0x01 Introduction

---

This article will cover the following:

  • Approach to obtaining historical records
  • Exporting the history of the logged-in user
  • Exporting the history of all users
  • Implementation ideas and script writing details for both methods

0x02 Approach to Obtain Remote Desktop Connection History

---

1. Obtain the current user's history:

Enumerate registry key values at HKCU:\Software\Microsoft\Terminal Server Client\Servers

Each registry entry stores the connected server address, with the key value UsernameHint corresponding to the login username

As shown in the figure below

1. Obtain the current user's history: — technical illustration 1

2. Obtain the history of logged-in users:

The registry information of logged-in users is synchronized under HKEY_USERS\SID, where SID corresponds to each user's SID

Currently, two users are logged into the system, each with two subkeys, as shown in the figure below

2. Obtain the history of logged-in users: — technical illustration 2

Note:

HKEY_USERS only contains default user settings and information of logged-in users; user settings are unavailable when the user is not logged in

That is, if two users are currently logged in, the registry information of both users will be stored under HKEY_USERS\SID. If a third user is not logged in, their registry information cannot be directly obtained, and thus the remote desktop connection history of that user cannot be exported

Therefore, by enumerating the registry key values at HKEY_USERS\SID\Software\Microsoft\Terminal Server Client\Servers, the remote desktop connection history of logged-in users can be obtained

3. Obtain all users' historical records:

For users who are not logged in, registry configuration information cannot be directly obtained. This can be resolved by loading a configuration unit.

Select the HKEY_USERS item, go to File -> Load Hive, as shown in the figure below.

3. Obtain all users' historical records: — technical illustration 3

Open the user's NTUSER.DAT file, located at C:\Documents and Settings\Username\NTUSER.DAT.

Then specify a key name to read the user's registry configuration information under HKEY_USERS, as shown in the figure below.

3. Obtain all users' historical records: — technical illustration 4

Note:

To delete this item, it must be cleared by unloading the configuration unit.

Therefore, to obtain all users' remote desktop connection history, first enumerate the registry key HKEY_USERS\SID\. For users not logged in, load the corresponding NTUSER.DAT file, enumerate again to obtain complete records, and finally unload the corresponding registry key.

Supplement:

Example of loading a configuration unit via command line:

Reg load HKEY_USERS\S-1-5-21-1170783345-3748964848-1387080272-1003 C:\Documents and Settings\c\NTUSER.DAT

Example of unloading a configuration unit via command line:

Reg unload HKEY_USERS\S-1-5-21-1170783345-3748964848-1387080272-1003

0x03 PowerShell Implementation Details

---

1. Obtain the current user's history

Location: HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers

Enumerate subkeys under the specified registry key:

dir "Registry::HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers" -Name

Query registry key values for the specified registry key:

(Get-ItemProperty -Path "Registry::HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers\192.168.62.137").UsernameHint

Implement enumeration using a foreach loop:

$RegPath = "Registry::HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers\"
$QueryPath = dir $RegPath -Name
foreach($Name in $QueryPath)
{
(Get-ItemProperty -Path $RegPath$Name).UsernameHint
}

Add exception handling, do not output error messages; if the registry key value cannot be found, return 'Unable to obtain'

Complete script:

$RegPath = "Registry::HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers\"
$QueryPath = dir $RegPath -Name
foreach($Name in $QueryPath)
{
Try
{
$User = (Get-ItemProperty -Path $RegPath$Name -ErrorAction Stop ).UsernameHint
Write-Host "Server:"$Name
Write-Host "User:"$User"`n"
}
Catch
{
Write-Host "No RDP Connections History"
}
}

2. Obtain the history of logged-in users

Location: HKEY_USERS\SID\Software\Microsoft\Terminal Server Client\Servers

Note:

SID corresponds to the SID of each user

First, enumerate all user SIDs

PowerShell:

Get-WmiObject -Class Win32_UserAccount

WMI:

wmic /NAMESPACE:"\\root\CIMV2" PATH Win32_UserAccount GET /all /FORMAT:list

Enumerate usernames and their corresponding SIDs:

$AllUser = Get-WmiObject -Class Win32_UserAccount

foreach($User in $AllUser)
{
Write-Host $User.Name":"$User.SID
}

Combine the above scripts: first enumerate user SIDs, query corresponding registry entries under HKEY_USERS, then enumerate registry key values to obtain complete results:

(Administrator privileges required)

$AllUser = Get-WmiObject -Class Win32_UserAccount
foreach($User in $AllUser)
{
$RegPath = "Registry::HKEY_USERS\"+$User.SID+"\Software\Microsoft\Terminal Server Client\Servers\"
Write-Host "User:"$User.Name
Write-Host "SID:"$User.SID
Write-Host "Status:"$User.Status
Try
{
$QueryPath = dir $RegPath -Name -ErrorAction Stop
}
Catch
{
Write-Host "No RDP Connections History"
Write-Host "----------------------------------"
continue
}
foreach($Name in $QueryPath)
{
Try
{
$User = (Get-ItemProperty -Path $RegPath$Name -ErrorAction Stop).UsernameHint
Write-Host "Server:"$Name
Write-Host "User:"$User
}
Catch
{
Write-Host "No RDP Connections History"
}
}
Write-Host "----------------------------------"
}

Note:

$User.Status indicates the account status, which cannot be directly queried via Get-WmiObject -Class Win32_UserAccount; it can be obtained using the wmi command:

wmic /NAMESPACE:"\\root\CIMV2" PATH Win32_UserAccount GET /all /FORMAT:list

3、Obtain history records for all users

File location for loading the hive:

"C:\Documents and Settings\Username\NTUSER.DAT"

Implementation approach:

  1. Obtain the SID corresponding to each user, concatenate the corresponding registry key value "Registry::HKEY_USERS\"+$User.SID+"\Software\Microsoft\Terminal Server Client\Servers\"
  2. If reading fails, it indicates that this user has not logged in; then attempt to load the hive
  3. Concatenate hive file location "C:\Documents and Settings\"+$User.Name+"\NTUSER.DAT"
  4. The registry key corresponding to the hive is named after the user's SID
  5. Enumerate the registry to obtain history records
  6. Unload registry key

Note:

A new process needs to be started to unload the hive, otherwise it will prompt failure

To avoid using multiple try-catch blocks to catch exceptions, the code structure has been changed to use If-Else for judgment. The complete implementation code can be referenced from:

An open-source project

Test results are shown in the figure below

Implementation approach: — technical illustration 5

0x04 Summary

---

This article introduces how to obtain the Remote Desktop connection history of a Windows system via PowerShell. It should be noted that registry configuration information for users who are not logged in cannot be obtained directly (this can be resolved by loading the hive). Based on the Remote Desktop connection history, critical servers can often be identified.

Related Questions & Answers

How can a penetration tester enumerate RDP connection history for users currently logged into the system using PowerShell?

First, retrieve all user SIDs with `Get-WmiObject -Class Win32_UserAccount`. Then for each SID, query the registry path `Registry::HKEY_USERS\SID\Software\Microsoft\Terminal Server Client\Servers`. Use a `foreach` loop with a try-catch block to handle missing keys. The PowerShell script in the article demonstrates this and also displays the account status. This method only works for users who have an active session, similar to accessing [multi-user login](/news/penetration-techniques-multi-user-login-for-windows-remote-desktop) scenarios where multiple users are logged in simultaneously.

Which registry path stores the Remote Desktop connection history, and what information does each key contain?

The Remote Desktop connection history is stored under `Software\Microsoft\Terminal Server Client\Servers` within each user's registry hive. For the current user, the full path is `HKCU:\Software\Microsoft\Terminal Server Client\Servers`. Each subkey is named after the target server's IP address or hostname, and it contains a value called `UsernameHint` that holds the username used for that connection. The [article](/news/penetration-techniques-obtaining-remote-desktop-connection-history-on-windows-systems) shows how to enumerate these keys for both logged-in and all users.

Why can't I directly read the RDP connection history for users who are not logged into the Windows system?

The registry information for a user is only loaded into `HKEY_USERS` when that user logs on. For users who are not currently logged in, their settings reside in their `NTUSER.DAT` file on disk and are not synced to the registry. To access that data, you must manually load the hive file as described in the article. This is a common challenge in forensic and penetration testing contexts, much like retrieving [PowerShell command history](/news/penetration-techniques-obtaining-powershell-command-history) which also requires accessing user-specific artifacts.

What is the best method to obtain RDP connection history for all users, including those not currently logged into the system?

To get the full history, you must first enumerate all user SIDs via WMI, then attempt to read each user's registry path under `HKEY_USERS\SID\...`. If a user is not logged in, their registry hive is unavailable, so you need to load their `NTUSER.DAT` file (located in `C:\Documents and Settings\Username\`) as a registry hive using `Reg load`. After loading, enumerate the keys, then unload the hive. The article details a complete PowerShell implementation that uses a loop and try-catch or if-else logic. This technique is similar to [account hiding](/news/penetration-techniques-account-hiding-in-windows-systems) in that it manipulates registry hives for deeper access.

How can I retrieve the Remote Desktop connection history of only the currently logged-in user during a penetration test?

You can enumerate the registry key `HKCU:\Software\Microsoft\Terminal Server Client\Servers` using a simple PowerShell loop. Each subkey represents a server, and the `UsernameHint` value stores the login username. A complete script is provided in the [article](/news/penetration-techniques-obtaining-remote-desktop-connection-history-on-windows-systems) that handles exceptions and outputs the server and user. This method requires no special privileges since it only reads the current user's hive.

Continue Reading