Довольно часто администратору нужно быстро узнать имя пользователя, который выполнил вход на удаленном компьютере Windows. В это статье мы рассмотрим несколько утилит и PowerShell скриптов, которые помогут вам узнать имена пользователей, залогиненых на удаленных компьютерах в сети.
Утилиты PSLoggedOn и Qwinsta
В комплекте утилит SysInternals PSTools от Microsoft есть консольная утилита PSLoggedOn.exe, которую можно использовать для получения имени пользователя, который вошел на удаленный компьютер, а также список подключенных к нему SMB сеансов.
Скачайте утилиту и запустите ее в формате:
psloggedon \\RemoteCompName
Как вы видите, утилита вернула имя залогиненного пользователя (Users logged on locally), а также список пользователей, которые по сети используют ресурсы с этого компьютера (Users logged on via resource shares).
Если нужно получить только имя пользователя, вошедшего локально, используйте опцию –l:
Psloggedon.exe \\wks215s1 –l
Утилита Psloggedon подключается к реестру и проверяет в нем имя пользователя, вошедшего локально. Для этого должна быть включена служба RemoteRegistry. Вы можете запустить ее и настроить автозапуск службы с помощью PowerShell:
Set-Service RemoteRegistry –startuptype automatic –passthru
Start-Service RemoteRegistry
Также можно получить список сессий на удаленном компьютере с помощью встроенной утилиты
qwinsta
. Эта утилита должна быть знакома любому администратору, управляющему терминальными серверами с Remote Desktop Services. Чтобы получить список сессий с удаленного компьютера, выполнит команду:
qwinsta /server:dc01
Утилита возвращает список всех сессий (активных и отключенных по таймауту) на RDS сервере или десктопной редакции Windows 10 (даже если вы разрешили к ней множественные RDP подключения).
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v "AllowRemoteRPC" /t "REG_DWORD" /d "1" /f
Получаем имя пользователя на удаленном компьютере через PowerShell
Вы можете получить имя пользователя, который залогинен на компьютере через WMI класс Win32_ComputerSystem. Откройте консоль PowerShell и выполните команду:
Get-WmiObject -class Win32_ComputerSystem | Format-List Username
Команда вернула имя пользователя, который выполнил вход на компьютер.
У командлета Get-WmiObject есть параметр –ComputerName, который можно использовать для получения доступа к WMI объектам на удаленном компьютере. Следующая команда вернет имя пользователя с удаленного компьютера:
(Get-WmiObject -class Win32_ComputerSystem –ComputerName wks215s1).Username
Данная команда показывает только пользователя, вошедшего на консоль (не через RDP).
Если нужно получить только имя пользователя на компьютере (без домена), воспользуетесь следующими командами:
$userinfo = Get-WmiObject -ComputerName 'wks215s1' -Class Win32_ComputerSystem
$user = $userinfo.UserName -split '\\'
$user[1]
Get-CimInstance –ComputerName wks215s1 –ClassName Win32_ComputerSystem | Select-Object UserName
Или
(Get-CimInstance -ComputerName wks215s1 -ClassName Win32_ComputerSystem).CimInstanceProperties | where{$_.Name -like "UserName"}| select value
GetCiminstance использует WinRM для подключения к удаленным компьютерам, поэтому на них нужно включить и настроить WinRM через GPO или командой:
WinRM quickconfig
PowerShell скрипт для проверки пользователей на удаленных компьютерах
Если вам нужно собрать информацию о пользователях сразу с нескольких компьютерах, можете использовать следующую PowerShell функцию получить имена пользователей.
function Get-LoggedUser { [CmdletBinding()] param ( [string[]]$ComputerName ) foreach ($comp in $ComputerName) { $output = @{'Computer' = $comp } $output.UserName = (Get-WmiObject -Class win32_computersystem -ComputerName $comp).UserName [PSCustomObject]$output } }
На вход функции Get-LoggedUser нужно передать имена компьютеров, на которых нужно проверить имена пользователей:
Get-LoggedUser wks215s1,wks215s2,dc01
Если для какого-то компьютера функция вернула пустое имя пользователя, значит на компьютер никто не залогинен.
Можно получить имена пользователей, которые работают на компьютерах в домене Active Directory. Для получения списка компьютеров нужно использовать командлет Get-ADComputer. В следующем примере мы получим имена пользователей, которые работают за активными компьютерами в определенном OU домена. Чтобы скрипт работал быстрее перед тем, как обратится к обратится к удаленному компьютеру, я добавил проверку его доступности по сети через ICMP пинг с помощью командлета Test-NetConnection:
function Get-LoggedUser { [CmdletBinding()] param ( [string[]]$ComputerName ) foreach ($comp in $ComputerName) { if ((Test-NetConnection $comp -WarningAction SilentlyContinue).PingSucceeded -eq $true) { $output = @{'Computer' = $comp } $output.UserName = (Get-WmiObject -Class win32_computersystem -ComputerName $comp).UserName } else { $output = @{'Computer' = $comp } $output.UserName = "offline" } [PSCustomObject]$output } } $computers = (Get-AdComputer -Filter {enabled -eq "true"} -SearchBase 'OU=Kazan,DC=winitpro,DC=loc').Name Get-LoggedUser $computers |ft -AutoSize
Также обратите внимание, что вы можете хранить в свойствах компьютеров в AD имя пользователя, который выполнил вход. Для этого можно использовать логон скрипт, описанный в статье “Set-ADComputer: добавляем информацию о пользователе в свойства компьютеров AD”
После этого вам не нужно сканировать все компьютеры, чтобы найти где залогинен определенный пользователь. Можно найти компьютер пользователя простым запросом к Active Directory:
$user='dvpetrov'
$user_cn=(get-aduser $user -properties *).DistinguishedName
Get-ADComputer -Filter "ManagedBy -eq '$user_cn'" -properties *|select name,description,managedBy|ft
У меня вопрос. Даже два. А если удаленный зафайерволлен, то соответственно, все эти скрипты работать не будут, верно ведь, да? 🙂
Так почему бы не проанализировать журнал аудита на контроллере домена на предмет выдачи тикетов?
Все верно, включенный файервол заблокирует подключение. Но файерволы надо настраивать, нет? 🙂
Варинт с парсингом логов на DC тоже на самом деле так себе — что если у вас десяток DC?
Тут наверно лучше логи лить в Azure log Analytics или ELK, и простым запросом делать выборку.
Либо вариант с логон скриптом, который записывает в свойства компьютера в AD имя пользователя, выполнившего вход (ссылка ближе к концу).
Главное, чтобы таки на удалённом ПК работала «Служба управления Windows». Настраивается через групповые политики, например.
Я вывел в поле Description в ADUC залогиненых и разлогиненых товарищей
Скрипт выложить могу, если кому надо, работает через групповые политики
Если можете, поделитесь. Прямо в комменте, или мне на ящик
Делюсь vbs скриптом. Кидаем его и в логон и логофф gpo. В результате в поле Description ваших компуктеров отобразится Пользователь и время его входа либо выхода. В скрипте не забудьте поправить ВХОД в логон скрипте либо ВЫХОД в логофф скрипте
On Error Resume Next
Dim adsinfo, ThisComp, oUser
Set adsinfo = CreateObject(«adsysteminfo»)
Set ThisComp = GetObject(«LDAP://» & adsinfo.ComputerName)
Set oUser = GetObject(«LDAP://» & adsinfo.UserName)
Thiscomp.put «description», «>> В(Ы)ХОД: » + oUser.cn + » » + CStr(Now)
ThisComp.Setinfo
Есть момент, с которым пока не получается разобраться:
Чтение (Win32_ComputerSystem).UserName требует особенных поономочий, недостаточно просто дать права на чтение всего от самого корня дерева root вниз, рекурсивно + группа «Пользователи DCOM»
Сам класс вычитывается удаленно, но только не UserName, его получается прочитать только если сервисную учетку, из под которой пробуем читать UserName удаленно через WMI, добавить в группу «Пользователи удаленного рабочего стола»
Конечная задача — делегировать права на чтение WMI доменной сервисной учетке, без стандартной локально группы Администраторы на целевом компе.
Может кто-то встречался с такой проблемой и как то решил вопрос с правами WMI?
Лет 10 назад решал уже эту проблему, победил тогда, но никак не могу вспомнить как и записей не осталось уже.
Другие варианты не интересуют, нужен именно класс Win32_ComputerSystem и чтение его не админом удаленно.
С раздачачей прав в WMI не игрался, и не знаю возомжно ли дать их так гранулированно.
Но в такис ситуациях может помочь PowerShell Just Enough Administration (JEA), который позволяет настроить какие точно команды, допустимые параметры и кому/из под кого разрешено выполнять удаленно.
https://winitpro.ru/index.php/2020/09/29/powershell-just-enough-administration-jea-delegirovaniye-admin-prav-polzovatelyam/