Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Извлечь данные в виде таблицы(+возможность сортировки) с журнала Security. (http://forum.oszone.net/showthread.php?t=340516)

rango13 14-05-2019 06:03 2871551

Извлечь данные в виде таблицы(+возможность сортировки) с журнала Security.
 
Всем привет!

Есть события под номером 4624 в журнале MS Windows "Безопасность"/(Security) на сервере MS Windows 2012r2 Std:

Код:

Вход с учетной записью выполнен успешно.

Субъект:
        ИД безопасности:                СИСТЕМА
        Имя учетной записи:                SRV01$
        Домен учетной записи:                NI
        Код входа:                0x3E7

Тип входа:                        10

Уровень олицетворения:                Олицетворение

Новый вход:
        ИД безопасности:                SRV01\user23
        Имя учетной записи:                user23
        Домен учетной записи:                SRV01
        Код входа:                0x5D9928C
        GUID входа:                {00000000-0000-0000-0000-000000000000}

Сведения о процессе:
        Идентификатор процесса:                0x1ad4
        Имя процесса:                C:\Windows\System32\winlogon.exe

Сведения о сети:
        Имя рабочей станции:        SRV01
        Сетевой адрес источника:        91.153.145.182
        Порт источника:                0

Сведения о проверке подлинности:
        Процесс входа:                User32
        Пакет проверки подлинности:        Negotiate
        Промежуточные службы:        -
        Имя пакета (только NTLM):        -
        Длина ключа:                0



Необходимо из них извлечь в виде таблицы данные:
  • Имя учетной записи
  • Сетевой адрес источника
  • Время регистрации самого события

Написал команду извлечения события и занесения их в массив $Events:
Код:

$Events = Get-WinEvent Security -FilterXPath "*[System[EventID=4624] and EventData[Data[@Name='LogonType']=10]]"
В виде таблицы её можно просмотреть через команду:
Код:

$Events  | Select-Object * | Out-GridView

Но вопрос в том, как мне распарсить содержимое события и отобразить в таблице только необходимые три поля, о которых я писал выше?

rango13 14-05-2019 07:09 2871553

Ответ нашёл

Код:

$Events = Get-WinEvent Security -FilterXPath "*[System[EventID=4624] and EventData[Data[@Name='LogonType']=10]]"
$Report = @()
$i = 0
ForEach ($Event in $Events)
    {
        $eventXML = [xml]$Event.ToXml()
        $obj = New-Object System.Management.Automation.PSObject       
        $obj | Add-Member Noteproperty -Name $eventXML.Event.EventData.Data[5].name -Value $eventXML.Event.EventData.Data[5].'#text'
        $obj | Add-Member Noteproperty -Name $eventXML.Event.EventData.Data[18].name -Value $eventXML.Event.EventData.Data[18].'#text'
        $obj | Add-Member Noteproperty -Name "TimeCreated" -Value $Events[$i].TimeCreated
        $i++
        $Report += $obj
    }       

$Report | Select-Object * | Out-GridView



Остался вопрос: что-то можно оптимизировать в этом скрипте? Так сказать, сделать по-правильному? Изучаю PS-скрипты, интересны советы по их оптимизации.

YuS_2 14-05-2019 08:25 2871564

Цитата:

Цитата rango13
Изучаю PS-скрипты, интересны советы по их оптимизации. »

Если говорить об изучении, то... есть такой скрипт, который из логов выковыривает дополнительные элементы:
сырой, но рабочий набросок
Код:

# Идея: https://blogs.technet.microsoft.com/ashleymcglone/2013/08/28/powershell-get-winevent-xml-madness-getting-details-from-event-logs/
#requires -v 5.0
#requires -runas
<#
Version 2.0.1.000
Date 27.02.19
Добавлены все параметры командлета get-winevent
Переработаны фильтры
Добавлен ключ -data, без него не будет вывода дополнительной информации из узлов DATA из отобранных событий, т.е. скрипт работает в режиме автоматизации сборки фильтра событий и только.
---
Version 2.0.1.005
Date 27.02.2019
изменение типа данных ввода учетной записи
Поправлены старые баги...
Добавлены новые... :)


 Все значения, заданные в параметрах, приведены для примера, их лучше удалить и задавать в параметрах скрипта
 Примеры использования:
 .\script.ps1 'Microsoft-Windows-Diagnostics-Performance/Operational' '^(boottime|start|bootstart|bootend)' -max 50 -eventid 100,103 -data
 .\script.ps1 'Microsoft-Windows-Diagnostics-Performance/Operational' '^(boottime|start|bootstart|bootend)' -max 50 -eventid 100 -data|ft
 .\script.ps1 'Microsoft-Windows-Diagnostics-Performance/Operational' '.' -max 50 -eventid 100,103 -data|out-gridview
 .\script.ps1|out-gridview
 .\script.ps1

Level
0 - всегда записывать;
1 - Критический;
2 - Ошибка;
3 - Предупреждение;
4 - Сведения;
5 - Подробности (Verbose).
#>

[cmdletbinding()]
param (
        [string]$computername, # Имя компьютера с которого получаем данные журналов
        $credential, # Ввод учетных данных
        [string[]]$logname, #= "Microsoft-Windows-Diagnostics-Performance/Operational", # Наименование лога (пути с именем журнала)
        [string[]]$listlog, # Получение списка указанных журналов событий, все журналы - *
        [string[]]$listprovider, # Получение списка указанных поставщиков
        [int64]$maxevents, #= 30, # Число событий для отчета
        [switch]$force, #  Дополнительное получение аналитических и отладочных журналов, если используются символы подстановки
        [switch]$oldest, # Формирование списка от наиболее старого к новому
        [string[]]$path, # Путь к указаннылм файлам логов, поддерживаются .evt, .evtx, .etl расширения
        [string[]]$providername, # Получение событий, записанных указанными поставщиками (поддерживаются подстановочные знаки)
        [string]$arguments = '.', #'^(boottime|start|bootstart|bootend)', # Шаблон для отбора элементов из узлов EventData
        [int[]]$level, #= (4), # Уровни для отбора событий
        [int[]]$eventid, #= (100,103,108) # ID событий для отбора
        [switch]$data #= $true # Переключатель для получения дополнительных данных из узлов Data в отобранных событиях
)

# Формируем простой фильтр XPath, если указаны $level или $eventid
function map_prefix ($prefix, $var){
        if ($var){
                '('+ (($var|%{"{0}{1}" -f $prefix,"$_"}) -join ' or ') + ')'
        }
}

$levels = map_prefix 'Level=' $level
$eventids = map_prefix 'EventID=' $eventid

$arr = $eventids,$levels
if ($arr -ne $null) {$flt = "*[System[$(($arr -ne $null) -join ' and ')]]"}

# Формируем строку параметров командлета
$pars = @{}
if($computername){$pars.computername="$computername"}
if($logname){$pars.logname="$logname"}
if($computername -and $credential){$pars.credential = Get-Credential -cred $credential}
if($listlog){$pars.listlog=$listlog}
if($listprovider){$pars.listprovider=$listprovider}
if($maxevents){$pars.maxevents=$maxevents}
if($oldest){$pars.oldest=$true}
if($force){$pars.force=$true}
if($path){$pars.path=$path}
if($providername){$pars.providername=$providername}
if($flt){$pars.filterxpath="$flt"}


if ($data){
        # Получаем результат работы командлета
        $events = get-winevent @pars
        # Фильтр элементов в событиях по шаблону
        $elname = ([xml[]]$events.toxml()).event.eventdata.data.name
        $sel = if (($a = $elname -match $arguments) -eq $true){$elname} else {$a|sort -uni}
       
        $z=-1
        # Добавляем свойства к объектам
        foreach ($event in $events){
                $xml = [xml]$event.toxml()
                if ($xml.event.eventdata.data.count){
                        for ($i=0;$i -lt $xml.event.eventdata.data.count;$i++){
                                if($xml.event.eventdata.data[$i].name){
                                        $name = $xml.event.eventdata.data[$i].name
                                        $val = $xml.event.eventdata.data[$i].'#text'
                                } else {
                                        $name = 'Data' + "$i"
                                        if ($i -gt $z) {[array]$darr += $name;$z = $i}
                                        $val = $xml.event.eventdata.data[$i]
                                }
                                $val = if([datetime]::tryparse($val,[ref](get-date))){get-date $val} else {$val}
                                add-member -inp $event -mem noteproperty -force -name $name -val $val
                        }
                }
        }

        # Формируем строку отбираемых свойств
        $head = 'timecreated','id','level','leveldisplayname'
        if($darr){
                # Фильтруем созданные свойства DataN, у которых не было аргументов
                $fdarr = if(($b = $darr -match $arguments) -eq $true){$darr} else {$b}
                if ($sel){
                        $sel = $head + $fdarr + $sel + '*'
                } else {$sel = $head + $fdarr + '*' }
        } elseif ($sel) {
                $sel = $head + $sel + '*'
        } else {$sel = $head + '*'}
       
        # Выводим результат
        $obj = try {$events|select $sel -ea 0} catch {continue}
        $obj|select *
} else {
        get-winevent @pars
}


Iska 14-05-2019 17:47 2871688

Цитата:

Цитата rango13
Остался вопрос: что-то можно оптимизировать в этом скрипте? »

Разве что сократить число обращений через «.». Например, можно задавать некую промежуточную переменную:
Код:

        …
        $oEventData = $eventXML.Event.EventData
        $obj | Add-Member Noteproperty -Name $oEventData.Data[5].name -Value $oEventData.Data[5].'#text'
        $obj | Add-Member Noteproperty -Name $oEventData.Data[18].name -Value $oEventData.Data[18].'#text'
        $obj | Add-Member Noteproperty -Name "TimeCreated" -Value $Events[$i].TimeCreated
        …



Время: 08:15.

Время: 08:15.
© OSzone.net 2001-