Ajouter scan.ps1
This commit is contained in:
@@ -0,0 +1,634 @@
|
|||||||
|
###############################################################################################################
|
||||||
|
# Language : PowerShell 4.0
|
||||||
|
# Filename : IPv4NetworkScan.ps1
|
||||||
|
# Autor : BornToBeRoot (https://github.com/BornToBeRoot)
|
||||||
|
# Description : Powerful asynchronus IPv4 Network Scanner
|
||||||
|
# Repository : https://github.com/BornToBeRoot/PowerShell_IPv4NetworkScanner
|
||||||
|
###############################################################################################################
|
||||||
|
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Powerful asynchronus IPv4 Network Scanner
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This powerful asynchronus IPv4 Network Scanner allows you to scan every IPv4-Range you want (172.16.1.47 to 172.16.2.5 would work). But there is also the possibility to scan an entire subnet based on an IPv4-Address withing the subnet and a the subnetmask/CIDR.
|
||||||
|
|
||||||
|
The default result will contain the the IPv4-Address, Status (Up or Down) and the Hostname. Other values can be displayed via parameter.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\IPv4NetworkScan.ps1 -StartIPv4Address 192.168.178.0 -EndIPv4Address 192.168.178.20
|
||||||
|
|
||||||
|
IPv4Address Status Hostname
|
||||||
|
----------- ------ --------
|
||||||
|
192.168.178.1 Up fritz.box
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\IPv4NetworkScan.ps1 -IPv4Address 192.168.178.0 -Mask 255.255.255.0 -DisableDNSResolving
|
||||||
|
|
||||||
|
IPv4Address Status
|
||||||
|
----------- ------
|
||||||
|
192.168.178.1 Up
|
||||||
|
192.168.178.22 Up
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\IPv4NetworkScan.ps1 -IPv4Address 192.168.178.0 -CIDR 25 -EnableMACResolving
|
||||||
|
|
||||||
|
IPv4Address Status Hostname MAC Vendor
|
||||||
|
----------- ------ -------- --- ------
|
||||||
|
192.168.178.1 Up fritz.box XX-XX-XX-XX-XX-XX AVM Audiovisuelles Marketing und Computersysteme GmbH
|
||||||
|
192.168.178.22 Up XXXXX-PC.fritz.box XX-XX-XX-XX-XX-XX ASRock Incorporation
|
||||||
|
|
||||||
|
.LINK
|
||||||
|
https://github.com/BornToBeRoot/PowerShell_IPv4NetworkScanner/blob/master/README.md
|
||||||
|
#>
|
||||||
|
|
||||||
|
[CmdletBinding(DefaultParameterSetName = 'CIDR')]
|
||||||
|
Param(
|
||||||
|
[Parameter(
|
||||||
|
ParameterSetName = 'Range',
|
||||||
|
Position = 0,
|
||||||
|
Mandatory = $true,
|
||||||
|
HelpMessage = 'Start IPv4-Address like 192.168.1.10')]
|
||||||
|
[IPAddress]$StartIPv4Address,
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
ParameterSetName = 'Range',
|
||||||
|
Position = 1,
|
||||||
|
Mandatory = $true,
|
||||||
|
HelpMessage = 'End IPv4-Address like 192.168.1.100')]
|
||||||
|
[IPAddress]$EndIPv4Address,
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
ParameterSetName = 'CIDR',
|
||||||
|
Position = 0,
|
||||||
|
Mandatory = $true,
|
||||||
|
HelpMessage = 'IPv4-Address which is in the subnet')]
|
||||||
|
[Parameter(
|
||||||
|
ParameterSetName = 'Mask',
|
||||||
|
Position = 0,
|
||||||
|
Mandatory = $true,
|
||||||
|
HelpMessage = 'IPv4-Address which is in the subnet')]
|
||||||
|
[IPAddress]$IPv4Address,
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
ParameterSetName = 'CIDR',
|
||||||
|
Position = 1,
|
||||||
|
Mandatory = $true,
|
||||||
|
HelpMessage = 'CIDR like /24 without "/"')]
|
||||||
|
[ValidateRange(0, 31)]
|
||||||
|
[Int32]$CIDR,
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
ParameterSetName = 'Mask',
|
||||||
|
Position = 1,
|
||||||
|
Mandatory = $true,
|
||||||
|
Helpmessage = 'Subnetmask like 255.255.255.0')]
|
||||||
|
[ValidateScript({
|
||||||
|
if ($_ -match "^(254|252|248|240|224|192|128).0.0.0$|^255.(254|252|248|240|224|192|128|0).0.0$|^255.255.(254|252|248|240|224|192|128|0).0$|^255.255.255.(254|252|248|240|224|192|128|0)$") {
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw "Enter a valid subnetmask (like 255.255.255.0)!"
|
||||||
|
}
|
||||||
|
})]
|
||||||
|
[String]$Mask,
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
Position = 2,
|
||||||
|
HelpMessage = 'Maxmium number of ICMP checks for each IPv4-Address (Default=2)')]
|
||||||
|
[Int32]$Tries = 2,
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
Position = 3,
|
||||||
|
HelpMessage = 'Maximum number of threads at the same time (Default=256)')]
|
||||||
|
[Int32]$Threads = 256,
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
Position = 4,
|
||||||
|
HelpMessage = 'Resolve DNS for each IP (Default=Enabled)')]
|
||||||
|
[Switch]$DisableDNSResolving,
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
Position = 5,
|
||||||
|
HelpMessage = 'Resolve MAC-Address for each IP (Default=Disabled)')]
|
||||||
|
[Switch]$EnableMACResolving,
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
Position = 6,
|
||||||
|
HelpMessage = 'Get extendend informations like BufferSize, ResponseTime and TTL (Default=Disabled)')]
|
||||||
|
[Switch]$ExtendedInformations,
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
Position = 7,
|
||||||
|
HelpMessage = 'Include inactive devices in result')]
|
||||||
|
[Switch]$IncludeInactive
|
||||||
|
)
|
||||||
|
|
||||||
|
Begin {
|
||||||
|
Write-Verbose -Message "Script started at $(Get-Date)"
|
||||||
|
|
||||||
|
$OUIListPath = "$PSScriptRoot\Resources\oui.txt"
|
||||||
|
|
||||||
|
function Convert-Subnetmask {
|
||||||
|
[CmdLetBinding(DefaultParameterSetName = 'CIDR')]
|
||||||
|
param(
|
||||||
|
[Parameter(
|
||||||
|
ParameterSetName = 'CIDR',
|
||||||
|
Position = 0,
|
||||||
|
Mandatory = $true,
|
||||||
|
HelpMessage = 'CIDR like /24 without "/"')]
|
||||||
|
[ValidateRange(0, 32)]
|
||||||
|
[Int32]$CIDR,
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
ParameterSetName = 'Mask',
|
||||||
|
Position = 0,
|
||||||
|
Mandatory = $true,
|
||||||
|
HelpMessage = 'Subnetmask like 255.255.255.0')]
|
||||||
|
[ValidateScript({
|
||||||
|
if ($_ -match "^(254|252|248|240|224|192|128).0.0.0$|^255.(254|252|248|240|224|192|128|0).0.0$|^255.255.(254|252|248|240|224|192|128|0).0$|^255.255.255.(255|254|252|248|240|224|192|128|0)$") {
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw "Enter a valid subnetmask (like 255.255.255.0)!"
|
||||||
|
}
|
||||||
|
})]
|
||||||
|
[String]$Mask
|
||||||
|
)
|
||||||
|
|
||||||
|
Begin {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
switch ($PSCmdlet.ParameterSetName) {
|
||||||
|
"CIDR" {
|
||||||
|
# Make a string of bits (24 to 11111111111111111111111100000000)
|
||||||
|
$CIDR_Bits = ('1' * $CIDR).PadRight(32, "0")
|
||||||
|
|
||||||
|
# Split into groups of 8 bits, convert to Ints, join up into a string
|
||||||
|
$Octets = $CIDR_Bits -split '(.{8})' -ne ''
|
||||||
|
$Mask = ($Octets | ForEach-Object -Process { [Convert]::ToInt32($_, 2) }) -join '.'
|
||||||
|
}
|
||||||
|
|
||||||
|
"Mask" {
|
||||||
|
# Convert the numbers into 8 bit blocks, join them all together, count the 1
|
||||||
|
$Octets = $Mask.ToString().Split(".") | ForEach-Object -Process { [Convert]::ToString($_, 2) }
|
||||||
|
$CIDR_Bits = ($Octets -join "").TrimEnd("0")
|
||||||
|
|
||||||
|
# Count the "1" (111111111111111111111111 --> /24)
|
||||||
|
$CIDR = $CIDR_Bits.Length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[pscustomobject] @{
|
||||||
|
Mask = $Mask
|
||||||
|
CIDR = $CIDR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
End {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Helper function to convert an IPv4-Address to Int64 and vise versa
|
||||||
|
function Convert-IPv4Address {
|
||||||
|
[CmdletBinding(DefaultParameterSetName = 'IPv4Address')]
|
||||||
|
param(
|
||||||
|
[Parameter(
|
||||||
|
ParameterSetName = 'IPv4Address',
|
||||||
|
Position = 0,
|
||||||
|
Mandatory = $true,
|
||||||
|
HelpMessage = 'IPv4-Address as string like "192.168.1.1"')]
|
||||||
|
[IPaddress]$IPv4Address,
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
ParameterSetName = 'Int64',
|
||||||
|
Position = 0,
|
||||||
|
Mandatory = $true,
|
||||||
|
HelpMessage = 'IPv4-Address as Int64 like 2886755428')]
|
||||||
|
[long]$Int64
|
||||||
|
)
|
||||||
|
|
||||||
|
Begin {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
switch ($PSCmdlet.ParameterSetName) {
|
||||||
|
# Convert IPv4-Address as string into Int64
|
||||||
|
"IPv4Address" {
|
||||||
|
$Octets = $IPv4Address.ToString().Split(".")
|
||||||
|
$Int64 = [long]([long]$Octets[0] * 16777216 + [long]$Octets[1] * 65536 + [long]$Octets[2] * 256 + [long]$Octets[3])
|
||||||
|
}
|
||||||
|
|
||||||
|
# Convert IPv4-Address as Int64 into string
|
||||||
|
"Int64" {
|
||||||
|
$IPv4Address = (([System.Math]::Truncate($Int64 / 16777216)).ToString() + "." + ([System.Math]::Truncate(($Int64 % 16777216) / 65536)).ToString() + "." + ([System.Math]::Truncate(($Int64 % 65536) / 256)).ToString() + "." + ([System.Math]::Truncate($Int64 % 256)).ToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[pscustomobject] @{
|
||||||
|
IPv4Address = $IPv4Address
|
||||||
|
Int64 = $Int64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
End {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Helper function to create a new Subnet
|
||||||
|
function Get-IPv4Subnet {
|
||||||
|
[CmdletBinding(DefaultParameterSetName = 'CIDR')]
|
||||||
|
param(
|
||||||
|
[Parameter(
|
||||||
|
Position = 0,
|
||||||
|
Mandatory = $true,
|
||||||
|
HelpMessage = 'IPv4-Address which is in the subnet')]
|
||||||
|
[IPAddress]$IPv4Address,
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
ParameterSetName = 'CIDR',
|
||||||
|
Position = 1,
|
||||||
|
Mandatory = $true,
|
||||||
|
HelpMessage = 'CIDR like /24 without "/"')]
|
||||||
|
[ValidateRange(0, 31)]
|
||||||
|
[Int32]$CIDR,
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
ParameterSetName = 'Mask',
|
||||||
|
Position = 1,
|
||||||
|
Mandatory = $true,
|
||||||
|
Helpmessage = 'Subnetmask like 255.255.255.0')]
|
||||||
|
[ValidateScript({
|
||||||
|
if ($_ -match "^(254|252|248|240|224|192|128).0.0.0$|^255.(254|252|248|240|224|192|128|0).0.0$|^255.255.(254|252|248|240|224|192|128|0).0$|^255.255.255.(254|252|248|240|224|192|128|0)$") {
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw "Enter a valid subnetmask (like 255.255.255.0)!"
|
||||||
|
}
|
||||||
|
})]
|
||||||
|
[String]$Mask
|
||||||
|
)
|
||||||
|
|
||||||
|
Begin {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
# Convert Mask or CIDR - because we need both in the code below
|
||||||
|
switch ($PSCmdlet.ParameterSetName) {
|
||||||
|
"CIDR" {
|
||||||
|
$Mask = (Convert-Subnetmask -CIDR $CIDR).Mask
|
||||||
|
}
|
||||||
|
"Mask" {
|
||||||
|
$CIDR = (Convert-Subnetmask -Mask $Mask).CIDR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get CIDR Address by parsing it into an IP-Address
|
||||||
|
$CIDRAddress = [System.Net.IPAddress]::Parse([System.Convert]::ToUInt64(("1" * $CIDR).PadRight(32, "0"), 2))
|
||||||
|
|
||||||
|
# Binary AND ... this is how subnets work.
|
||||||
|
$NetworkID_bAND = $IPv4Address.Address -band $CIDRAddress.Address
|
||||||
|
|
||||||
|
# Return an array of bytes. Then join them.
|
||||||
|
$NetworkID = [System.Net.IPAddress]::Parse([System.BitConverter]::GetBytes([UInt32]$NetworkID_bAND) -join ("."))
|
||||||
|
|
||||||
|
# Get HostBits based on SubnetBits (CIDR) // Hostbits (32 - /24 = 8 -> 00000000000000000000000011111111)
|
||||||
|
$HostBits = ('1' * (32 - $CIDR)).PadLeft(32, "0")
|
||||||
|
|
||||||
|
# Convert Bits to Int64
|
||||||
|
$AvailableIPs = [Convert]::ToInt64($HostBits, 2)
|
||||||
|
|
||||||
|
# Convert Network Address to Int64
|
||||||
|
$NetworkID_Int64 = (Convert-IPv4Address -IPv4Address $NetworkID.ToString()).Int64
|
||||||
|
|
||||||
|
# Convert add available IPs and parse into IPAddress
|
||||||
|
$Broadcast = [System.Net.IPAddress]::Parse((Convert-IPv4Address -Int64 ($NetworkID_Int64 + $AvailableIPs)).IPv4Address)
|
||||||
|
|
||||||
|
# Change useroutput ==> (/27 = 0..31 IPs -> AvailableIPs 32)
|
||||||
|
$AvailableIPs += 1
|
||||||
|
|
||||||
|
# Hosts = AvailableIPs - Network Address + Broadcast Address
|
||||||
|
$Hosts = ($AvailableIPs - 2)
|
||||||
|
|
||||||
|
# Build custom PSObject
|
||||||
|
[pscustomobject] @{
|
||||||
|
NetworkID = $NetworkID
|
||||||
|
Broadcast = $Broadcast
|
||||||
|
IPs = $AvailableIPs
|
||||||
|
Hosts = $Hosts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
End {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
# Calculate Subnet (Start and End IPv4-Address)
|
||||||
|
if ($PSCmdlet.ParameterSetName -eq 'CIDR' -or $PSCmdlet.ParameterSetName -eq 'Mask') {
|
||||||
|
# Convert Subnetmask
|
||||||
|
if ($PSCmdlet.ParameterSetName -eq 'Mask') {
|
||||||
|
$CIDR = (Convert-Subnetmask -Mask $Mask).CIDR
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create new subnet
|
||||||
|
$Subnet = Get-IPv4Subnet -IPv4Address $IPv4Address -CIDR $CIDR
|
||||||
|
|
||||||
|
# Assign Start and End IPv4-Address
|
||||||
|
$StartIPv4Address = $Subnet.NetworkID
|
||||||
|
$EndIPv4Address = $Subnet.Broadcast
|
||||||
|
}
|
||||||
|
|
||||||
|
# Convert Start and End IPv4-Address to Int64
|
||||||
|
$StartIPv4Address_Int64 = (Convert-IPv4Address -IPv4Address $StartIPv4Address.ToString()).Int64
|
||||||
|
$EndIPv4Address_Int64 = (Convert-IPv4Address -IPv4Address $EndIPv4Address.ToString()).Int64
|
||||||
|
|
||||||
|
# Check if range is valid
|
||||||
|
if ($StartIPv4Address_Int64 -gt $EndIPv4Address_Int64) {
|
||||||
|
Write-Error -Message "Invalid IP-Range... Check your input!" -Category InvalidArgument -ErrorAction Stop
|
||||||
|
}
|
||||||
|
|
||||||
|
# Calculate IPs to scan (range)
|
||||||
|
$IPsToScan = ($EndIPv4Address_Int64 - $StartIPv4Address_Int64)
|
||||||
|
|
||||||
|
Write-Verbose -Message "Scanning range from $StartIPv4Address to $EndIPv4Address ($($IPsToScan + 1) IPs)"
|
||||||
|
Write-Verbose -Message "Running with max $Threads threads"
|
||||||
|
Write-Verbose -Message "ICMP checks per IP: $Tries"
|
||||||
|
|
||||||
|
# Properties which are displayed in the output
|
||||||
|
$PropertiesToDisplay = @()
|
||||||
|
$PropertiesToDisplay += "IPv4Address", "Status"
|
||||||
|
|
||||||
|
if ($DisableDNSResolving -eq $false) {
|
||||||
|
$PropertiesToDisplay += "Hostname"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($EnableMACResolving) {
|
||||||
|
$PropertiesToDisplay += "MAC"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if it is possible to assign vendor to MAC --> import CSV-File
|
||||||
|
if ($EnableMACResolving) {
|
||||||
|
if (Test-Path -Path $OUIListPath -PathType Leaf) {
|
||||||
|
$OUIHashTable = @{ }
|
||||||
|
|
||||||
|
Write-Verbose -Message "Read oui.txt and fill hash table..."
|
||||||
|
|
||||||
|
foreach ($Line in Get-Content -Path $OUIListPath) {
|
||||||
|
if (-not([String]::IsNullOrEmpty($Line))) {
|
||||||
|
try {
|
||||||
|
$HashTableData = $Line.Split('|')
|
||||||
|
$OUIHashTable.Add($HashTableData[0], $HashTableData[1])
|
||||||
|
}
|
||||||
|
catch [System.ArgumentException] { } # Catch if mac is already added to hash table
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$AssignVendorToMAC = $true
|
||||||
|
|
||||||
|
$PropertiesToDisplay += "Vendor"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$AssignVendorToMAC = $false
|
||||||
|
|
||||||
|
Write-Warning -Message "No OUI-File to assign vendor with MAC-Address found! Execute the script ""Create-OUIListFromWeb.ps1"" to download the latest version. This warning does not affect the scanning procedure."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ExtendedInformations) {
|
||||||
|
$PropertiesToDisplay += "BufferSize", "ResponseTime", "TTL"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Scriptblock --> will run in runspaces (threads)...
|
||||||
|
[System.Management.Automation.ScriptBlock]$ScriptBlock = {
|
||||||
|
Param(
|
||||||
|
$IPv4Address,
|
||||||
|
$Tries,
|
||||||
|
$DisableDNSResolving,
|
||||||
|
$EnableMACResolving,
|
||||||
|
$ExtendedInformations,
|
||||||
|
$IncludeInactive
|
||||||
|
)
|
||||||
|
|
||||||
|
# +++ Send ICMP requests +++
|
||||||
|
$Status = [String]::Empty
|
||||||
|
|
||||||
|
for ($i = 0; $i -lt $Tries; i++) {
|
||||||
|
try {
|
||||||
|
$PingObj = New-Object System.Net.NetworkInformation.Ping
|
||||||
|
|
||||||
|
$Timeout = 1000
|
||||||
|
$Buffer = New-Object Byte[] 32
|
||||||
|
|
||||||
|
$PingResult = $PingObj.Send($IPv4Address, $Timeout, $Buffer)
|
||||||
|
|
||||||
|
if ($PingResult.Status -eq "Success") {
|
||||||
|
$Status = "Up"
|
||||||
|
break # Exit loop, if host is reachable
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$Status = "Down"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$Status = "Down"
|
||||||
|
break # Exit loop, if there is an error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# +++ Resolve DNS +++
|
||||||
|
$Hostname = [String]::Empty
|
||||||
|
|
||||||
|
if ((-not($DisableDNSResolving)) -and ($Status -eq "Up" -or $IncludeInactive)) {
|
||||||
|
try {
|
||||||
|
$Hostname = ([System.Net.Dns]::GetHostEntry($IPv4Address).HostName)
|
||||||
|
}
|
||||||
|
catch { } # No DNS
|
||||||
|
}
|
||||||
|
|
||||||
|
# +++ Get MAC-Address +++
|
||||||
|
$MAC = [String]::Empty
|
||||||
|
|
||||||
|
if (($EnableMACResolving) -and (($Status -eq "Up") -or ($IncludeInactive))) {
|
||||||
|
$Arp_Result = (arp -a).ToUpper().Trim()
|
||||||
|
|
||||||
|
foreach ($Line in $Arp_Result) {
|
||||||
|
if ($Line.Split(" ")[0] -eq $IPv4Address) {
|
||||||
|
$MAC = [Regex]::Matches($Line, "([0-9A-F][0-9A-F]-){5}([0-9A-F][0-9A-F])").Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# +++ Get extended informations +++
|
||||||
|
$BufferSize = [String]::Empty
|
||||||
|
$ResponseTime = [String]::Empty
|
||||||
|
$TTL = $null
|
||||||
|
|
||||||
|
if ($ExtendedInformations -and ($Status -eq "Up")) {
|
||||||
|
try {
|
||||||
|
$BufferSize = $PingResult.Buffer.Length
|
||||||
|
$ResponseTime = $PingResult.RoundtripTime
|
||||||
|
$TTL = $PingResult.Options.Ttl
|
||||||
|
}
|
||||||
|
catch { } # Failed to get extended informations
|
||||||
|
}
|
||||||
|
|
||||||
|
# +++ Result +++
|
||||||
|
if (($Status -eq "Up") -or ($IncludeInactive)) {
|
||||||
|
[pscustomobject] @{
|
||||||
|
IPv4Address = $IPv4Address
|
||||||
|
Status = $Status
|
||||||
|
Hostname = $Hostname
|
||||||
|
MAC = $MAC
|
||||||
|
BufferSize = $BufferSize
|
||||||
|
ResponseTime = $ResponseTime
|
||||||
|
TTL = $TTL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Verbose -Message "Setting up RunspacePool..."
|
||||||
|
|
||||||
|
# Create RunspacePool and Jobs
|
||||||
|
$RunspacePool = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspacePool(1, $Threads, $Host)
|
||||||
|
$RunspacePool.Open()
|
||||||
|
[System.Collections.ArrayList]$Jobs = @()
|
||||||
|
|
||||||
|
Write-Verbose -Message "Setting up jobs..."
|
||||||
|
|
||||||
|
# Set up jobs for each IP...
|
||||||
|
for ($i = $StartIPv4Address_Int64; $i -le $EndIPv4Address_Int64; $i++) {
|
||||||
|
# Convert IP back from Int64
|
||||||
|
$IPv4Address = (Convert-IPv4Address -Int64 $i).IPv4Address
|
||||||
|
|
||||||
|
# Create hashtable to pass parameters
|
||||||
|
$ScriptParams = @{
|
||||||
|
IPv4Address = $IPv4Address
|
||||||
|
Tries = $Tries
|
||||||
|
DisableDNSResolving = $DisableDNSResolving
|
||||||
|
EnableMACResolving = $EnableMACResolving
|
||||||
|
ExtendedInformations = $ExtendedInformations
|
||||||
|
IncludeInactive = $IncludeInactive
|
||||||
|
}
|
||||||
|
|
||||||
|
# Catch when trying to divide through zero
|
||||||
|
try {
|
||||||
|
$Progress_Percent = (($i - $StartIPv4Address_Int64) / $IPsToScan) * 100
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$Progress_Percent = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Progress -Activity "Setting up jobs..." -Id 1 -Status "Current IP-Address: $IPv4Address" -PercentComplete $Progress_Percent
|
||||||
|
|
||||||
|
# Create new job
|
||||||
|
$Job = [System.Management.Automation.PowerShell]::Create().AddScript($ScriptBlock).AddParameters($ScriptParams)
|
||||||
|
$Job.RunspacePool = $RunspacePool
|
||||||
|
|
||||||
|
$JobObj = [pscustomobject] @{
|
||||||
|
RunNum = $i - $StartIPv4Address_Int64
|
||||||
|
Pipe = $Job
|
||||||
|
Result = $Job.BeginInvoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add job to collection
|
||||||
|
[void]$Jobs.Add($JobObj)
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Verbose -Message "Waiting for jobs to complete & starting to process results..."
|
||||||
|
|
||||||
|
# Total jobs to calculate percent complete, because jobs are removed after they are processed
|
||||||
|
$Jobs_Total = $Jobs.Count
|
||||||
|
|
||||||
|
# Process results, while waiting for other jobs
|
||||||
|
Do {
|
||||||
|
# Get all jobs, which are completed
|
||||||
|
$Jobs_ToProcess = $Jobs | Where-Object -FilterScript { $_.Result.IsCompleted }
|
||||||
|
|
||||||
|
# If no jobs finished yet, wait 500 ms and try again
|
||||||
|
if ($null -eq $Jobs_ToProcess) {
|
||||||
|
Write-Verbose -Message "No jobs completed, wait 250ms..."
|
||||||
|
|
||||||
|
Start-Sleep -Milliseconds 250
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get jobs, which are not complete yet
|
||||||
|
$Jobs_Remaining = ($Jobs | Where-Object -FilterScript { $_.Result.IsCompleted -eq $false }).Count
|
||||||
|
|
||||||
|
# Catch when trying to divide through zero
|
||||||
|
try {
|
||||||
|
$Progress_Percent = 100 - (($Jobs_Remaining / $Jobs_Total) * 100)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$Progress_Percent = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Progress -Activity "Waiting for jobs to complete... ($($Threads - $($RunspacePool.GetAvailableRunspaces())) of $Threads threads running)" -Id 1 -PercentComplete $Progress_Percent -Status "$Jobs_Remaining remaining..."
|
||||||
|
|
||||||
|
Write-Verbose -Message "Processing $(if($null -eq $Jobs_ToProcess.Count){"1"}else{$Jobs_ToProcess.Count}) job(s)..."
|
||||||
|
|
||||||
|
# Processing completed jobs
|
||||||
|
foreach ($Job in $Jobs_ToProcess) {
|
||||||
|
# Get the result...
|
||||||
|
$Job_Result = $Job.Pipe.EndInvoke($Job.Result)
|
||||||
|
$Job.Pipe.Dispose()
|
||||||
|
|
||||||
|
# Remove job from collection
|
||||||
|
$Jobs.Remove($Job)
|
||||||
|
|
||||||
|
# Check if result contains status
|
||||||
|
if ($Job_Result.Status) {
|
||||||
|
if ($AssignVendorToMAC) {
|
||||||
|
$Vendor = [String]::Empty
|
||||||
|
|
||||||
|
# Check if MAC is null or empty
|
||||||
|
if (-not([String]::IsNullOrEmpty($Job_Result.MAC))) {
|
||||||
|
# Split it, so we can search the vendor (XX-XX-XX-XX-XX-XX to XXXXXX)
|
||||||
|
$MAC_VendorSearch = $Job_Result.MAC.Replace("-", "").Substring(0, 6)
|
||||||
|
|
||||||
|
$Vendor = $OUIHashTable.Get_Item($MAC_VendorSearch)
|
||||||
|
}
|
||||||
|
|
||||||
|
[pscustomobject] @{
|
||||||
|
IPv4Address = $Job_Result.IPv4Address
|
||||||
|
Status = $Job_Result.Status
|
||||||
|
Hostname = $Job_Result.Hostname
|
||||||
|
MAC = $Job_Result.MAC
|
||||||
|
Vendor = $Vendor
|
||||||
|
BufferSize = $Job_Result.BufferSize
|
||||||
|
ResponseTime = $Job_Result.ResponseTime
|
||||||
|
TTL = $ResuJob_Resultlt.TTL
|
||||||
|
} | Select-Object -Property $PropertiesToDisplay
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$Job_Result | Select-Object -Property $PropertiesToDisplay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} While ($Jobs.Count -gt 0)
|
||||||
|
|
||||||
|
Write-Verbose -Message "Closing RunspacePool and free resources..."
|
||||||
|
|
||||||
|
# Close the RunspacePool and free resources
|
||||||
|
$RunspacePool.Close()
|
||||||
|
$RunspacePool.Dispose()
|
||||||
|
|
||||||
|
Write-Verbose -Message "Script finished at $(Get-Date)"
|
||||||
|
}
|
||||||
|
|
||||||
|
End {
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user