usr/Get-SysModules.ps1
using namespace System.Runtime.InteropServices function Get-SysModules { [CmdletBinding()]param() begin { New-Delegate ntdll { int NtQuerySystemInformation([uint, ptr, uint, buf]) } New-Structure RTL_PROCESS_MODULE_INFORMATION { IntPtr Section IntPtr MappedBase IntPtr ImageBase UInt32 ImageSize UInt32 Flags UInt16 LoadOrderIndex UInt16 InitOrderIndex UInt16 LoadCount UInt16 OffsetToFileName Char[] 'FullPathName ByValArray 256' } } process {} end { $STATUS_INFO_LENGTH_MISMATCH, $req = 0xC0000004, [Byte[]]::new(4) $STATUS_SUCCESS, $sysdir = 0, [Environment]::SystemDirectory if ($STATUS_INFO_LENGTH_MISMATCH -ne ( $nts = $ntdll.NtQuerySystemInformation.Invoke(11, [IntPtr]::Zero, 0, $req) )) { Write-Verbose (ConvertTo-ErrMessage -NtStatus $nts) return } try { $ptr = [Marshal]::AllocHGlobal(($sz = [BitConverter]::ToUInt32($req, 0))) if ($STATUS_SUCCESS -ne ( $nts = $ntdll.NtQuerySystemInformation.Invoke(11, $ptr, $sz, $null) )) { throw (ConvertTo-ErrMessage -NtStatus $nts) } $psz, $sz = [IntPtr]::Size, [RTL_PROCESS_MODULE_INFORMATION]::GetSize() $num, $itr = [Marshal]::ReadInt32($ptr), ($ptr."ToInt$($psz * 8)"() + $psz) $((0..($num - 1)).ForEach{ $mod = ([IntPtr]$itr) -as [RTL_PROCESS_MODULE_INFORMATION] [PSCustomObject]@{ Ord = $mod.LoadOrderIndex Address = $mod.ImageBase.ToString("X$($psz * 2)") Size = $mod.ImageSize #Flags = $mod.Flags Count = $mod.LoadCount Path = [String]::new($mod.FullPathName ).Split("`0")[0] -replace '(?:\\)?.*system32', $sysdir } $itr += $sz }) | Format-Table -AutoSize } catch { Write-Verbose $_ } finally { if ($ptr) { [Marshal]::FreeHGlobal($ptr) } } } } Export-ModuleMember -Function Get-SysModules |