PDA

Показать полную графическую версию : Как отфильтровать вывод скрипта, удалив из него строки с подстрокой


Страниц : [1] 2

rises
23-04-2020, 11:13
Всем доброе время.

Нашел в сети powershell скрипт и допилил его под себя. (для русской Windows Server)
Он на windows Server (2016) читает лог успешных попыток входа и выводит их за определенное время.

Выводит он что-то типа такого:

TimeGenerated ClientIP Username LogType
------------- -------- -------- -------
23.04.2020 10:45:33 - -\СИСТЕМА Service
23.04.2020 10:41:44 - -\СИСТЕМА Service
23.04.2020 10:41:44 - -\СИСТЕМА Service
23.04.2020 10:35:26 192.168.0.66 MAINS\acidс RDP
23.04.2020 10:35:26 192.168.0.66 MAINS\acidс RDP
23.04.2020 10:35:25 - -\DWM-16 Interactive - local logon

Можно ли как-то куда-то перенаправить вывод, чтобы отфильтровать строки, содержащие "-\СИСТЕМА"?

Чтобы остались только:

23.04.2020 10:35:26 192.168.0.66 MAINS\acidс RDP
23.04.2020 10:35:25 - -\DWM-16 Interactive - local logon


Get-EventLog -LogName Security -after ((Get-date).AddMinutes(-200))| ?{(4624) -contains $_.EventID -and $_.Message -match ‘Тип входа:’}| %{
#rdp - 10, без него будет выводить все логины match 'Тип входа:\s+(10)\s'
(new-object -Type PSObject -Property @{
TimeGenerated = $_.TimeGenerated
ClientIP = $_.Message -replace '(?smi).*Сетевой адрес источника:\s+([^\s]+)\s+.*','$1'
UserName =(([regex]'(?<=Новый вход:.*[\s\S]*.*записи:.\s)([\s\S]*)(?=\s\n.*Домен)').match($_.message).value)
UserDomain = $_.Message -replace '(?smi).*Имя рабочей станции:\s+([^\s]+)\s+.*','$1'
LogonType = $_.Message -replace '(?smi).*Тип входа:\s+([^\s]+)\s+.*','$1'
})
} | sort TimeGenerated -Descending | Select TimeGenerated, ClientIP `
, @{N='Username';E={'{0}\{1}' -f $_.UserDomain,$_.UserName}} `
, @{N='LogType';E={
switch ($_.LogonType) {
2 {'Interactive - local logon'}
3 {'Network conection to shared folder)'}
4 {'Batch'}
5 {'Service'}
7 {'Unlock (after screensaver)'}
8 {'NetworkCleartext'}
9 {'NewCredentials (local impersonation process under existing connection)'}
10 {'RDP'}
11 {'CachedInteractive'}
default {"LogType Not Recognised: $($_.LogonType)"}
}
}}

Sham
23-04-2020, 12:26
перед sort where {$_.UserDomain -ne '-' -and $_.UserName.tolower() -ne 'система'} |

rises
23-04-2020, 13:29
Эта комманда удаляет все, где есть -.

Удаляет и такие строки: 23.04.2020 11:48:34 202.137.7.58 -\АНОНИМНЫЙ ВХОД Network conection to shared folder
23.04.2020 10:35:25 - -\DWM-16 Interactive - local logon

Ура! Я понял принцип...

Вот так работает! where UserName -ne 'СИСТЕМА'

Thanks!

rises
23-04-2020, 16:02
Подскажите еще pls, можно как-то в выводе этом не выводить первые строчки?
Выводить данные, но не выводить их описание?

TimeGenerated ClientIP Username LogType
------------- -------- -------- -------

rises
23-04-2020, 17:11
Наковырял такой способ:

ConvertTo-Csv -NoType | Select-Object -Skip 1

Получаем что-то типа:

"23.04.2020 16:56:54","202.166.174.27","-\АНОНИМНЫЙ ВХОД","Network conection to shared folder"
"23.04.2020 16:56:54","202.166.174.27","-\АНОНИМНЫЙ ВХОД","Network conection to shared folder"

Только кавычки теперь глаза мозолят, можно как-то кавычки все убрать? :)

Sham
23-04-2020, 17:27
Format-Table -HideTableHeaders можно

rises
23-04-2020, 17:35
Ура! Получилось то, что нужно может кому пригодится.

На Windows Server запускается этот скрипт каждый час и пишет в лог за последний час успешные входы в систему, с какого IP кто именно, какой тип соединения. Соотвественно имеем лог входов в систему.
Get-EventLog -LogName Security -after ((Get-date).AddMinutes(-60))| ?{(4624) -contains $_.EventID -and $_.Message -match ‘Тип входа:’}| %{
#rdp - 10, без него будет выводить все логины match 'Тип входа:\s+(10)\s'
(new-object -Type PSObject -Property @{
TimeGenerated = $_.TimeGenerated
ClientIP = $_.Message -replace '(?smi).*Сетевой адрес источника:\s+([^\s]+)\s+.*','$1'
UserName =(([regex]'(?<=Новый вход:.*[\s\S]*.*записи:.\s)([\s\S]*)(?=\s\n.*Домен)').match($_.message).value)
UserDomain = $_.Message -replace '(?smi).*Имя рабочей станции:\s+([^\s]+)\s+.*','$1'
LogonType = $_.Message -replace '(?smi).*Тип входа:\s+([^\s]+)\s+.*','$1'
})
} | where ClientIP -ne '-' | sort TimeGenerated -Descending | Select TimeGenerated, ClientIP `
, @{N='Username';E={'{0}\{1}' -f $_.UserDomain,$_.UserName}} `
, @{N='LogType';E={
switch ($_.LogonType) {
2 {'Interactive = local logon'}
3 {'Network conection to shared folder'}
4 {'Batch'}
5 {'Service'}
7 {'Unlock (after screensaver)'}
8 {'NetworkCleartext'}
9 {'NewCredentials (local impersonation process under existing connection)'}
10 {'RDP'}
11 {'CachedInteractive'}
default {"LogType Not Recognised: $($_.LogonType)"}
}
}} | ConvertTo-Csv -NoType | Select-Object -Skip 1 | % {$_ -replace '"',''} >> C:\logs\logons\logon.txt


Format-Table -HideTableHeaders можно »

Блин, спасибо, так тоже выглядит зачетно. :)

Iska
23-04-2020, 19:43
запускается этот скрипт каждый час и пишет в лог за последний час успешные входы в систему, с какого IP кто именно, какой тип соединения. Соотвественно имеем лог входов в систему. »
Вот только пропускать будете или дублировать записи. Надо не (Get-date).AddMinutes(-60), а хотя бы надо хранить время последнего запроса и использовать его.

rises
24-04-2020, 07:41
Вот только пропускать будете или дублировать записи. Надо не (Get-date).AddMinutes(-60), а хотя бы надо хранить время последнего запроса и использовать его. »

Потеряться точно ничего не потеряется, запускается скрипт ровно в 8:00:00, это значит, что он возьмет информацию с 7:00:00 до того, что появится в базе, если он выполняется скажем 15 секунд, то продублироваться могут пару записей за эти 15 секунд, пара избыточных записей мне погоды не сделает, а вот теряться они тут не будут, так как информация берется четко за 1 час.
Посмотрел логи - ни одной дублирующей записи пока не нашел, понаблюдаю дальше.

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

Есть ли такая функция как в unix подобных системах? Чтобы не затрачивать время на чтение всего файла, скажем который вырастет до 50Мб, и добавит время работы скрипта?

Вот такой строчкой скажем сейчас заканчивается файл.
24.04.2020 4:15:10,201.216.208.137,-\АНОНИМНЫЙ ВХОД,Network conection to shared folder

Кстати сделано это все для отслеживания левых подключений, пытаюсь понять, что это за левые Анонимные входы с левых IP.

Хотя придумал простой способ, нужно брать время последнего изменения файла и стартовать от него.

Скрипт запустился в 5:00
Закончил работу в 24 ‎апреля ‎2020 ‎г., ‏‎5:00:23 по времени изменения файла.
Берем это время и старт от него, будет точнее.

rises
24-04-2020, 08:08
Что-то типа такого(файл должен существовать, если это первый запуск, можно создать пустой, лом добавлять это):

$file = Get-Item 'C:\logs\logons\logon.txt'

Get-EventLog -LogName Security -after $file.LastWriteTime | ?{(4624) -contains $_.EventID -and $_.Message -match ‘Тип входа:’}| %{
#rdp - 10, без него будет выводить все логины match 'Тип входа:\s+(10)\s'
(new-object -Type PSObject -Property @{
TimeGenerated = $_.TimeGenerated
ClientIP = $_.Message -replace '(?smi).*Сетевой адрес источника:\s+([^\s]+)\s+.*','$1'
UserName =(([regex]'(?<=Новый вход:.*[\s\S]*.*записи:.\s)([\s\S]*)(?=\s\n.*Домен)').match($_.message).value)
UserDomain = $_.Message -replace '(?smi).*Имя рабочей станции:\s+([^\s]+)\s+.*','$1'
LogonType = $_.Message -replace '(?smi).*Тип входа:\s+([^\s]+)\s+.*','$1'
})
} | where ClientIP -ne '-' | sort TimeGenerated -Descending | Select TimeGenerated, ClientIP `
, @{N='Username';E={'{0}\{1}' -f $_.UserDomain,$_.UserName}} `
, @{N='LogType';E={
switch ($_.LogonType) {
2 {'Interactive = local logon'}
3 {'Network conection to shared folder'}
4 {'Batch'}
5 {'Service'}
7 {'Unlock (after screensaver)'}
8 {'NetworkCleartext'}
9 {'NewCredentials (local impersonation process under existing connection)'}
10 {'RDP'}
11 {'CachedInteractive'}
default {"LogType Not Recognised: $($_.LogonType)"}
}
}} | ConvertTo-Csv -NoType | Select-Object -Skip 1 | % {$_ -replace '"',''} >> C:\logs\logons\logon.txt
#}} | Format-Table -HideTableHeaders >> C:\logs\logons\logon.txt

Iska
24-04-2020, 12:20
rises, по поводу «Такого не может быть, потому что такого не может быть никогда» — оставлю на Вашей совести. Это… такое себе… Как показывает практика, то, что может произойти — рано или поздно, но происходит.

нужно хранить это время в файлике »
Или в реестре. Но лучше вообще поменять парадигму (см. ниже).

Или читать последнюю строчку лог файла и брать из нее время.
Есть ли такая функция как в unix подобных системах? Чтобы не затрачивать время на чтение всего файла, скажем который вырастет до 50Мб, и добавит время работы скрипта? »
Писать лучше всего не в текстовый файл, а в базу данных, пусть даже в mdb. Поскольку содержимым базы данных легко манипулировать — и запросы произвольные к ней составлять, и время последней записи получать и прочая, и прочая…

rises
24-04-2020, 13:10
Я согласен, что можно сделать красиво, но лично для моих целей этого достаточно. Благодаря этому логу я наглядно вижу, что попытки анонимного доступа прекращены и бонусом к этому я имею себе лог файл времени и источника входа пользователей на сервер. Можно допилить и сделать качественный и правильный продукт, но тут уже вопрос цель/средство. Может быть кто-то допилит этот скрипт и сделает что-то более красивое и правильное. ;-)

Sham
24-04-2020, 14:06
все данные можно взять из массива строк ReplacementStrings (https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.eventlogentry.replacementstrings?view=netframework-4.8#System_Diagnostics_EventLogEntry_ReplacementStrings), и желательно не лезть в Message c тяжёлыми регулярками.

Sham
24-04-2020, 20:13
структура ReplacementStrings привязана к eventid, поэтому идея такая
$eventid = 4624
$logontypes = @{
2 = 'Interactive - local logon';
3 = 'Network conection to shared folder)';
4 = 'Batch';
5 = 'Service';
7 = 'Unlock (after screensaver)';
8 = 'NetworkCleartext';
9 = 'NewCredentials (local impersonation process under existing connection)';
10 = 'RDP';
11 = 'CachedInteractive'
}

get-eventlog -LogName Security -InstanceId $eventid -after (get-date).AddMinutes(-1000) |
select TimeGenerated, ReplacementStrings |
where {$arr = $_.ReplacementStrings; $arr[18] -ne '-'} | #IP
foreach {
$ip = $arr[18]
$domain_name = $arr[5] + @('', ('\' + $arr[11]))[[bool]$arr[11]]
$logontype = $arr[8] + ':' + $logontypes[[int]$arr[8]]

$_.TimeGenerated, $ip, $domain_name, $logontype -join '; '
}

rises
26-04-2020, 16:34
Sham, крутецкая тема, спасибо, может кому еще сгодится. :-)

rises
26-04-2020, 21:20
Вот такой код оставил, крутится нормально. Запускается шедулером через каждые пол часа.
Берет время изменения файла и от него выводит лог.


$file = Get-Item 'C:\logs\logons\logon.txt'

$eventid = 4624
$logontypes = @{
2 = 'Interactive - local logon';
3 = 'Network conection to shared folder)';
4 = 'Batch';
5 = 'Service';
7 = 'Unlock (after screensaver)';
8 = 'NetworkCleartext';
9 = 'NewCredentials (local impersonation process under existing connection)';
10 = 'RDP';
11 = 'CachedInteractive'
}

get-eventlog -LogName Security -InstanceId $eventid -after ($file.LastWriteTime) |
select TimeGenerated, ReplacementStrings |
where {$arr = $_.ReplacementStrings; $arr[18] -ne '-'} | #IP
foreach {
$ip = $arr[18]
$domain_name = $arr[5] + @('', ('\' + $arr[11]))[[bool]$arr[11]]
$logontype = $arr[8] + ':' + $logontypes[[int]$arr[8]]

$_.TimeGenerated, $ip, $domain_name, $logontype -join '; '
} >> C:\logs\logons\logon.txt

rises
07-05-2020, 22:24
Кстати заметил, что скрипт немного несвязно выводит даты, можно как-то вывод упорядочить по дате и времени?
Выводит как-то так:

07.05.2020 14:36:44; 192.168.0.249; АНОНИМНЫЙ ВХОД\JUL; 3:Network conection to shared folder)
07.05.2020 15:30:01; 192.168.0.249; АНОНИМНЫЙ ВХОД\JUL; 3:Network conection to shared folder)
07.05.2020 15:25:21; 192.168.0.249; АНОНИМНЫЙ ВХОД\JUL; 3:Network conection to shared folder)

Foreigner
08-05-2020, 00:03
можно как-то вывод упорядочить по дате и времени? »


....|
select TimeGenerated, ReplacementStrings | sort TimeGenerated |
where....

rises
08-05-2020, 14:05
Foreigner, спасибо, вроде бы едет.

overrise
16-05-2020, 19:56
А можно как-то добавить сюда не только логин, но и дисконнект?
Если добавить событие $eventid = 4624,4779, то он пишет в лог IP адрес, но не пишет имени пользователя, можно это как-то подправить?

Тогда лог будет более полноценным и на коннект и на дисконнект?

Пишет на дисконнект так:
16.05.2020 19:30:00; 192.168.20.74; serg\FILESERVER; 10:RDP
16.05.2020 19:40:16; ; 192.168.20.74; :
16.05.2020 19:40:21; 192.168.20.74; serg\LAPTOP; 3:Network conection to shared folder




© OSzone.net 2001-2012