Powershell for Windows

21.06.2013

Пишем WinLocker на PowerShell.

Filed under: PowerShell, Security — Метки: , , , — Yamshikov Pavel @ 4:54 пп

Целью статьи не является создание вредоносного приложения. Полученный в результате код можно использовать в качестве примера создания GUI с помощью PowerShell. Пару лет назад я уже освещал тему создания подобного кода с помощью VBScript, правда тогда не обошлось без «костыля» в виде ActiveX DLL. В этот раз есть возможность решить вопрос «нативными» средствами.

Для начала нарисуем интерфейс нашего локера.
Честно говоря я не представляю себе скрипт, для создания интерфейса которого может возникнуть необходимость использовать WPF — красота тут ни к чему. В общем на любителя. По-моему проще через Windows Forms.
Открываем PowerShell ISE, рисуем:
— форму без границ, во весь экран, поверх всех окон, слегка прозрачную, оттенка синего цвета
— кнопку для проверки введенного кода разблокировки
— текстовое поля для ввода кода разблокировки
— поле, содержащее текст приглашения ввести код разблокировки

div class=»geshifilter»>

Add-Type -AssemblyName System.Windows.Forms

$Form = New-Object System.Windows.Forms.Form
$Form.TopMost = $true
$Form.FormBorderStyle = 0 # None
$Form.BackColor = '#3333ff'
$Form.WindowState = 2 # Maximized
$Form.ShowInTaskbar = $false
$Form.Opacity = 0.8

$Button = New-Object System.Windows.Forms.Button
$Button.Text = 'OK'
$Button.ForeColor = '#ffffff'
$Button.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",12,1,3) # Normal, Bold
$Button.Anchor = 0 # None
$Button.Width = 200
$Button.Height = 30
$Button.Left = ($Form.ClientSize.Width - $Button.Width)/2
$Button.Top = ($Form.ClientSize.Height - $Button.Height)/2 + 60
$Form.Controls.Add($Button)

$TextBox = New-Object System.Windows.Forms.TextBox
$TextBox.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",12,0,3) # Normal, Bold
$TextBox.Anchor = 0 # None
$TextBox.Width = 200
$TextBox.Left = ($Form.ClientSize.Width - $TextBox.Width)/2
$TextBox.Top = ($Form.ClientSize.Height - $TextBox.Height)/2 + 30
$Form.Controls.Add($TextBox)

$Label = New-Object System.Windows.Forms.Label
$Label.Font = New-Object System.Drawing.Font('Times New Roman',22,3,3) # Italic, Bold
$Label.ForeColor = '#ffffff'
$Label.AutoSize = $false
$Label.Dock = 5 # Fill
$Label.TextAlign = 32 # MiddleCenter
$Label.Text = "Пожалуйста, введите код:"
$Form.Controls.Add($Label)

$Form.ShowDialog() | Out-Null

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

Add-Type -AssemblyName System.Windows.Forms

$Form = New-Object System.Windows.Forms.Form
$Form.TopMost = $true
$Form.FormBorderStyle = 0 # None
$Form.BackColor = '#3333ff'
$Form.WindowState = 2 # Maximized
$Form.ShowInTaskbar = $false
$Form.Opacity = 0.8

$Button = New-Object System.Windows.Forms.Button
$Button.Text = 'OK'
$Button.ForeColor = '#ffffff'
$Button.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",12,1,3) # Normal, Bold
$Button.Anchor = 0 # None
$Button.Width = 200
$Button.Height = 30
$Button.Left = ($Form.ClientSize.Width - $Button.Width)/2
$Button.Top = ($Form.ClientSize.Height - $Button.Height)/2 + 60
$Form.Controls.Add($Button)

$TextBox = New-Object System.Windows.Forms.TextBox
$TextBox.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",12,0,3) # Normal, Bold
$TextBox.Anchor = 0 # None
$TextBox.Width = 200
$TextBox.Left = ($Form.ClientSize.Width - $TextBox.Width)/2
$TextBox.Top = ($Form.ClientSize.Height - $TextBox.Height)/2 + 30
$Form.Controls.Add($TextBox)

$Label = New-Object System.Windows.Forms.Label
$Label.Font = New-Object System.Drawing.Font('Times New Roman',22,3,3) # Italic, Bold
$Label.ForeColor = '#ffffff'
$Label.AutoSize = $false
$Label.Dock = 5 # Fill
$Label.TextAlign = 32 # MiddleCenter
$Label.Text = "Пожалуйста, введите код:"
$Form.Controls.Add($Label)

$notClose = $true # глобальная переменная - не позволять закрывать форму

# функция проверки введенного кода
function checkCode() { 
    $code = '12345' 
    if ($TextBox.Text -eq $code) {
        $notClose = $false
        $Form.Close()
    } 
}

# функция-обработчик события для текстового поля
function keyDown() {
    $ret = 'Return'
    if ($_.KeyCode -eq $ret) {
        Invoke-Expression "checkCode"
    }
}

# функция-обработчик события закрытия формы
function formClosing() {    
    if ($notClose) {        
        $_.Cancel = $true        
    }
}

# обработчик события для кнопки
$Button.add_Click({ Invoke-Expression "checkCode" })

# обработчик события для текстового поля
$TextBox.add_KeyDown({ Invoke-Expression "keyDown" })

# обработчик события закрытия формы
$Form.add_FormClosing({ Invoke-Expression "formClosing" })

$Form.ShowDialog() | Out-Null

Выполняем скрипт в PowerShell ISE (F5) . . .
Как запустить выполнение скрипта в «боевых» условиях — догадайтесь сами Smile.
Дисклеймер: за «допиливание» полученного кода с целью противозаконного использования автор ответственности не несет.

Written by: Anatoly Demidovich

18.06.2009

Удаляем «Левые» задания вида AT*.JOB

Вирус-червь Win32/Conficker создает в планировщике «левые» задания вида At*.job.
Для очистки компьютера от этой «грязи» написал скрипт на PowerShell.

Скрипт для очистки с одного компьютера.

param(
[string]$Computer,
[string]$Process = 'rundll32.exe',
[string]$FolderPath = 'c:\WINDOWS\Tasks',
[string]$ObjectName = 'at',
$User
)
#################################################################################################################
if ($Computer -eq "") {
Write-Host "ERROR: Use Computer parameter." -foregroundcolor blue ;break
}
if ($User -is [String]) {
$Connection = Get-Credential -Credential $User
}
if ($FolderPath -like "*:*") {
$FolderPath = $FolderPath.replace(":","$");
Write-Host "The path parametre has been changed on $FolderPath " -foregroundcolor Green
}
if ($ObjectName -notlike "*'*'*") {
$ObjectName = $ObjectName+'*';
Write-Host "The path parametre has been changed on $ObjectName" -foregroundcolor Green
}
#################################################################################################################
$ArrInfo = @();`
$InfoProcess = @();$InfoTasks = @();$counterProcess = 0;$counterTasks = 0
#################################################################################################################
if ($Connection -eq $null) {
$InfoTasks = Get-ChildItem -LiteralPath \\$Computer\$FolderPath -ErrorAction SilentlyContinue | where {$_.PSIsContainer -eq $false -and $_.PSChildName -like $ObjectName}
if ($InfoTasks -like $ObjectName){
$InfoProcess = gwmi "win32_process" -ComputerName $Computer -filter "name='$Process'" | % {$counterProcess++;$_.terminate()}
$InfoTasks | % {$counterTasks++;$_.delete()}
}
}
else {
$InfoTasks = Get-ChildItem -LiteralPath \\$Computer\$FolderPath -ErrorAction SilentlyContinue | where {$_.PSIsContainer -eq $false -and $_.PSChildName -like $ObjectName}
if ($InfoTasks -like $ObjectName){
$InfoProcess = gwmi "win32_process" -ComputerName $Computer -filter "name='$Process'" -Credential $Connection | % {$counterProcess++;$_.terminate()}
$InfoTasks | % {$counterTasks++;$_.delete()}
}
}
#################################################################################################################
$ArrInfo = "" | select @{e={$Computer};n='Компьютер'},`
@{e={$Process};n='Процесс'}, @{e={$counterProcess};n='Остановлен процесс'}, @{e={$ObjectName};n='Имя файла'}, @{e={$counterTasks};n='Удален объект'}
#################################################################################################################
$ArrInfo

Для очистки компьютеров в сети нужно видо изменить скрипт используя следующее:

1. Параметры

param(
[int[]]$a,
[int[]]$b = 1..254,
[string]$Process = 'rundll32.exe',
[string]$FolderPath = 'c:\WINDOWS\Tasks',
[string]$ObjectName = 'at',
$User
)

2.Функции проверки
Function ping ($Name){
$ping = new-object System.Net.NetworkInformation.Ping
if ($ping.send($Name).Status -eq "Success" ) { $True }
else { $False }
}

Function nbtstat ($Name) {
$nbtstat = c:\WINDOWS\system32\nbtstat.exe -A $Name | % {$_ -replace " *",""}
if ($nbtstat.SyncRoot[6] -ne "Узелненайден.") { $True }
else { $False }
}

4. Создаем список ИП-адресов и перебором проходимся по ним
$IPNetwork = @()
foreach ($y in $a) {foreach ($x in $b) {$IPNetwork += $("192.168.$y.$x")}}

foreach ($ip in $IPNetwork){
$Alive = «»;`
$NetName = «»
$Alive = ping $ip

if ($Alive -eq $True){
$NetName = nbtstat $ip

if ($NetName -eq $True){

Часть скрипта для очистки берем из первого

}}}

02.06.2009

Утилита для просмотра Svchost.exe

Svchost.exe — самый таинственный процесс в  Microsoft Windows.

Svchost Process Analyzer –  утилита  для детального просмотра процесса Svchost.exe. Это облегчит обнаружение саморазмножающегося вируса типа Conficker.

07.05.2009

Завершение процесса.

Скрипт ProccessKill.ps1

param(
[string]$Computer,
[string]$Process,
$User
)
if ($Computer -eq "" -and $Process -eq "") {
Write-Host "ERROR: Use Computer and Process parameter." -foregroundcolor blue ;break
}
if ($Computer -ne "" -and $Process -eq "") {
Write-Host "ERROR: Use Process parameter." -foregroundcolor blue ;break
}
if ($User -is [String] ) {
$Connection = Get-Credential -Credential $User
}
$Info = @();`
$arrInfo = @();$counter = 0
if ($Connection -eq $null) {
$Info = gwmi "win32_process" -ComputerName $Computer -filter "name='$Process'" | % {$counter++;$_.terminate()}
}
else {
$Info = gwmi "win32_process" -ComputerName $Computer -filter "name='$Process'" -Credential $Connection | % {$counter++;$_.terminate()}
}
$ArrInfo = "" | select @{e={$Computer};n='Компьютер'},`
@{e={$Process};n='Процесс'}, @{e={$counter};n='Количество'}
$ArrInfo

06.05.2009

Проверка работы службы и экспорт данных в файл *.csv

Работа скрипта:

  1. Задаем параметры
  2. Проверяем путь к папке и если нужно создаем.
  3. Циклом перебираем список указанных ИП-адресов
  4. Проверяем  “жив” ли  компьютер
  5. Проверяем есть ли доступ к компьютеру
  6. Циклом перебираем список указанных служб
  7. Проверяем на компьютере установлена служба
  8. Проверяем тип запуска и если нужно меняем на auto
  9. Проверяем работает ли служба и если нужно запускаем
  10. Экспорт данных в файл *.csv

Скрипт TestService.ps1


param (
[string]$Folder, # Путь к папке. Необязательный параметр.
[string[]]$IPNetwork, # ИП-адрес. Можно указать несколько значений.
[string[]]$ServiceName, # Имя сервиса. Можно указать несколько значений.
$User # Доменная учетная запись (domen\user).
#[int[]]$y, # Номер сети.
#[int[]]$x = 1..254 # Номер ип-адреса.
)

#region Parametrs
#foreach ($a in $y) {
# foreach ($b in $x) {
# $IPNetwork += $(«192.168.$a.$b»)
# }
#}

$Data = get-date -uformat «%d.%m.%Y»

if ($Folder -eq «») {
$LogPath = «C:\Temp\$Data»
}
else {
$LogPath = «$Folder\$Data»
}

if ($User -is [string]) {
$Connection = Get-Credential -Credential $User
}

$Ping = @();`
$NoAccess = @();$ServerRPCUnavailable = @();$ChangeStateOrStartMode = @();$NoService = @()
#endregion Parametrs

#region Check Path Export LOGS
If((Test-Path ($LogPath)) -eq $False) {
New-Item ($LogPath) -Type Directory
}
#endregion Check Path Export LOGS

#region We Write The Received Results in Log
$LogPing = «$LogPath\Ping.csv»
$LogNoService = «$LogPath\Service_No_Install.csv»
$LogChangeStateOrStartMode = «$LogPath\Change_State_Or_StartMode.csv»
$LogRPCUnavailable = «$LogPath\Server_RPC_Unavailable.csv»
$LogNoAccess = «$LogPath\No_Access_Computer.csv»
#endregion We Write The Received Results in Log

#region Function
function Ping ($Name){
$ping = new-object System.Net.NetworkInformation.Ping
if ($ping.send($Name).Status -eq «Success») {$True}
else {$False}
trap {Write-Verbose «Ошибка пинга»; $False; continue}
}
#endregion Function

#region Service Check
if ($Connection -eq $null){
foreach ($IP in $IPNetwork){
$Alive=»»;`
$Comp = «»;$Service = «»;$StartMode = «»;$State = «»

$Alive = Ping $IP
if ($Alive -eq «True»){
$Ping += «» | select @{e={$IP};n=’IP’}

Trap {Continue}
$Comp = gwmi -Class «Win32_computersystem» -ComputerName $IP -ErrorAction SilentlyContinue

if ($Comp -eq «»){
Write-Host «NoAccess $IP» -ForegroundColor Red ;`
$NoAccess += «» | select @{e={$IP};n=’IP’};
}

if ($Comp -eq $Null){
Write-Host «ServerRPCUnavailable $IP» -ForegroundColor Red ;`
$ServerRPCUnavailable += «» | select @{e={$IP};n=’IP’};
}

if ($Comp.Caption.Length -gt 1) {

foreach ( $SN in $ServiceName){
$Service = gwmi -Class «Win32_Service» -ComputerName $IP -Filter «name=’$($SN)'»

if ($Service -ne $Null) {

if ($Service.StartMode -ne «Auto») {
$Service.ChangeStartMode(«automatic»);`
$StartMode = ‘Change’
}

if ($Service.State -ne «Running») {
$Service.startservice();`
$State = ‘Change’
}

$ChangeStateOrStartMode += «» | select @{e={$comp.Name};n=’Computer’},`
@{e={$IP};n=’IP’},@{e={$Service.DisplayName+»(«+$Service.Name+»)»};n=’ServiceName’},@{e={$StartMode};n=’StartMode’},@{e={$State};n=’State’}
}

else {
$NoService += «» | select @{e={$comp.Name};n=’Computer’},`
@{e={$IP};n=’IP’},@{e={$ServiceName};n=’ServiceName’}
}
}
}
}
}

}
else {
foreach ($IP in $IPNetwork){
$Alive=»»;`
$Comp = «»;$Service = «»;$StartMode = «»;$State = «»

$Alive = Ping $IP
if ($Alive -eq «True»){
$Ping += «» | select @{e={$IP};n=’IP’}

Trap {Continue}
$Comp = gwmi -Class «Win32_computersystem» -ComputerName $IP -Credential $Connection -ErrorAction SilentlyContinue

if ($Comp -eq «»){
Write-Host «NoAccess $IP» -ForegroundColor Red ;`
$NoAccess += «» | select @{e={$IP};n=’IP’};
}

if ($Comp -eq $Null){
Write-Host «ServerRPCUnavailable $IP» -ForegroundColor Red ;`
$ServerRPCUnavailable += «» | select @{e={$IP};n=’IP’};
}

if ($Comp.Caption.Length -gt 1) {

foreach ( $SN in $ServiceName){
$Service = gwmi -Class «Win32_Service» -ComputerName $IP -Filter «name=’$($SN)'» -Credential $Connection

if ($Service -ne $Null) {

if ($Service.StartMode -ne «Auto») {
$Service.ChangeStartMode(«automatic»);`
$StartMode = ‘Change’
}

if ($Service.State -ne «Running») {
$Service.startservice();`
$State = ‘Change’
}

$ChangeStateOrStartMode += «» | select @{e={$comp.Name};n=’Computer’},`
@{e={$IP};n=’IP’},@{e={$Service.DisplayName+»(«+$Service.Name+»)»};n=’ServiceName’},@{e={$StartMode};n=’StartMode’},@{e={$State};n=’State’}
}

else {
$NoService += «» | select @{e={$comp.Name};n=’Computer’},`
@{e={$IP};n=’IP’},@{e={$ServiceName};n=’ServiceName’}
}
}
}
}
}
}
#endregion Service Check

#region Save to File
$Ping | export-csv -Encoding OEM -Path $LogPing -NoTypeInformation
$NoAccess | export-csv -Encoding OEM -Path $LogNoAccess -NoTypeInformation
$ServerRPCUnavailable | export-csv -Encoding OEM -Path $LogRPCUnavailable -NoTypeInformation
$ChangeStateOrStartMode | export-csv -Encoding OEM -Path $LogChangeStateOrStartMode -NoTypeInformation
$NoService | export-csv -Encoding OEM -Path $LogNoService -NoTypeInformation
#endregion Save to File

Поиск в локальной сети открытых ресурсов и экспорт в файл *.csv

Работа скрипта:

  1. Проверяем путь к папке и если нужно создаем.
  2. Создаем список компьютеров доменной сети
  3. Циклом перебираем список компьютеров доменной сети
  4. Проверяем  «жив» ли  компьютер
  5. Проверяем есть ли доступ к компьютеру
  6. Получаем список «шар» (без системных «шар»)
  7. Проверяем есть ли доступ к «шаре»
  8. Получаем данные о «шаре» (имя, путь, разрешения доступа)
  9. Экспорт данных в файл *.csv

Скрипт FindLanShares.ps1

$Data = get-date -uformat "%d.%m.%Y_%H.%M.%S"
$LogPath = "C:\Monitoring\LOG\$Data"
$AllComputerInfo = @();$AllNOPermissions = @();$AllServerRPCUnavailable = @();$AllNoAccess = @()

#region Check Path Export LOGS
If((Test-Path ($LogPath)) -eq $False)
{New-Item ($LogPath) -Type Directory}
#endregion Check Path Export LOGS

#region We Write The Received Results in Log.
$LogADComputerInfo = "$LogPath\Computer_Information.csv"
$LogNOPermissions = "$LogPath\NO_Permissions_Share.csv"
$LogRPCUnavailable = "$LogPath\Server_RPC_Unavailable.csv"
$LogNoAccess = "$LogPath\No_Access_Computer.csv"
#endregion We Write The Received Results in Log.

#region Function
function Ping ($Name){
$ping = new-object System.Net.NetworkInformation.Ping
if ($ping.send($Name).Status -eq "Success" ) { $True }
else { $False }
trap {Write-Verbose "Ошибка пинга"; $False; continue}
}
#endregion Function

#region Collection of the Information on the Computer

#region The List Active Directory Computers
$LC = Get-QADComputer -ErrorAction SilentlyContinue -SizeLimit 0 | Sort-object Name | foreach {$_.name -replace " *",""}
foreach ($strComputer in $LC){

#region Life check Computer
$Alive="";$Comp = "";$NoAccess = "";$ServerRPCUnavailable = "";$shares =""
$Alive = Ping $strComputer
if ($Alive -eq "True"){Write-Output "Scanning $strComputer"

#region Computer Information

#region Access check to the computer
Trap {"WMI Error Access check $strComputer"; Continue}
$Comp = Get-WmiObject -Class "Win32_computersystem" -ComputerName $strComputer -ErrorAction SilentlyContinue

if ($Comp -eq ""){"NoAccess $strComputer";$AllNoAccess += $NoAccess | % {$_ | select @{e={$strComputer};n='Computer'}}}
if ($Comp -eq $Null){"ServerRPCUnavailable $strComputer";$AllServerRPCUnavailable += $ServerRPCUnavailable | % {$_ | select @{e={$strComputer};n='Computer'}}}
if ($Comp.Caption.Length -gt 1) {

#region Share Information
Trap {"WMI Error Share Name $strComputer"; Continue}
$shares = Get-WmiObject Win32_Share -ComputerName $strComputer -filter 'type=0' -ErrorAction SilentlyContinue

foreach($share in $shares) {
$shareSec ="";$sd = "";$NOPermissions = @();$ShareInfo = @()

Trap {"WMI Error Share Security Setting $strComputer";Continue}
$shareSec = Get-WmiObject Win32_LogicalShareSecuritySetting -ComputerName $strComputer -filter "name='$($share.name)'" -ErrorAction SilentlyContinue

if ($shareSec) {$sd = $sharesec.GetSecurityDescriptor();$DACL = $SD.Descriptor

#region There are No Permissions
if ($DACL.DACL -eq $Null){
$NOPermissions += $DACL |% {
$_ | select @{e={$strComputer};n='Computer'},
@{e={$share.name};n='ShareName'},
@{e={$DACL.DACL};n='DACL'}
}
foreach($NOPermission in $NOPermissions){if ($NOPermission.DACL -eq $Null){$NOPermission.DACL = "NO Permissions"}}
$AllNOPermissions += $NOPermissions
}
#endregion There are No Permissions

$ShareInfo += $DACL.DACL |% {
$_ | select @{e={$comp.Name};n='Computer'},
@{e={$comp.UserName};n='Login'},
@{e={$share.name};n='ShareName'},
@{e={$share.Path};n='PathShare'},
AccessMask,
@{e={$_.trustee.Name};n='User'},
@{e={$_.trustee.Domain};n='Domain'},
@{e={$_.trustee.SIDString};n='SID'}
}
foreach($Info in $ShareInfo){
if ($Info.Login -eq $null){$Info.Login = "Emply"}
if ($Info.AccessMask -eq "1179817"){$Info.AccessMask = "ReadAndExecute"}
if ($Info.AccessMask -eq "1245631"){$Info.AccessMask = "Modify"}
if ($Info.AccessMask -eq "2032127"){$Info.AccessMask = "FullControl"}
if ($Info.User -eq $Null){$Info.User = "DEAD"}
if ($Info.Domain -eq $Null){$Info.Domain = "Emply"}
}
$AllComputerInfo += $ShareInfo
}
}
#endregion Share Information
}
#endregion Access check to the computer
#endregion Computer Information
}
#endregion Life check Computer
}
#endregion The List Active Directory Computers

#endregion  Collection of the Information on the Computer

#region Save to File
$AllComputerInfo | export-csv -Encoding OEM -Path $LogADComputerInfo -NoTypeInformation
$AllNOPermissions | export-csv -Encoding OEM -Path $LogNOPermissions -NoTypeInformation
$AllServerRPCUnavailable | export-csv -Encoding OEM -Path $LogRPCUnavailable -NoTypeInformation
$AllNoAccess | export-csv -Encoding OEM -Path $LogNoAccess -NoTypeInformation
#endregion Save to File

Скачать FindLanShares.ps1

Создайте бесплатный сайт или блог на WordPress.com.