-ѕоиск по дневнику

ѕоиск сообщений в predefglas

 -ѕодписка по e-mail

 

 -—татистика

—татистика LiveInternet.ru: показано количество хитов и посетителей
—оздан: 10.12.2014
«аписей:
 омментариев:
Ќаписано: 94

ƒерево процессов

ƒневник

—уббота, 04 »юн€ 2016 г. 19:39 + в цитатник
¬ывод комадлета Get-Process дл€ воспри€ти€ не слишком удобен Ч просто список, в котором данные ко всему прочему отражены в стиле стран ближнего востока, то бишь справа налево, подаетс€ Microsoft как идеолгоически верный путь к пониманию сути того, что творитс€ в процессах. –ечь не о том как с помощью PowerShell палить вирусы, а об отсутствии визуального представлени€ какой процесс какого ≈рофеича родил, чай, ведь уже п€та€ верси€ PowerShell'а, а древовидного представлени€ по-прежнему нема, да и в ближайшей перспективе, должно быть, не предвидетс€. » здесь из зрительного зала раздаетс€: Ђј нафига нам древовидное представление процессов в PowerShell, когда есть ProcessExplorer, на худой конец Ч pslist?ї ¬о-первых, GUI дл€ консольщика как серпом по €йцам, во-вторых, какой резон разводить зоопарк из набора сторонних утилит, когда наличие PowerShell по сути €вл€етс€ синонимом Ђуже все естьї? Ч остаетс€ лишь творить под цвет своих фломастеров. ѕреамбула приобретает некий сюрреалистический оттенок, да и рискует зат€нутьс€, если продолжать в том же роде, так что готовим фломастерыЕ —юрприз! ≈сли кто-то из читающих раскатал губу на WMI, то может смело закатывать ее фломастером обратно, ибо речь оп€ть-таки пойдет о рефлексии, точнее не столько о ней самой, сколько о достижении цели через нее.  удр€во сказано, но да ладно.  ак подсказывает  эп, дл€ построени€ дерева процессов нужно знать такие параметры, как им€ процесса, его PID, а также PPID. ѕоследний служит отправной точной при определении отпрыска от родител€, причем получить оный в Windows можно как миниму трем€ приемами дзюдо: счетчики производительности, WMI и NtQuerySystemInformation. ѕервый (ровно как и второй) идет лесом, так как в грубом приближении €вл€етс€ оберткой над NtQuerySystemInformation, токмо с тормозами в придачу Ч показатель варьируетс€ от начинки ѕ , но это тема отдельного разговора. ќткрываем Vim (или что у кого там любимое) и пишем: Set-Variable ($$ = [Regex].Assembly.GetType( 'Microsoft.Win32.NativeMethods' ).GetMethod('NtQuerySystemInformation')).Name $$ »так, мы определили переменую $NtQuerySystemInformation. “еперь нужно получить указатель на структуру SYSTEM_PROCESS_INFORMATION, в Win7 x86 выгл€д€щую так: +0x000 NextEntryOffset : Uint4B +0x004 NumberOfThreads : Uint4B +0x008 WorkingSetPrivateSize : _LARGE_INTEGER +0x010 HardFaultCount : Uint4B +0x014 NumberOfThreadsHighWatermark : Uint4B +0x018 CycleTime : Uint8B +0x020 CreateTime : _LARGE_INTEGER +0x028 UserTime : _LARGE_INTEGER +0x030 KernelTime : _LARGE_INTEGER +0x038 ImageName : _UNICODE_STRING +0x040 BasePriority : Int4B +0x044 UniqueProcessId : Ptr32 Void +0x048 InheritedFromUniqueProcessId : Ptr32 Void +0x04c HandleCount : Uint4B +0x050 SessionId : Uint4B +0x054 UniqueProcessKey : Uint4B +0x058 PeakVirtualSize : Uint4B +0x05c VirtualSize : Uint4B +0x060 PageFaultCount : Uint4B +0x064 PeakWorkingSetSize : Uint4B +0x068 WorkingSetSize : Uint4B +0x06c QuotaPeakPagedPoolUsage : Uint4B +0x070 QuotaPagedPoolUsage : Uint4B +0x074 QuotaPeakNonPagedPoolUsage : Uint4B +0x078 QuotaNonPagedPoolUsage : Uint4B +0x07c PagefileUsage : Uint4B +0x080 PeakPagefileUsage : Uint4B +0x084 PrivatePageCount : Uint4B +0x088 ReadOperationCount : _LARGE_INTEGER +0x090 WriteOperationCount : _LARGE_INTEGER +0x098 OtherOperationCount : _LARGE_INTEGER +0x0a0 ReadTransferCount : _LARGE_INTEGER +0x0a8 WriteTransferCount : _LARGE_INTEGER +0x0b0 OtherTransferCount : _LARGE_INTEGER ѕричем из всей структуры нас интересуют такие пол€ как NextEntryOffset, ImageName, UniqueProcessId и InheritedFromUniqueProcessId, так что дл€ получени€ только этих четырех полей определ€ть структуру в домене приложений слишком жирно Ч воспользуемс€ методами типа Marshal. ѕолучаем указатель: if (($ta = [PSObject].Assembly.GetType( 'System.Management.Automation.TypeAccelerators' ))::Get.Keys -notcontains 'Marshal') { $ta::Add('Marshal', [Runtime.InteropServices.Marshal]) } $ret = 0 try { #задаем размер буфера минимальным значением $ptr = [Marshal]::AllocHGlobal(1024) if ($NtQuerySystemInformation.Invoke($null, ( $par = [Object[]]@(5, $ptr, 1024, $ret) )) -eq 0xC0000004) { #STATUS_INFO_LENGTH_MISMATCH $ptr = [Marshal]::ReAllocHGlobal($ptr, [IntPtr]$par[3]) if ($NtQuerySystemInformation.Invoke($null, ( $par = [Object[]]@(5, $ptr, $par[3], 0) )) -ne 0) { throw New-Object InvalidOperationException('„то-то пошло не так...') } } } catch { $_.Exception } finally { if ($ptr -ne $null) { [Marshal]::FreeHGlobal($ptr) } } ”казатель получили, читаем данные. —топ! ј ведь ImageName Ч это структура UNICODE_STRING, как быть? ƒелаем ход конем: $UNICODE_STRING = [Activator]::CreateInstance( [Object].Assembly.GetType( 'Microsoft.Win32.Win32Native+UNICODE_STRING' ) ) ¬от теперь мы во всеоружии и готовы Ђчитатьї указатель. $len = [Marshal]::SizeOf($UNICODE_STRING) - 1 $tmp = $ptr $Processes = while (($$ = [Marshal]::ReadInt32($tmp))) #NextEntryOffset [Byte[]]$bytes = 0..$len{ [Marshal]::ReadByte($tmp, $ofb) $ofb++ } #конвертируем байты в UNICODE_STRING $gch = [Runtime.InteropServices.GCHandle]::Alloc($bytes, 'Pinned') $uni = [Marshal]::PtrToStructure( $gch.AddrOfPinnedObject(), [Type]$UNICODE_STRING.GetType() ) $gch.Free() New-Object PSObject -Property @{ ProcessName = if ([String]::IsNullOrEmpty(( $proc = $uni.GetType().GetField( 'Buffer', [Reflection.BindingFlags]36 ).GetValue($uni)) )) { 'Idle' } else { $proc } PID = [Marshal]::ReadInt32($tmp, 0x44) PPID = [Marshal]::ReadInt32($tmp, 0x48) } $tmp = [IntPtr]($tmp.ToInt32() + $$) } ѕеременна€ $Processes отныне хранит массив объектов PSObject, эдакие контейнеры дл€ нужных нам данных. “еперь, согласно женевской конвенции, остаетс€ построить само дерево. function Get-ProcessChild { param( > ѕосле запуска получим в хосте древовидное представление процессов. —обственно, на этом вечерний эротический сеанс показ окончен, можно расходитьс€. ѕолный код#function Get-ProcessTree { <# .NOTES ¬место методов расширений .Where и .ForEach используютс€ одноименные командлеты в цел€х совместимости с PS -lt v5 #> begin { Set-Variable ($$ = [Regex].Assembly.GetType( 'Microsoft.Win32.NativeMethods' ).GetMethod('NtQuerySystemInformation')).Name $$ $UNICODE_STRING = [Activator]::CreateInstance( [Object].Assembly.GetType( 'Microsoft.Win32.Win32Native+UNICODE_STRING' ) ) function Get-ProcessChild { param( System.Management.Automation.TypeAccelerators' ))::Get.Keys -notcontains 'Marshal') { $ta::Add('Marshal', [Runtime.InteropServices.Marshal]) } } process { try { $ret = 0 $ptr = [Marshal]::AllocHGlobal(1024) if ($NtQuerySystemInformation.Invoke($null, ( $par = [Object[]]@(5, $ptr, 1024, $ret) )) -eq 0xC0000004) { #STATUS_INFO_LENGTH_MISMATCH $ptr = [Marshal]::ReAllocHGlobal($ptr, [IntPtr]$par[3]) if (($nts = $NtQuerySystemInformation.Invoke($null, ( $par = [Object[]]@(5, $ptr, $par[3], 0) ))) -ne 0) { throw New-Object InvalidOperationException( 'NTSTATUS: 0x{0:X}' -f $nts ) } } $len = [Marshal]::SizeOf($UNICODE_STRING) - 1 $tmp = $ptr $Processes = while (($$ = [Marshal]::ReadInt32($tmp))) ForEach-Object $ofb = 0x38{ [Marshal]::ReadByte($tmp, $ofb) $ofb++ } $gch = [Runtime.InteropServices.GCHandle]::Alloc($bytes, 'Pinned') $uni = [Marshal]::PtrToStructure( $gch.AddrOfPinnedObject(), [Type]$UNICODE_STRING.GetType() ) $gch.Free() New-Object PSObject -Property @{ ProcessName = if ([String]::IsNullOrEmpty(( $proc = $uni.GetType().GetField( 'Buffer', [Reflection.BindingFlags]36 ).GetValue($uni)) )) { 'Idle' } else { $proc } PID = [Marshal]::ReadInt32($tmp, 0x44) PPID = [Marshal]::ReadInt32($tmp, 0x48) } $tmp = [IntPtr]($tmp.ToInt32() + $$) } } catch { $_.Exception } finally { if ($ptr -ne $null) { [Marshal]::FreeHGlobal($ptr) } } } end { if ($Processes -eq $null) { break } $Processes | Where-Object { -not (Get-Process -Id $_.PPID -ea 0) -or $_.PPID -eq 0 } | ForEach-Object { "$($_.ProcessName) ($($_.PID))" Get-ProcessChild $_ } [void]$ta::Remove('Marshal') } #}

ћетки:  

 —траницы: [1]