foreach ($dev in (Get-PnpDevice | Where-Object{$_.Name -like "Tap*"})){ .\pnputil.exe /remove-device $dev.InstanceId }
пятница, 9 августа 2024 г.
Posh удалить все TAP устройства
понедельник, 3 июня 2024 г.
CMD Объем носителей и свободное пространство
На просторах можно найти полный красивый скрипт, но мне достаточно вот этой строки для оценки
WMIC LogicalDisk WHERE "DriveType='3'" GET FreeSpace^, Name^, Size
суббота, 11 мая 2024 г.
RPi подключаем модем для обработки USSD и SMS
Ниже описан полный путь. В какой то момент я купил новый модем, но у него оказался API без поддержки USSD и я вернулся к старому. Поэтому не взыщите за столь длинный эпос
yser@rpi02:~ $ lsusb
Bus 001 Device 007: ID 12d1:1001 Huawei Technologies Co., Ltd. E161/E169/E620/E800 HSDPA Modem
Bus 001 Device 004: ID 0d9f:00a7 Powercom Co., Ltd UPS KIN-2200AP FW3.A7
Bus 001 Device 005: ID 0d9f:0002 Powercom Co., Ltd Black Knight PRO / WOW Uninterruptible Power Supply (Cypress HID->COM RS232)
Bus 001 Device 006: ID 0424:7800 Microchip Technology, Inc. (formerly SMSC)
Bus 001 Device 003: ID 0424:2514 Microchip Technology, Inc. (formerly SMSC) USB 2.0 Hub
Bus 001 Device 002: ID 0424:2514 Microchip Technology, Inc. (formerly SMSC) USB 2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
user@rpi02:~ $ cat lsusb_ext.sh
#!/bin/bash
for sysdevpath in $(find /sys/bus/usb/devices/usb*/ -name dev); do
(
syspath="${sysdevpath%/dev}"
devname="$(udevadm info -q name -p $syspath)"
[[ "$devname" == "bus/"* ]] && exit
eval "$(udevadm info -q property --export -p $syspath)"
[[ -z "$ID_SERIAL" ]] && exit
echo "/dev/$devname - $ID_SERIAL"
)
done
user@rpi02:~ $ ./lsusb_ext.sh
/dev/ttyUSB2 - HUAWEI_Technology_HUAWEI_Mobile
/dev/ttyUSB3 - HUAWEI_Technology_HUAWEI_Mobile
/dev/ttyUSB1 - HUAWEI_Technology_HUAWEI_Mobile
/dev/ttyUSB0 - POWERCOM_CO.__LTD._USB_to_Serial
Исполнить правила devrul без перезапуска/перевыдергивания
sudo udevadm control --reload-rules && sudo udevadm trigger
Чего то с тем модемом не взлетело. Купил E3372h-153, вроде как с ним должно быть проще, но нет
понедельник, 1 апреля 2024 г.
RPi 3B+ DHT11/22 Monitoring
На данный момент в "серверной" мы проверяем температуру при помощи камеры направленной на термометр от Xiaomi. Работу кондиционера оцениваем по веревочкам, т.е. если они колышатся, то кондиционер работает. Также на самой камере настроено оповещение на почту при наличии движения от этих веревочек два раза в сутки. Логика простая: есть движение - отправить письмо, нет движения - нет письма. Нет письма - реагируем. У меня есть RaspberryPi и датчик температуры/влажности DTH11. Малинка стоит в серверной, так почему бы мне не научить малину считывать температуру? Почему бы не мониторить температуру заббиксом, чтобы оповещать при критической ситуации?
Сначала подключим к малине датчик
Для работы сенсора буду использовать Adafruit, надо установить (предполагается что pip3 и python уже стоят на малине, моя ОС на базе Debian 12):
user@rpi02:~$ sudo pip3 install Adafruit_Python_DHT --break-system-packages
среда, 13 марта 2024 г.
PoSh Script Проверка web сервиса и перезапуск docker desktop
Сервис развернут контейнере (Docker desktop). Пожаловались, что иногда он вываливается и единственное решение - полный перезапуск wsl и "docker desktop". Пользователь в будуюшем будет переносить докеры в linux среду, а на текущий момент нужен костыль. Сразу оговорюсь, попытка создать службу docker провалилась, поэтому здесь решение совсем грязное. Но в самом скрипте есть пара интересных, для меня, моментов, поэтому кладу его здесь.
Скрипт проверяет ответ от web-сервиса (внешний адрес и порт), если его нету, то ждет N время, иначе выходит. По истечении N времени идет повторная проверка, если ответа нет, то идет проверка локальная, иначе выход. Если локальная проверка не прошла, то перезапускаем нужные службы и программы, иначе выходим.
Запускать я решил батником в task scheduller, чтобы не править каждый раз задачу. При этом задача должна выполнятся от имени администратора и БЕЗ привязки к пользователю, иначе Desktop manager не запустит контейнеры.
Два триггера
Для автозапуска Docker desktop при загрузке ПК настраиваем автовход пользователя (control userpasswords2) и автозапуск Docker desktop при входе в настройках программы. На данный момент это единственное рабочее решение из найденных :-(
Команда запуска в планировщике (окно скрипта скрыто)
%windir%\system32\cmd.exe
/c start /min C:\usr\WSLCheckStart.bat ^& exit
Будьте осторожны с таким методом скрытия окна. Этот метод открывает скрипт за пределами планировщика. Планировщик не может контролировать выполнение задачи, а значит возможно наложение нескольких задач. Для таких случаев рекомендуется проводить проверку в самом скрипте.
Батник:
@echo off
cd %~dp0
set "pathscript=%~dp0\WSLCheck.ps1"
set "pathlog=%~dp0\log"
mkdir %~dp0\log
IF EXIST %pathscript% (
powershell.exe -NoProfile -ExecutionPolicy Bypass -File %pathscript% -Address "dev.site.com" -Port "443" -LocalPort "8080" -TimeOut 20 -TimeOutHTTP 10 -LogFile %pathlog%
) ELSE (
echo "ERROR! %pathscript% not exist"
echo "ERROR! %pathscript% not exist" >> WSLLogStart.log
)
Сам скрипт Powershell
Posh script Простенькая функция логирования
# Имя файла лога отличается от имени скрипта только расширением
$ScriptPath=(Get-Item $PSCommandPath).Directory
$ScriptBaseName=(Get-Item $PSCommandPath).BaseName
$LogFile="$ScriptPath\$ScriptBaseName.log"
$whatif=$false
# простенькая функция логирования, если файл есть, то пишет в него
# можно было использовать tee-object, но этот командлет выдает ошибку при отсутствии папки для лога
# CheckRepeat проверяет последнюю строку лога с будущей, чтобы не засорять файл
# level - число -
function Logging($Message,$Level=0,$CheckRepeat=$false){
if ("$Message" -eq ""){
return
}
$mLevel=switch($level){
0 {New-Object psobject -Property @{label="[INF]";color="White"}}
1 {New-Object psobject -Property @{label="[WAR]";color="Yellow"}}
2 {New-Object psobject -Property @{label="[ERR]";color="Red"}}
}
$CurrentTimeStamp=Get-Date -Format "dd.MM.yyyy`tHH:mm:ss"
Write-Host "$Message" -ForegroundColor $mLevel.color
if ($whatif){return}
if (-not (Test-Path $LogFile)) {New-Item -Path $LogFile -ItemType File -ErrorAction SilentlyContinue}
if (Test-Path $LogFile) {
$lastLine=""
if ($CheckRepeat){
$lastLine=$(Get-Content -Path $LogFile)[-1].Split("`t")[-1]
}
if ("$Message" -ne "$lastLine"){
Write-Output("$CurrentTimeStamp`t$($mLevel.label)`t$Message") | Out-File $LogFile -Append
}
}
}
пятница, 23 февраля 2024 г.
Bash скрипт заметка
Заметка скрипт.
Интересный моменты в скрипте:
- Вызов функции из себя как вариант цикличности, а не рекурсии
- $EUID -ne 0
Проверка на наличие root прав у текущего пользователя - echo -e "[User]\nSystemAccount=true"> /var/lib/AccountsService/users/$AdminName
Скрытие учетки в *nix-подобных системах (сервисный аккаунт) - logname
Получение имени залогинившегося пользователя, даже если он под sudo - eval getent passwd {$UID_MIN..$UID_MAX}
eval - преобразует текст в команду - getent passwd {1000..6000} | cut -d: -f1
получение списка пользователей с UID между 1000-6000, все сервисные аккаунты имеют UID < 1000 - blkid -U "$(grep -vE "^#|^$" /etc/crypttab | tail -n1 | cut -d" " -f1 | cut -d"-" -f2-)"
LUKS иногда создает устройство с именем равным LUKS-UUID_source_block_device, но вот получить именно адрес в виде /dev/sda3 не так просто
- Проверить наличие определенного пользователя
- Создать администратора, при его отсутствии
- Переименовать выбранного пользователя
- Сбросить ID Anydesk
- Изменить passphrase для шифрованного раздела
- Переименовать ПК
среда, 21 февраля 2024 г.
Script posh Keepass Выбор профиля Chrome
По-умолчанию двойной клик по полю url с протоколом https/http открывает новую вкладку chrome в ближайшем окне (если смотреть по порядку). При этом не важно, какой там профиль. Меня это не устраивает. Поэтому я начал искать пути решения.
Первый вариант был привязать тег keepass к папке и добавлять его как параметр --profile-directory, но оказывается я не могу использовать теги.
Следующий вариант был - получить в окне powershell список профилей из каталога %userprofile%\AppData\Local\Google\Chrome\User Data\, но тут лежат не только профили, а сами профили имеют отличные, от заданных в chrome, имена. В итоге выяснилось, что информация об именах и каталогах хранится в файле %userprofile%\AppData\Local\Google\Chrome\User Data\Local State. Это JSON файл, и, к сожалению, в одну строчку распарсить его не получится. Поэтому родился вот такой скрипт с дополнительными проверками. Скрипт выдает таблицу
воскресенье, 11 февраля 2024 г.
Script Posh Сформировать список файловых баз 1С рекурсивно
Переношу 1С с одного сервера на другой, основные базы были клиент-серверные, переводим в файловую и добавляем в список. Делов на пять минут, так как их не много. А вот в файловых базах целая туча без логики во вложенности. Решил накидать скрипт, который сам сформирует список баз. Скрипт проходит рекурсивно, ищет файл базы 1Cv8.1CD и строит дерево. Если в каталоге нет файла БД и нет подкаталогов, то пропускает, во всех остальных случаях добавляет в файл списка баз. Из за этого возможны пустые каталоги
$Folder="D:\1C_BASES\Базы1с_8"
$filev8i="$Folder\bases_here.v8i"
$level=1
function CheckName{
param(
[Parameter()]
[string]$Name,
[Parameter()]
[string]$File,
[Parameter()]
[int]$cnt=1
)
$content=$(Get-Content $File)
if ($content | Select-String -Pattern "[$Name]" -SimpleMatch -Quiet){
$cnt=$cnt+1
$res=$(CheckName -Name "$Name ($cnt)" -File $file -cnt $cnt)
}else{
$res=$Name
}
return $res
}
function GetTree{
param(
[Parameter()]
[string]$Folder,
[Parameter()]
[string]$Parent="",
[Parameter()]
[int]$level
)
$ChildList=$(Get-ChildItem -Path $Folder -Directory)
foreach ($child in $ChildList){
$FullPath=$($child.FullName)
$NameParentFolder=$Parent
if (Test-Path "$FullPath\1Cv8.1CD"){
$pref="-"*$($level)+"|->"
Write-Host("$pref Folder `"$child`" with 1C Bases")
$Name=$(CheckName -Name $child -File $filev8i)
$Text=@"
[$Name]
Connect=File=`"$FullPath`";
ID=
OrderInList=
Folder=$($NameParentFolder.Replace("\","/"))
OrderInTree=
External=0
ClientConnectionSpeed=Normal
App=Auto
WA=1
Version=8.3
AppArch=Auto
DisableLocalSpeechToText=0
DisableLocalSpeechToText=0
"@
Write-Output($text) | Out-File -Encoding "UTF8" $filev8i -Append
} else {
if ($(get-childitem $FullPath -Directory).count -gt 0){
$pref="-"*$level+"|->"
Write-Host("$pref Folder `"$child`":")
$Name=$(CheckName -Name $child -File $filev8i)
$text=@"
[$name]
ID=
Folder=$($NameParentFolder.Replace("\","/"))
"@
Write-Output($text) | Out-File -Encoding "UTF8" $filev8i -Append
GetTree -Folder $FullPath -Parent "$NameParentFolder\$name" -level $($level+1)
} else {
$pref="-"*$level+"|->"
Write-Host("$pref Folder `"$child`" not contain subfolders")
}
}
}
}
Remove-Item -Path $filev8i -Force
$currentParent=$(($Folder.Split("\"))[-1])
$text=@"
[$currentParent]
ID=
Folder=/
"@
Write-Output($text) | Out-File -Encoding "UTF8" $filev8i -Append
GetTree -Folder $Folder -level $level -Parent "/$currentParent"
Скрипт мою задачу решил, наводить лоск смысла не вижу смысла
воскресенье, 4 февраля 2024 г.
Script Posh Восстановление acl в папке пользователя
В попытке настроить аудит, у меня сломался acl для пользовательских папок. Если бы речь шла об одной папке, то я бы решил этот вопрос простым удалением папки пользователя и его повторным входом в систему. Но речь шла о терминальном сервере. Поэтому родился этот скрипт. Единственно что надо учесть:
- Скрипт рассчитан на русскую локализацию
- Скрипт обрабатывает только каталоги внутри пользовательского
- Скрипт подразумевает, что имя каталога совпадает с именем пользователя
- Скрипт рассчитан на то, что владельцем каталога пользователя является системная учетная запись, а все дочерние принадлежат пользователю. На разных системах по разному.
- Сам скрипт использует icacls, вместо get-acl.
- Входящими параметрами скрипта является имя пользователя и домен, если домен не указан, то скрипт будет использовать имя ПК, с которого запущен (на тесте были ошибки, но мне не нужно было и не стал исправлять).
param(
[Parameter()]
[string]$User,
[Parameter()]
[string]$Domain=$env:COMPUTERNAME
)
$LogFile = (Get-Item $PSCommandPath ).DirectoryName+"\"+(Get-Item $PSCommandPath ).BaseName+".log"
$CurrentTimeStamp=Get-Date -Format "dd.MM.yyyy`tHH:mm:ss"
function Logging($Message) {
Write-Host "$Message"
Write-Output("$CurrentTimeStamp`t$Message") | Out-File $LogFile -Append
}
if ($User) {
Logging("User $User in $Domain is processing")
} else {
Logging("Parameter `"User for processing (-User)`" is not specified ")
exit
}
$UserFolder="C:\users\$User"
if (-Not (Test-Path $UserFolder)) {
Logging("User folder $UserFolder not found")
Exit
}
function getAcls ($ObjectFS){
switch ($ObjectFS)
{
"Application Data" {return "SYSTEM"}
"Local Settings" {return "SYSTEM"}
"NetHood" {return "SYSTEM"}
"PrintHood" {return "SYSTEM"}
"SendTo" {return "SYSTEM"}
"главное меню" {return "SYSTEM"}
"Мои документы" {return "SYSTEM"}
"Шаблоны" {return "SYSTEM"}
Default {return "FULL"}
}
}
foreach ($ObjectFS in $(Get-ChildItem -Path $UserFolder -Force -Exclude "ntuser*","AppData")) {
$ObjectFSFullName=$($ObjectFS.FullName)
Logging(" Object $ObjectFSFullName is processing")
#ICACLS
$ACL= getAcls($ObjectFS.BaseName)
Logging(" $ACL")
Logging(" ICACLS $ObjectFSFullName /setowner $Domain\$user")
ICACLS $ObjectFSFullName /setowner $Domain\$user /C /Q
Logging(" ICACLS $ObjectFSFullName /C /Q /RESET")
ICACLS $ObjectFSFullName /C /Q /RESET
if ( "$ACL" -eq "SYSTEM" ) {
Logging(" ICACLS $ObjectFSFullName /setowner `"NT AUTHORITY\СИСТЕМА`" /c /q")
ICACLS $ObjectFSFullName /setowner "NT AUTHORITY\СИСТЕМА" /c /q
Logging(" ICACLS $ObjectFSFullName /deny `"Все:(NP)(S,RD)`" /c /q")
ICACLS $ObjectFSFullName /deny "Все:(NP)(S,RD)" /c /q
}
}
воскресенье, 28 января 2024 г.
AHK управление аудиоустройством не по-умолчанию
Повесил себе колонку для фоновой музыки. Уровень громкости там около 6 единиц, при этом на основной колонке требуется уровень >30. В общем Windows 10 позволяет настроить вывод на разные аудиоустройства, но управление громкостью возможно только в том, которое выбрано сейчас.
#Requires AutoHotkey v2.0
; Use the Soundcard Analysis script found here to set these parameters
; https://www.autohotkey.com/docs/v2/lib/Sound.htm#ExSoundcard
DeviceNumber := 3
ComponentID := ""
savedVol := 0
LShift & Volume_Up::{
SoundSetVolume("+2", ComponentID, DeviceNumber)
}
LShift & Volume_Down::{
SoundSetVolume(-2, ComponentID, DeviceNumber)
}
LShift & Volume_Mute::{
global savedVol
currentVol := SoundGetVolume(ComponentID, DeviceNumber)
if (currentVol > 0){
savedVol := currentVol
SoundSetVolume(0, ComponentID, DeviceNumber)
} else {
SoundSetVolume(savedVol, ComponentID, DeviceNumber)
}
}
Скрипт найден на просторах интернета, я лишь уточнил, что реагируем не на стандартные клавиши, а на их сочетание с левым шифтом. device number подобран эмпирическим путем. Теперь стандартные клавиши (mute, Volume Up, Volume Down) работают как раньше на текущее основное аудиоустройство, а сочетание с shift - только на устройств с Device Number равным 3, т.е. в моем случае колонка Dell
AHK Переключение раскладки между двумя последними
Когда пишешь код для 1С на кириллице, приходится постоянно переключаться между раскладками, так как в коде используются некоторые символы, доступные только в латинской раскладке. Да можно настроить клавиатуру под себя, но мне это не очень удобно. Поэтому я вынужден постоянно переключаться между раскладками. В какой то момент обратил внимание на то, что раскладка не успевает переключиться за то время, как я нажимаю клавиши. Выяснилось, что у windows есть таймаут нажатия и правится он в реестре:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Control Panel\Accessibility\Keyboard Response]
"DelayBeforeAcceptance"="50"
А когда у меня добавилась раскладка, выяснилось, что нельзя настроить переключение не иначе, как каруселью (стандартными средствами). Сегодня случайно узнал, что есть комбинация Win-Ctrl-Space, которая позволяет переключаться между двумя последними, как в gboard. А потом нашелся скрипт для autoHotKey, который позволяет сменить стандартное поведение alt+shift на эту волшебную комбинацию. Выбор другой раскладки можно оставить за win+Space или настроить при помощи стандартных средств.
Скрипт для ahk v1 и не мой, я лишь добавил {LAlt up}{LShift up}, так как у меня иногда "залипают" эти клавиши. Идея оказалась так себе, так как стало еще хуже
; This scripts changes the functi onality of Shift + Alt from "switch keyboard layout"
; to "change to previous layout".
; this is usefull when you have more than 2 keyboard layouts and want to switch between
; only 2 of them.
LAlt & LShift::send, #^{space down}{space up}
; Замена Alt-Shift на Win-Ctrl-Space
Теперь надо отучиться дважды переключать раскладку X-D
Неожиданно выяснилось, что эта штука ведет себя некорректно в сеансах RDP O_O. Пришлось сгруппировать процессы exe в группу и сказать скрипту работать, только если активное окно не входит в эту группу
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
GroupAdd, RDP_EXE, ahk_exe RDCMan.exe
GroupAdd, RDP_EXE, ahk_exe mRemoteNG.exe
GroupAdd, RDP_EXE, ahk_exe mstsc.exe
#IfWinNotActive ahk_group RDP_EXE
LAlt & LShift::send, #^{space down}{space up} ; Замена Alt-Shift на Win-Ctrl-Space
#If
пятница, 26 января 2024 г.
CMD Симлинки в профиле пользователя
Как посмотреть симовлические ссылки в Windows
dir /AL /S "C:\Users\%username%"
А это список ссылок, которые есть в профиле пользователя (пысы, случайно грохнул содержимое своей папки пользователя О_О)
mklink /j "C:\Users\%username%\Application Data" "C:\Users\%username%\AppData\Roaming"
mklink /j "C:\Users\%username%\Cookies" "C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Cookies"
mklink /j "C:\Users\%username%\Local Settings" "C:\Users\%username%\AppData\Local"
mklink /j "C:\Users\%username%\NetHood" "C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Network Shortcuts"
mklink /j "C:\Users\%username%\PrintHood" "C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Printer Shortcuts"
mklink /j "C:\Users\%username%\Recent" "C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Recent"
mklink /j "C:\Users\%username%\SendTo" "C:\Users\%username%\AppData\Roaming\Microsoft\Windows\SendTo"
mklink /j "C:\Users\%username%\Главное меню" "C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Start Menu"
mklink /j "C:\Users\%username%\Мои документы" "C:\Users\%username%\Documents"
mklink /j "C:\Users\%username%\Шаблоны" "C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Templates"
mklink /j "C:\Users\%username%\AppData\Local\Application Data" "C:\Users\%username%\AppData\Local"
mklink /j "C:\Users\%username%\AppData\Local\History" "C:\Users\%username%\AppData\Local\Microsoft\Windows\History"
mklink /j "C:\Users\%username%\AppData\Local\Temporary Internet Files" "C:\Users\%username%\AppData\Local\Microsoft\Windows\Temporary Internet Files"
mklink /j "C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Start Menu\Программы" "C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs"
mklink /j "C:\Users\%username%\Documents\Мои видеозаписи" "C:\Users\%username%\Videos"
mklink /j "C:\Users\%username%\Documents\Мои рисунки" "C:\Users\%username%\Pictures"
mklink /j "C:\Users\%username%\Documents\Моя музыка" "C:\Users\%username%\Music"
четверг, 28 декабря 2023 г.
Обновление пароля при входе на сервер RDP
Попалась интересная задачка: генерировать пароль для RDP и выдавать его в телеграм боте.
Ну тут множество готовых решений есть, но решили сделать свое. Плюс я внес корректив в план и описал его так:
- Пользователь приходит на работу
- Открывает ТГ, проваливается в бота и запрашивает пароль (команда=имя)
- Бот смотрит на сервере файл с именем команды и возвращает содержимое
- Пользователь заходит на сервер
- На сервере срабатывает триггер и запускает скрипт
- Скрипт генерирует пароль и отправляет его на сервер бота в файл
- Пользователь пошел кушац, комп заблокировался
- Пользователь вернулся и начинает с шага 2
вторник, 28 ноября 2023 г.
GPO+Powershell Включение аудита файлов пользователя
понедельник, 20 ноября 2023 г.
RDP ограничение сеансов по времени
Задача банальна - завершить сеансы пользователей через 2 минуты простоя, но это оказалось не так просто, по следующим причинам:
- Настройки на вкладке сеансы свойств пользователя не применяются. Я не знаю почему, они никогда не работали у меня
- Настройка через групповые политики работает на всех пользователях
- Настройка через реестр работает на всех пользователях
- Доменной структуры нет, поэтому разделить при помощи GPO правых и левых нельзя
суббота, 16 сентября 2023 г.
Заметка Powershell и скрипт добавления IKEv2
Простой скрипт добавления интерфейса IKEv2. Данное решение выполняет следующие задачи:
- Экспортирует сертификат пользователя и CA
- Добавляет интерфейс IKEv2
- Создает IPsec политику
- Связывает интерфейс с CA
- Отключает маршрут по умолчанию
- Отключает IPv6
- Отключает автометрику и выставляет метрику равной 1. Данная метрика не влияет на трафик, нужна только для смены порядка выбора DNS сервера (подробнее)
Posh Закодировать скрипт, заготовка
Понадобилось закодировать скрипт, но не ради обмана антивируса, а из-за нежелания возиться с экранированием символов при создании скрипта из батника. В итоге родилось вот такое чудо:
param ($CreateBatch=$False)
$CurrentDir = Split-Path -Parent $MyInvocation.MyCommand.Path
Set-Location -Path $CurrentDir
if ($CreateBatch -eq $true) {
$ps_file_name=(Get-Item $PSCommandPath).Name
$cmd_file_name=((Get-Item $PSCommandPath).Basename+".bat")
$encoded_script=[Convert]::ToBase64String( [System.Text.Encoding]::Unicode.GetBytes( $(Get-Content $ps_file_name -Raw)))
$content=("@echo off`r`n"+
"cd %~dp0`r`n"+
"powershell -Command [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String('$encoded_script'))>$ps_file_name`r`n"+
"powershell -NoProfile -ExecutionPolicy Bypass -File $ps_file_name`r`n"+
"pause")
out-file -FilePath $CurrentDir\$cmd_file_name -InputObject $content -Encoding ASCII
exit
}
Данная заготовка добавляет параметр (добавьте его, если блок с параметрами уже есть) и проверяет его, если он истин, то выполняется создание батника с закодированным скриптом. Батник будет иметь такое же имя с расширением bat и лежать в этой же директории.
Именно Get-Content -Raw позволяет закодировать и раскодировать потом скрипт со всеми переносами строк. Если в скрипте нет обращений к файлам с неизвестным расположением, то можно выполнить скрипт без разворачивания в отдельный файл командой powershell -enc "закодированная строка".
среда, 13 сентября 2023 г.
Powershell Fail2ban for RDP
Да, можно использовать VPN, разрешенные списки IP адресов и прочее, но бывают случаи, когда требуется прямой доступ к машине без всего этого. Тогда встает вопрос о хотя бы защите от грубого перебора паролей? Есть некоторое количество программ, которые позволяют это сделать, но к сожалению они не являются частью ОС Windows. На просторах интернета был найден скрипт и слегка доработан, можно его использовать повесив в планировщике на событие 4625 журнала безопасность.
Также для работы нужно правило в firewall с именем BlockRDP (читай комментарии к скрипту)
# After first run you need to create firewall rule
# New-NetFirewallRule -DisplayName "BlockRDPBruteForce" –RemoteAddress 1.1.1.1 -Direction Inbound -Protocol TCP –LocalPort 3389 -Action Block
# In action task scheduler. Check name script file
# %systemroot%\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\ps\ban_rdp_brutfors.ps1"
$log = "C:\ps\blocked_ip.txt"
$interval = 600000; #600000ms = 10min
$count_fail = 5
# фильтр событий в журнале
$XPath = "*[System[Provider[@Name=""Microsoft-Windows-Security-Auditing""]
and Task = 12544
and (band(Keywords,4503599627370496))
and (EventID=4625)
and TimeCreated[timediff(@SystemTime) >= $interval]]]";
$list_IP =@();
$Events = @();
# выбираем события
try { $Events = Get-WinEvent -Logname "security" -FilterXPath $XPath -ErrorAction Stop
}
catch [Exception] {
if ($_.Exception -match "Не удалось найти события, соответствующие указанному условию выбора.") {
Write-Host "Не найдены события перебора паролей за последние $($interval/60000) мин.";
exit;
}
}
# выбираем IP адреса
$list_IP = $Events | ForEach-Object {
([xml]$_.ToXML()).Event.EventData.Data | Where-Object {$_.Name -eq "IpAddress"} | ForEach-Object {$_."#text"}} | Where-Object {$_ -ne "-" };
$current_ips = @((Get-NetFirewallRule -DisplayName "BlockRDP" | Get-NetFirewallAddressFilter ).RemoteAddress)
foreach ($ip in $list_IP) {
if ( $((($list_IP | where {$_ -eq $ip}).count) -gt $count_fail) -AND $(($current_ips | where {$_ -eq $ip}).count -eq 0)) {
(Get-Date).ToString() + " " + $ip + " IP заблокирован за " + $cnt_try + " попыток за $($interval/60000) мин.">> $log # запись события блокировки IP адреса в лог файл
$current_ips += $ip
}
}
$current_ips = $current_ips | gu
if ($current_ips.Length -gt 0) {
Set-NetFirewallRule -DisplayName "BlockRDP" -RemoteAddress $current_ips
}
суббота, 9 сентября 2023 г.
Удаление данных пользователя при выходе
Google Chrome (да и большинство браузеров) можно настроить так, что при закрытии он удаляет все данные работы, как инкогнито, но не инкогнито (читай тут). Встала задача провернуть такое же с учеткой Windows.
Сразу, это длинопост, в котором нет конкретного решения, есть мой путь к моему решению в самом конце