From ebe7f0981a0a8c4cd485ae5b3455e0b27af070aa Mon Sep 17 00:00:00 2001 From: Rich Lundeen Date: Sun, 9 Jun 2013 21:08:44 -0700 Subject: added invoke-portscan module --- Recon/Invoke-Portscan.ps1 | 1012 +++++++++++++++++++++++++++++++++++++++++++++ Recon/Recon.psd1 | 2 +- 2 files changed, 1013 insertions(+), 1 deletion(-) create mode 100644 Recon/Invoke-Portscan.ps1 diff --git a/Recon/Invoke-Portscan.ps1 b/Recon/Invoke-Portscan.ps1 new file mode 100644 index 0000000..6696a17 --- /dev/null +++ b/Recon/Invoke-Portscan.ps1 @@ -0,0 +1,1012 @@ +function Invoke-Portscan +{ +<# +.SYNOPSIS + +Simple portscan module + +PowerSploit Function: Invoke-Portscan +Author: Rich Lundeen (http://webstersProdigy.net) +License: BSD 3-Clause +Required Dependencies: None +Optional Dependencies: None + +.DESCRIPTION + +Does a simple port scan using regular sockets, based (pretty) loosely on nmap + +.NOTES + +version .11 + +.EXAMPLE + +C:\PS> Invoke-Portscan -v -Hosts "webstersprodigy.net,google.com,microsoft.com" -topPorts 30 + +Description +----------- +Scans the top 30 ports for hosts found for webstersprodigy.net,google.com, and microsoft.com + + +.EXAMPLE + +C:\PS> echo webstersprodigy.net | Invoke-Portscan -oG test.gnmap -f -ports "80,443,8080" + +Description +----------- +Does a portscan of "webstersprodigy.net", and writes a greppable output file + + +.EXAMPLE + +C:\PS> Invoke-Portscan -Hosts 192.168.1.1/24 -T 4 -topPorts 25 -v -oA localnet + +Description +----------- +Scans the top 20 ports for hosts found in the 192.168.1.1/24 range, outputs all file formats + + +.LINK + +http://webstersprodigy.net +#> + + [CmdletBinding()]Param ( + #Host, Ports + [Parameter(ParameterSetName="cmdHosts", + ValueFromPipeline=$True, + Mandatory = $True, + HelpMessage = "include these comma seperated hosts (supports IPv4 CIDR notation), or pipe them in" )] + [String[]] $Hosts, + + [Parameter(ParameterSetName="fHosts", + Mandatory = $True, + HelpMessage = "input hosts from file")] + [String] $iL, + + [Parameter(Mandatory = $False, + HelpMessage = "exclude these comma seperated hosts")] + [String] $exclude, + + [Parameter(Mandatory = $False, + HelpMessage = "include these comma seperated ports (can also be a range like 80-90)")] + [String] $Ports, + + [Parameter(Mandatory = $False, + HelpMessage = "input ports from a file")] + [String] $iP, + + [Parameter(Mandatory = $False, + HelpMessage = "include the x top ports - only goes to 1000, default is top 50")] + [String] $topPorts, + + [Parameter(Mandatory = $False, + HelpMessage = "exclude these comma seperated ports")] + [String] $xPorts, + + #Host Discovery + [Parameter(Mandatory = $False, + HelpMessage = "treat all hosts as online, skip host discovery")] + [Switch] $Pn, + + [Parameter(Mandatory = $False, + HelpMessage = "Ping scan only (disable port scan)")] + [Switch] $sn, + + [Parameter(Mandatory = $False, + HelpMessage = "comma separated ports for discovery. -1 is a ping")] + [string] $PS = "-1,445,80,443", + + #Timing and Performance + [Parameter(Mandatory = $False, + HelpMessage = "number of max threads for the thread pool (per host)")] + [int] $Threads = 100, + + [Parameter(Mandatory = $False, + HelpMessage = "number of hosts to concurrently scan")] + [int] $nHosts = 25, + + [Parameter(Mandatory = $False, + HelpMessage = "timeout time on a connection in miliseconds")] + [int] $Timeout = 2000, + + [Parameter(Mandatory = $False, + HelpMessage = "wait before thread checking, in miliseconds")] + [int] $sleepTimer = 500, + + [Parameter(Mandatory = $False, + HelpMessage = "how often (in terms of hosts) to sync threads and flush output")] + [int] $syncFreq = 1024, + + [Parameter(Mandatory = $False, + HelpMessage = "[0-5] shortcut performance options. Default is 3. higher is more aggressive. Sets (nhosts, threads,timeout) + 5: (40,1000,750) 4: (30,1000,1200) 3: (25,100,2000) 2:(20,32,2500) 1:(10,32,5000)")] + [int] $T, + + #Output + [Parameter(Mandatory = $False, + HelpMessage = "Greppable output file")] + [String] $oG, + + [Parameter(Mandatory = $False, + HelpMessage = "output in xml")] + [String] $oX, + + [Parameter(Mandatory = $False, + HelpMessage = "output in 'readable' format")] + [String] $oN, + + [Parameter(Mandatory = $False, + HelpMessage = "output in readable and xml format in addition to greppable.")] + [String] $oA, + + [Parameter(Mandatory = $False, + HelpMessage = "gives a progress meter")] + [Switch] $v, + + [Parameter(Mandatory = $False, + HelpMessage = "supresses output")] + [Switch] $q, + + [Parameter(Mandatory = $False, + HelpMessage = "Force Overwrite if output Files exist. Otherwise it throws exception")] + [Switch] $F + + #TODO add script parameter + #TODO add resume parameter + ) + + PROCESS { + + $version = .11 + $hostList = New-Object System.Collections.ArrayList + [int[]]$portList = @() + [int[]]$hostPortList = @() + + function Parse-Hosts + { + Param ( + [Parameter(Mandatory = $True)] [String] $Hosts + ) + + [String[]] $iHosts = $Hosts.Split(",") + + foreach($iHost in $iHosts) + { + $iHost = $iHost.Replace(" ", "") + + if(!$iHost) + { + continue + } + + if($iHost.contains("/")) + { + $netPart = $iHost.split("/")[0] + [uint32]$maskPart = $iHost.split("/")[1] + + $address = [System.Net.IPAddress]::Parse($netPart) + + if ($maskPart -ge $address.GetAddressBytes().Length * 8) + { + throw "Bad host mask" + } + + $numhosts = 1 -shl (($address.GetAddressBytes().Length *8) - $maskPart) + + #Get start address + $startAddress = $address.GetAddressBytes() + $numbits = $startAddress.Length * 8 + [array]::Reverse($startAddress) + $startAddress = ([System.Numerics.BigInteger] [byte[]]$startAddress) + $startAddress = $startAddress -band ([System.Numerics.BigInteger]::Pow(2, $maskPart)-1 -shl ($numbits - $maskPart)) + $startAddress = $startAddress.ToByteArray() + [array]::Reverse($startAddress) + + #strip out leading 0 put in by BigIneger, if any + if ($startAddress[0] -eq 0) + { + $startAddress = $startAddress[1..$startAddress.Length] + } + + $address = [System.Net.IPAddress] [byte[]] $startAddress + $hostList.Add($address.IPAddressToString) + + + for ($i=0; $i -lt $numhosts-1; $i++) + { + $nextAddress = $address.GetAddressBytes() + [array]::Reverse($nextAddress) + $nextAddress = ([System.Numerics.BigInteger] [byte[]]$nextAddress) + 1 + $nextAddress = $nextAddress.ToByteArray() + [array]::Reverse($nextAddress) + + $address = [System.Net.IPAddress] [byte[]] $nextAddress + + $hostList.Add($address.IPAddressToString) + + } + } + else + { + try + { + $address = [System.Net.IPAddress]::Parse($iHost) + $hostList.Add($address.IPAddressToString) + } + catch + { + #we're assuming this is a host name + $hostList.Add($iHost) + } + } + } + } + + function Parse-ILHosts + { + Param ( + [Parameter(Mandatory = $True)] [String] $HostFile + ) + + Get-Content $HostFile | ForEach-Object { + Parse-Hosts $_ + } + } + + function Exclude-Hosts + { + Param ( + [Parameter(Mandatory = $True)] [String] $excludeHosts + ) + + [String[]] $iHosts = $excludeHosts.Split(",") + + foreach($iHost in $iHosts) + { + $iHost = $iHost.Replace(" ", "") + $hostList.Remove($iHost) + } + } + + function Get-TopPort + { + Param ( + [Parameter(Mandatory = $True)] [int] $numPorts + ) + + if ($numPorts -gt 1000 -or $numPorts -lt 0) + { + throw "Topports out of range - only supports top 1000" + } + + #list of top 1000 ports from nmap from Jun 2013 + [int[]] $topPortList = @(80,23,443,21,3389,110,445,139,143,53,135,3306,8080,22 + 1723,111,995,993,5900,1025,1720,548,113,81,6001,179,1026,2000,8443, + 8000,32768,554,26,1433,49152,2001,515,8008,49154,1027,5666,646,5000, + 5631,631,49153,8081,2049,88,79,5800,106,2121,1110,49155,6000,513, + 990,5357,49156,543,544,5101,144,7,389,8009,9999,5009,7070,5190,3000, + 5432,1900,3986,13,1029,9,5051,6646,49157,1028,873,1755,2717,4899,9100, + 119,37,1000,3001,5001,82,10010,1030,9090,2107,1024,2103,6004,1801, + 5050,19,8031,1041,255,1048,1049,1053,1054,1056,1064,3703,17,808,3689, + 1031,1044,1071,5901,100,9102,2869,4001,5120,8010,9000,2105,636,1038, + 2601,1,7000,1066,1069,625,311,280,254,4000,1761,5003,2002,1998,2005, + 1032,1050,6112,1521,2161,6002,2401,902,4045,787,7937,1058,2383,1033, + 1040,1059,50000,5555,1494,3,593,2301,3268,7938,1022,1234,1035,1036,1037, + 1074,8002,9001,464,497,1935,2003,6666,6543,24,1352,3269,1111,407,500, + 20,2006,1034,1218,3260,15000,4444,264,33,2004,1042,42510,999,3052,1023, + 222,1068,888,7100,1717,992,2008,7001,2007,8082,512,1043,2009,5801,1700, + 7019,50001,4662,2065,42,2602,3333,9535,5100,2604,4002,5002,1047,1051,1052, + 1055,1060,1062,1311,3283,4443,5225,5226,6059,6789,8089,8651,8652,8701,9415, + 9593,9594,9595,16992,16993,20828,23502,32769,33354,35500,52869,55555,55600, + 64623,64680,65000,65389,1067,13782,366,5902,9050,85,1002,5500,1863,1864, + 5431,8085,10243,45100,49999,51103,49,90,6667,1503,6881,27000,340,1500,8021, + 2222,5566,8088,8899,9071,5102,6005,9101,163,5679,146,648,1666,83,3476,5004, + 5214,8001,8083,8084,9207,14238,30,912,12345,2030,2605,6,541,4,1248,3005,8007, + 306,880,2500,1086,1088,2525,4242,8291,9009,52822,900,6101,2809,7200,211,800, + 987,1083,12000,705,711,20005,6969,13783,1045,1046,1061,1063,1070,1072,1073, + 1075,1077,1078,1079,1081,1082,1085,1093,1094,1096,1098,1099,1100,1104,1106, + 1107,1108,1148,1169,1272,1310,1687,1718,1783,1840,2100,2119,2135,2144,2160, + 2190,2260,2381,2399,2492,2607,2718,2811,2875,3017,3031,3071,3211,3300,3301, + 3323,3325,3351,3404,3551,3580,3659,3766,3784,3801,3827,3998,4003,4126,4129, + 4449,5222,5269,5633,5718,5810,5825,5877,5910,5911,5925,5959,5960,5961,5962, + 5987,5988,5989,6123,6129,6156,6389,6580,6901,7106,7625,7777,7778,7911,8086, + 8181,8222,8333,8400,8402,8600,8649,8873,8994,9002,9011,9080,9220,9290,9485, + 9500,9502,9503,9618,9900,9968,10002,10012,10024,10025,10566,10616,10617,10621, + 10626,10628,10629,11110,13456,14442,15002,15003,15660,16001,16016,16018,17988, + 19101,19801,19842,20000,20031,20221,20222,21571,22939,24800,25734,27715,28201, + 30000,30718,31038,32781,32782,33899,34571,34572,34573,40193,48080,49158,49159, + 49160,50003,50006,50800,57294,58080,60020,63331,65129,691,212,1001,1999,2020, + 2998,6003,7002,50002,32,2033,3372,99,425,749,5903,43,458,5405,6106,6502,7007, + 13722,1087,1089,1124,1152,1183,1186,1247,1296,1334,1580,1782,2126,2179,2191,2251, + 2522,3011,3030,3077,3261,3493,3546,3737,3828,3871,3880,3918,3995,4006,4111,4446, + 5054,5200,5280,5298,5822,5859,5904,5915,5922,5963,7103,7402,7435,7443,7512,8011, + 8090,8100,8180,8254,8500,8654,9091,9110,9666,9877,9943,9944,9998,10004,10778,15742, + 16012,18988,19283,19315,19780,24444,27352,27353,27355,32784,49163,49165,49175, + 50389,50636,51493,55055,56738,61532,61900,62078,1021,9040,666,700,84,545,1112, + 1524,2040,4321,5802,38292,49400,1084,1600,2048,2111,3006,6547,6699,9111,16080, + 555,667,720,801,1443,1533,2106,5560,6007,1090,1091,1114,1117,1119,1122,1131,1138, + 1151,1175,1199,1201,1271,1862,2323,2393,2394,2608,2725,2909,3003,3168,3221,3322, + 3324,3390,3517,3527,3800,3809,3814,3826,3869,3878,3889,3905,3914,3920,3945,3971, + 4004,4005,4279,4445,4550,4567,4848,4900,5033,5080,5087,5221,5440,5544,5678,5730, + 5811,5815,5850,5862,5906,5907,5950,5952,6025,6510,6565,6567,6689,6692,6779,6792, + 6839,7025,7496,7676,7800,7920,7921,7999,8022,8042,8045,8093,8099,8200,8290,8292, + 8300,8383,9003,9081,9099,9200,9418,9575,9878,9898,9917,10003,10180,10215,11111, + 12174,12265,14441,15004,16000,16113,17877,18040,18101,19350,25735,26214,27356, + 30951,32783,32785,40911,41511,44176,44501,49161,49167,49176,50300,50500,52673, + 52848,54045,54328,55056,56737,57797,60443,70,417,714,722,777,981,1009,2022,4224, + 4998,6346,301,524,668,765,2041,5999,10082,259,1007,1417,1434,1984,2038,2068,4343, + 6009,7004,44443,109,687,726,911,1461,2035,4125,6006,7201,9103,125,481,683,903, + 1011,1455,2013,2043,2047,6668,6669,256,406,843,2042,2045,5998,9929,31337,44442, + 1092,1095,1102,1105,1113,1121,1123,1126,1130,1132,1137,1141,1145,1147,1149,1154, + 1164,1165,1166,1174,1185,1187,1192,1198,1213,1216,1217,1233,1236,1244,1259,1277, + 1287,1300,1301,1309,1322,1328,1556,1641,1688,1719,1721,1805,1812,1839,1875,1914, + 1971,1972,1974,2099,2170,2196,2200,2288,2366,2382,2557,2800,2910,2920,2968,3007, + 3013,3050,3119,3304,3307,3376,3400,3410,3514,3684,3697,3700,3824,3846,3848,3859, + 3863,3870,3872,3888,3907,3916,3931,3941,3957,3963,3968,3969,3972,3990,3993,3994, + 4009,4040,4080,4096,4143,4147,4200,4252,4430,4555,4600,4658,4875,4949,5040,5063, + 5074,5151,5212,5223,5242,5279,5339,5353,5501,5807,5812,5818,5823,5868,5869,5899, + 5905,5909,5914,5918,5938,5940,5968,5981,6051,6060,6068,6203,6247,6500,6504,6520, + 6550,6600) + $numPorts-- + return $topPortList[0..$numPorts] + } + + function Parse-Ports + { + Param ( + [Parameter(Mandatory = $True)] [String] $Ports + ) + [int[]] $iPorts = @() + + foreach ($pRange in $Ports.Split(",")) + { + + #-1 is a special case for ping + if ($pRange -eq "-1") + { + [int[]] $portsToAdd = $pRange + } + elseif ($pRange.Contains("-")) + { + [int[]] $range = $pRange.Split("-").Trim() + if ($range.Count -ne 2 -or $pRange.Split("-")[0] -eq "" -or $pRange.split("-")[1] -eq "") + { + throw "Invalid port range" + } + + [int[]] $portsToAdd = $range[0]..$range[1] + } + else + { + [int[]] $portsToAdd = $pRange + } + + foreach ($p in $portsToAdd) + { + + [int] $p = $p + if ($p -lt -1 -or $p -gt 65535) + { + throw "Port $p out of range" + } + + $iPorts += $p + } + } + + return $iPorts + } + + function Parse-IpPorts + { + Param ( + [Parameter(Mandatory = $True)] [String] $PortFile + ) + + [int[]] $PortList = @() + + Get-Content $PortFile | ForEach-Object { + $PortList += @(Parse-Ports $_) + } + return $PortList + } + + function Remove-Ports + { + Param ( + [Parameter(Mandatory = $True)] [String] $xPorts, + [Parameter(Mandatory = $True)] [int[]] $portList + ) + [int[]] $iPorts = @() + [int[]] $xPorts = $xPorts.Split(",") + foreach ($p in $portList) + { + if (!$xPorts.Contains($p)) + { + $iPorts += $p + } + } + return $iPorts + } + + function Write-PortscanOut + { + Param ( + [Parameter(Mandatory = $True, ParameterSetName="Comment")] [string] $comment, + [Parameter(Mandatory = $True, ParameterSetName="HostOut")] [string] $outhost, + [Parameter(Mandatory = $True, ParameterSetName="HostOut")] [bool] $isUp, + [Parameter(Mandatory = $True, ParameterSetName="HostOut")] $openPorts, + [Parameter(Mandatory = $True, ParameterSetName="HostOut")] $closedPorts, + [Parameter(Mandatory = $True, ParameterSetName="HostOut")] $filteredPorts, + [Parameter()] [bool] $quiet, + [Parameter()] [bool] $Pn, + [Parameter()] [System.IO.StreamWriter] $grepStream, + [Parameter()] [System.Xml.XmlWriter] $xmlStream, + [Parameter()] [System.IO.StreamWriter] $readableStream + + ) + switch ($PSCmdlet.ParameterSetName) + { + "Comment" + { + if (!$quiet) { + Write-Output $comment + } + if ($grepStream) { + $grepStream.WriteLine("# " + $comment) + } + if ($xmlStream) { + $xmlStream.WriteComment($comment) + } + if ($readableStream) { + $readableStream.WriteLine($comment) + } + } + "HostOut" + { + $oPort = [string]::join(",", $openPorts.ToArray()) + $cPort = [string]::join(",", $closedPorts.ToArray()) + $fPort = [string]::join(",", $filteredPorts.ToArray()) + + if (!$quiet) { + if ($isUp -and !$Pn) { + Write-Output ("Host: {0,-25} Status: Up" -f $outhost) + } + if ($isUp -or $Pn) { + if ($oPort -ne "") { + Write-Output ("Host: {0,-25} Open Ports: {1,0}" -f $outhost, $oPort) + } + if ($cPort -ne "") { + Write-Output ("Host: {0,-25} Closed Ports: {1,0}" -f $outhost, $cPort) + } + if ($fPort -ne "") { + Write-Output ("Host: {0,-25} Filtered Ports: {1,0}" -f $outhost, $fPort) + } + } + elseif (!$Pn) { + Write-Output ("Host: {0,-25} Status: Down" -f $outhost) + } + + } + if ($grepStream) { + #for grepstream use tabs - can be ugly, but easier for regex + if ($isUp -and !$Pn) { + $grepStream.writeline("Host: $outhost`tStatus: Up") + } + if ($isUp -or $Pn) { + if ($oPort -ne "") { + $grepStream.writeline("Host: $outhost`tOpen Ports: $oPort") + } + if ($cPort -ne "") { + $grepStream.writeline("Host: $outhost`tClosed Ports: $cPort") + } + if ($fPort -ne "") { + $grepStream.writeline("Host: $outhost`tFiltered Ports: $fPort") + } + } + elseif (!$Pn) { + $grepStream.writeline("Host: $outhost`tStatus: Down") + } + } + if ($xmlStream) { + $xmlStream.WriteStartElement("Host") + + $xmlStream.WriteAttributeString("id", $outhost) + if (!$PN) { + if ($isUp) { + $xmlStream.WriteAttributeString("Status", "Up") + } + else { + $xmlStream.WriteAttributeString("Status", "Downs") + } + } + + $xmlStream.WriteStartElement("Ports") + foreach($p in $openPorts) { + $xmlStream.writestartElement("Port") + $xmlStream.WriteAttributeString("id", [string]$p) + $xmlStream.WriteAttributeString("state", "open") + $xmlStream.WriteEndElement() + + } + foreach ($p in $closedPorts) { + $xmlStream.writestartElement("Port") + $xmlStream.WriteAttributeString("id", [string]$p) + $xmlStream.WriteAttributeString("state", "closed") + $xmlStream.WriteEndElement() + } + foreach ($p in $filteredPorts) { + $xmlStream.writestartElement("Port") + $xmlStream.WriteAttributeString("id", [string]$p) + $xmlStream.WriteAttributeString("state", "filtered") + $xmlStream.WriteEndElement() + } + + $xmlStream.WriteEndElement() + $xmlStream.WriteEndElement() + } + if ($readableStream) { + $readableStream.writeline("Porscan.ps1 scan report for $outhost") + if ($isUp) { + $readableStream.writeline("Host is up") + } + + if ($isUp -or $Pn) { + + $readableStream.writeline(("{0,-10}{1,0}" -f "PORT", "STATE")) + + [int[]]$allports = $openPorts + $closedPorts + $filteredPorts + foreach($p in ($allports| Sort-Object)) + { + if ($openPorts.Contains($p)) { + $readableStream.writeline(("{0,-10}{1,0}" -f $p, "open")) + } + elseif ($closedPorts.Contains($p)) { + $readableStream.writeline(("{0,-10}{1,0}" -f $p, "closed")) + } + elseif ($filteredPorts.Contains($p)) { + $readableStream.writeline(("{0,-10}{1,0}" -f $p, "filtered")) + } + } + + } + elseif(!$Pn) { + $readableStream.writeline("Host is Down") + } + $readableStream.writeline("") + } + } + } + } + + + try + { + ######### + #parse arguments + ######### + + if ($Hosts) + { + foreach($h in $Hosts) + { + Parse-Hosts($h) | Out-Null + } + } + elseif ($iL) + { + Parse-ILHosts($iL) | Out-Null + } + if($exclude) + { + Exclude-Hosts($exclude) + } + + + if (($topPorts -and $Ports) -or ($topPorts -and $iP)) + { + throw "Cannot set topPorts with other specific ports" + } + if($Ports) + { + $portList += @(Parse-Ports($Ports)) + } + if($iP) + { + $portList += @(Parse-IpPorts($iP)) + } + if($portList.Length -eq 0) + { + if ($topPorts) + { + $portList += @(Get-TopPort($topPorts)) + } + else + { + #if the ports still aren't set, give the deftault, top 50 ports + $portList += @(Get-TopPort(50)) + } + } + if ($xPorts) + { + $portList = Remove-Ports -xPorts $xPorts -portList $portList + } + + if($T) + { + switch ($T) + { + 5 {$nHosts=40; $Threads = 1000; $Timeout = 750 } + 4 {$nHosts=30; $Threads = 1000; $Timeout = 1200 } + 3 {$nHosts=25; $Threads = 100; $Timeout = 2000 } + 2 {$nHosts=20; $Threads = 32; $Timeout = 2500 } + 1 {$nHosts=10; $Threads = 32; $Timeout = 5000 } + default { + throw "Invalid T parameter" + } + } + } + + if($oA) + { + if ($oG -or $oX -or $oN) { + Write-Warning "Both -oA specified with other output... going to ignore -oG/-oN/-oX" + } + $oG = $oA + ".gnmap" + $oX = $oA + ".xml" + $oN = $oA + ".nmap" + } + if ($oG) { + if (!$F -and (Test-Path $oG)) { + throw "Error: $oA already exists. Either delete the file or specify the -f flag" + } + $grepStream = [System.IO.StreamWriter] $oG + } + if ($oN) { + if (!$F -and (Test-Path $oN)) { + throw "Error: $oN already exists. Either delete the file or specify the -f flag" + } + $readableStream = [System.IO.StreamWriter] $oN + } + if ($oX) { + if (!$F -and (Test-Path $oX)) { + throw "Error: $oX already exists. Either delete the file or specify the -f flag" + } + + $xmlStream = [System.xml.xmlwriter]::Create([string]$oX) + $xmlStream.WriteStartDocument() + $xmlStream.WriteStartElement("Portscanrun") + $xmlStream.WriteAttributeString("version", $version) + + } + + $hostPortList += @(Parse-Ports($PS)) + + [Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath + + $startdate = Get-Date + $myInvocationLine = $PSCmdlet.MyInvocation.Line + $startMsg = "Invoke-Portscan.ps1 v$version scan initiated $startdate as: $myInvocationLine" + + Write-PortscanOut -comment $startMsg -quiet $q -grepStream $grepStream -xmlStream $xmlStream -readableStream $readableStream + + + #converting back from int array gives some argument error checking + $sPortList = [string]::join(",", $portList) + $sHostPortList = [string]::join(",", $hostPortList) + + + ######## + #Port Scan Code - run on a per host basis + ######## + $portScanCode = { + param ( + [Parameter( Mandatory = $True)] [string] $thost, + [Parameter( Mandatory = $True)][bool] $Pn, + [Parameter( Mandatory = $True)][bool] $sn, + [Parameter( Mandatory = $True)][int] $Timeout, + [Parameter( Mandatory = $True)][int[]] $PortList, + [Parameter( Mandatory = $True)][int[]] $hostPortList, + [Parameter( Mandatory = $True)][int] $maxthreads) + Process + { + $openPorts = New-Object System.Collections.ArrayList + $closedPorts = New-Object System.Collections.ArrayList + $filteredPorts = New-Object System.Collections.ArrayList + + $sockets = @{} + $timeouts = New-Object Hashtable + + #set maximum $async threads + $fThreads = New-Object int + $aThreads = New-Object int + [System.Threading.ThreadPool]::GetMaxThreads([ref]$fThreads, [ref]$aThreads) | Out-Null + [System.Threading.ThreadPool]::SetMaxThreads($fthreads,$maxthreads) | Out-Null + + function New-ScriptBlockCallback { + param( + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [scriptblock]$Callback + ) + + #taken from http://www.nivot.org/blog/post/2009/10/09/PowerShell20AsynchronousCallbacksFromNET + if (-not ("CallbackEventBridge" -as [type])) { + Add-Type @" + using System; + + public sealed class CallbackEventBridge + { + public event AsyncCallback CallbackComplete = delegate { }; + + private CallbackEventBridge() {} + + private void CallbackInternal(IAsyncResult result) + { + CallbackComplete(result); + } + + public AsyncCallback Callback + { + get { return new AsyncCallback(CallbackInternal); } + } + + public static CallbackEventBridge Create() + { + return new CallbackEventBridge(); + } + } +"@ + } + + $bridge = [CallbackEventBridge]::Create() + Register-ObjectEvent -InputObject $bridge -EventName CallbackComplete -Action $Callback | Out-Null + + $bridge.Callback + + } + + function Test-Port { + + Param ( + [Parameter(Mandatory = $True)] [String] $h, + [Parameter(Mandatory = $True)] [int] $p, + [Parameter(Mandatory = $True)] [int] $timeout + ) + + $sockets[$p] = new-object System.Net.Sockets.TcpClient + $scriptBlockAsString = @" + + #somewhat of a race condition with the timeout, but I don't think it matters + if ( `$sockets[$p] -ne `$NULL) + { + if (!`$timeouts[$p].Disposed) { + `$timeouts[$p].Dispose() + } + + `$status = `$sockets[$p].Connected; + if (`$status -eq `$True) + { + #write-host "$p is open" + `$openPorts.Add($p) + } + else + { + #write-host "$p is closed" + `$closedPorts.Add($p) + + } + `$sockets[$p].Close(); + + `$sockets.Remove($p) + } +"@ + $timeoutCallback = @" + #write-host "$p is filtered" + `$sockets[$p].Close() + if (!`$timeouts[$p].Disposed) { + `$timeouts[$p].Dispose() + `$filteredPorts.Add($p) + } + `$sockets.Remove($p) +"@ + + + $timeoutCallback = [scriptblock]::Create($timeoutCallback) + + $timeouts[$p] = New-Object System.Timers.Timer + Register-ObjectEvent -InputObject $timeouts[$p] -EventName Elapsed -Action $timeoutCallback | Out-Null + $timeouts[$p].Interval = $timeout + $timeouts[$p].Enabled = $true + + + $myscriptblock = [scriptblock]::Create($scriptBlockAsString) + $x = $sockets[$p].beginConnect($h, $p,(New-ScriptBlockCallback($myscriptblock)) , $null) + + } + + function PortScan-Alive + { + Param ( + [Parameter(Mandatory = $True)] [String] $h + ) + + Try + { + + #ping + if ($hostPortList.Contains(-1)) + { + $ping = new-object System.Net.NetworkInformation.Ping + $pResult = $ping.send($h) + if ($pResult.Status -eq "Success") + { + return $True + } + } + foreach($Port in $hostPortList) + { + if ($Port -ne -1) + { + Test-Port -h $h -p $Port -timeout $Timeout + } + } + + do { + if (($openPorts.Count -gt 0) -or ($closedPorts.Count -gt 0)) { + return $True + } + Start-Sleep -Milli 100 + } + While ($sockets.Count -gt 0) + + } + Catch + { + Write-Error "Exception trying to host scan $h" + Write-Error $_.Exception.Message; + } + + return $False + } + + function Portscan-Port + { + Param ( + [Parameter(Mandatory = $True)] [String] $h + ) + + $openPorts.clear() + $closedPorts.clear() + $filteredPorts.Clear() + + #$sPortlist = @($sPortList) + #$Timeout = $Timeout + + [string[]]$Ports = @() + + + foreach($Port in $Portlist) + { + Try + { + Test-Port -h $h -p $Port -timeout $Timeout + #tiny delay can makeit more responsive + #Start-Sleep -Milli 1 + + } + Catch + { + Write-Error "Exception trying to scan $h port $Port" + Write-Error $_.Exception.Message; + } + } + } + + if(!$Pn) + { + [bool] $hostResult = PortScan-Alive $thost + } + if((!$sn) -and ($hostResult -or $Pn)) + { + Portscan-Port $thost + } + while ($sockets.Count -gt 0) { + Start-Sleep -Milli 500 + } + + + return @($hostResult, $openPorts, $closedPorts, $filteredPorts) + } + } + + # the outer loop is to flush the loop. + # Otherwise Get-Job | Wait-Job could clog, etc + + [int]$saveIteration = 0 + [int]$computersDone=0 + [int]$upHosts=0 + while (($saveIteration * $syncFreq) -lt $hostList.Count) + { + + Get-Job | Remove-Job -Force + $sIndex = ($saveIteration*$syncFreq) + $eIndex = (($saveIteration+1)*$syncFreq)-1 + foreach ($iHost in $hostList[$sIndex..$eIndex]) + { + while ($(Get-Job -state Running).count -ge $nHosts) + { + Start-Sleep -Milliseconds $sleepTimer + } + + $computersDone++ + if($v) + { + Write-Progress -Activity "Port Scan" -CurrentOperation "starting computer $computersDone" -PercentComplete ($computersDone / $hostList.Count * 100) + } + + Start-Job -ScriptBlock $portScanCode -Name $iHost -ArgumentList @($iHost, $Pn, $sn, $Timeout, $portList, $hostPortList, $Threads) | Out-Null + + } + + Get-Job | Wait-Job | Out-Null + + foreach ($job in Get-Job) + { + $jobOut = @(Receive-Job $job) + [bool]$hostUp = $jobOut[0] + $jobName = $job.Name + + $openPorts = $jobOut[1] + $closedPorts = $jobOut[2] + $filteredPorts = $jobOut[3] + + if($hostUp) { + $upHosts ++ + } + + Write-PortscanOut -outhost $jobName -isUp $hostUp -openPorts $openPorts -closedPorts $closedPorts -filteredPorts $filteredPorts -grepStream $grepStream -xmlStream $xmlStream -readableStream $readableStream -quiet $q -Pn $Pn + + } + + if ($grepStream) { + $grepStream.flush() + } + if ($xmlStream) { + $xmlStream.flush() + } + if($readableStream) { + $readableStream.flush() + } + + $saveIteration ++ + } + + $enddate = Get-Date + $totaltime = ($enddate - $startdate).TotalSeconds + $endMsg = "Port scan complete at $enddate ($totaltime seconds)" + if (!$Pn) { + $endMsg += ", $upHosts hosts are up" + } + + Write-PortscanOut -comment $endMsg -quiet $q -grepStream $grepStream -xmlStream $xmlStream -readableStream $readableStream + + if($grepStream) { + $grepStream.Close() + } + if ($xmlStream) { + $xmlStream.Close() + } + if($readableStream) { + $readableStream.Close() + } + } + Catch + { + Write-Error $_.Exception.Message; + } + } +} + + diff --git a/Recon/Recon.psd1 b/Recon/Recon.psd1 index 59c6377..89c9d4f 100644 --- a/Recon/Recon.psd1 +++ b/Recon/Recon.psd1 @@ -74,7 +74,7 @@ ModuleList = @(@{ModuleName = 'Recon'; ModuleVersion = '1.0.0.0'; GUID = '7e775a # List of all files packaged with this module FileList = 'Recon.psm1', 'Recon.psd1', 'Get-GPPPassword.ps1', 'Get-HttpStatus.ps1', - 'Invoke-ReverseDnsLookup.ps1', 'Usage.md' + 'Invoke-ReverseDnsLookup.ps1', 'Invoke-Portscan.ps1', 'Usage.md' # Private data to pass to the module specified in RootModule/ModuleToProcess # PrivateData = '' -- cgit v1.2.3 From 9a5b1ae75ae6f3dc99a10ebcd72c94f45d27c0a7 Mon Sep 17 00:00:00 2001 From: Rich Lundeen Date: Sun, 9 Jun 2013 21:18:38 -0700 Subject: removed a few comments --- Recon/Invoke-Portscan.ps1 | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Recon/Invoke-Portscan.ps1 b/Recon/Invoke-Portscan.ps1 index 6696a17..8a8a7cb 100644 --- a/Recon/Invoke-Portscan.ps1 +++ b/Recon/Invoke-Portscan.ps1 @@ -881,9 +881,6 @@ http://webstersprodigy.net $closedPorts.clear() $filteredPorts.Clear() - #$sPortlist = @($sPortList) - #$Timeout = $Timeout - [string[]]$Ports = @() @@ -892,9 +889,6 @@ http://webstersprodigy.net Try { Test-Port -h $h -p $Port -timeout $Timeout - #tiny delay can makeit more responsive - #Start-Sleep -Milli 1 - } Catch { -- cgit v1.2.3 From 03e0a0b489fdbc910010a1416ed2a4869b30a261 Mon Sep 17 00:00:00 2001 From: Rich Lundeen Date: Mon, 10 Jun 2013 16:09:07 -0700 Subject: fixing powershell 2.0 compat --- Recon/Invoke-Portscan.ps1 | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Recon/Invoke-Portscan.ps1 b/Recon/Invoke-Portscan.ps1 index 8a8a7cb..01fc2c8 100644 --- a/Recon/Invoke-Portscan.ps1 +++ b/Recon/Invoke-Portscan.ps1 @@ -57,12 +57,12 @@ http://webstersprodigy.net ValueFromPipeline=$True, Mandatory = $True, HelpMessage = "include these comma seperated hosts (supports IPv4 CIDR notation), or pipe them in" )] - [String[]] $Hosts, + [String[]] $Hosts, [Parameter(ParameterSetName="fHosts", Mandatory = $True, HelpMessage = "input hosts from file")] - [String] $iL, + [String] $iL, [Parameter(Mandatory = $False, HelpMessage = "exclude these comma seperated hosts")] @@ -192,14 +192,19 @@ http://webstersprodigy.net throw "Bad host mask" } - $numhosts = 1 -shl (($address.GetAddressBytes().Length *8) - $maskPart) + #For ps 2.0 compatability, use math pow rather than shl + $numhosts = [System.math]::Pow(2,(($address.GetAddressBytes().Length *8) - $maskPart)) #Get start address $startAddress = $address.GetAddressBytes() $numbits = $startAddress.Length * 8 [array]::Reverse($startAddress) + $startAddress = ([System.Numerics.BigInteger] [byte[]]$startAddress) - $startAddress = $startAddress -band ([System.Numerics.BigInteger]::Pow(2, $maskPart)-1 -shl ($numbits - $maskPart)) + + $startMask = ([System.Numerics.BigInteger]::Pow(2, $maskPart)-1) * ([System.Math]::Pow(2,($numbits - $maskPart))) + $startAddress = $startAddress -band $startMask + $startAddress = $startAddress.ToByteArray() [array]::Reverse($startAddress) @@ -648,6 +653,10 @@ http://webstersprodigy.net } } + $grepStream = $null + $xmlStream = $null + $readableStream = $null + if($oA) { if ($oG -or $oX -or $oN) { @@ -688,10 +697,10 @@ http://webstersprodigy.net $startdate = Get-Date $myInvocationLine = $PSCmdlet.MyInvocation.Line $startMsg = "Invoke-Portscan.ps1 v$version scan initiated $startdate as: $myInvocationLine" + #$grepStream = $null Write-PortscanOut -comment $startMsg -quiet $q -grepStream $grepStream -xmlStream $xmlStream -readableStream $readableStream - #converting back from int array gives some argument error checking $sPortList = [string]::join(",", $portList) $sHostPortList = [string]::join(",", $hostPortList) @@ -927,11 +936,14 @@ http://webstersprodigy.net Get-Job | Remove-Job -Force $sIndex = ($saveIteration*$syncFreq) $eIndex = (($saveIteration+1)*$syncFreq)-1 + foreach ($iHost in $hostList[$sIndex..$eIndex]) { - while ($(Get-Job -state Running).count -ge $nHosts) + $ctr = @(Get-Job -state Running) + while ($ctr.Count -ge $nHosts) { Start-Sleep -Milliseconds $sleepTimer + $ctr = @(Get-Job -state Running) } $computersDone++ -- cgit v1.2.3 From 3ec7b95f8d586938c53c648a38a6b163deced8bf Mon Sep 17 00:00:00 2001 From: Rich Lundeen Date: Tue, 11 Jun 2013 10:22:37 -0700 Subject: Powershell 2.0 fixes - should work now --- Recon/Invoke-Portscan.ps1 | 289 ++++++++++++++++++++++++++-------------------- 1 file changed, 165 insertions(+), 124 deletions(-) diff --git a/Recon/Invoke-Portscan.ps1 b/Recon/Invoke-Portscan.ps1 index 01fc2c8..d0e3fcf 100644 --- a/Recon/Invoke-Portscan.ps1 +++ b/Recon/Invoke-Portscan.ps1 @@ -17,7 +17,7 @@ Does a simple port scan using regular sockets, based (pretty) loosely on nmap .NOTES -version .11 +version .12 .EXAMPLE @@ -58,110 +58,110 @@ http://webstersprodigy.net Mandatory = $True, HelpMessage = "include these comma seperated hosts (supports IPv4 CIDR notation), or pipe them in" )] [String[]] $Hosts, - + [Parameter(ParameterSetName="fHosts", Mandatory = $True, HelpMessage = "input hosts from file")] - [String] $iL, + [String] $iL, [Parameter(Mandatory = $False, - HelpMessage = "exclude these comma seperated hosts")] + HelpMessage = "exclude these comma seperated hosts")] [String] $exclude, [Parameter(Mandatory = $False, - HelpMessage = "include these comma seperated ports (can also be a range like 80-90)")] + HelpMessage = "include these comma seperated ports (can also be a range like 80-90)")] [String] $Ports, [Parameter(Mandatory = $False, - HelpMessage = "input ports from a file")] + HelpMessage = "input ports from a file")] [String] $iP, [Parameter(Mandatory = $False, - HelpMessage = "include the x top ports - only goes to 1000, default is top 50")] + HelpMessage = "include the x top ports - only goes to 1000, default is top 50")] [String] $topPorts, [Parameter(Mandatory = $False, - HelpMessage = "exclude these comma seperated ports")] + HelpMessage = "exclude these comma seperated ports")] [String] $xPorts, #Host Discovery [Parameter(Mandatory = $False, - HelpMessage = "treat all hosts as online, skip host discovery")] + HelpMessage = "treat all hosts as online, skip host discovery")] [Switch] $Pn, [Parameter(Mandatory = $False, - HelpMessage = "Ping scan only (disable port scan)")] + HelpMessage = "Ping scan only (disable port scan)")] [Switch] $sn, [Parameter(Mandatory = $False, - HelpMessage = "comma separated ports for discovery. -1 is a ping")] + HelpMessage = "comma separated ports for discovery. -1 is a ping")] [string] $PS = "-1,445,80,443", #Timing and Performance [Parameter(Mandatory = $False, - HelpMessage = "number of max threads for the thread pool (per host)")] + HelpMessage = "number of max threads for the thread pool (per host)")] [int] $Threads = 100, [Parameter(Mandatory = $False, - HelpMessage = "number of hosts to concurrently scan")] + HelpMessage = "number of hosts to concurrently scan")] [int] $nHosts = 25, - + [Parameter(Mandatory = $False, - HelpMessage = "timeout time on a connection in miliseconds")] + HelpMessage = "timeout time on a connection in miliseconds")] [int] $Timeout = 2000, [Parameter(Mandatory = $False, - HelpMessage = "wait before thread checking, in miliseconds")] - [int] $sleepTimer = 500, + HelpMessage = "wait before thread checking, in miliseconds")] + [int] $sleepTimer = 500, [Parameter(Mandatory = $False, - HelpMessage = "how often (in terms of hosts) to sync threads and flush output")] - [int] $syncFreq = 1024, + HelpMessage = "how often (in terms of hosts) to sync threads and flush output")] + [int] $syncFreq = 1024, [Parameter(Mandatory = $False, - HelpMessage = "[0-5] shortcut performance options. Default is 3. higher is more aggressive. Sets (nhosts, threads,timeout) - 5: (40,1000,750) 4: (30,1000,1200) 3: (25,100,2000) 2:(20,32,2500) 1:(10,32,5000)")] - [int] $T, + HelpMessage = "[0-5] shortcut performance options. Default is 3. higher is more aggressive. Sets (nhosts, threads,timeout) + 5: (40,1000,750) 4: (30,1000,1200) 3: (25,100,2000) 2:(20,32,2500) 1:(10,32,5000)")] + [int] $T, #Output [Parameter(Mandatory = $False, - HelpMessage = "Greppable output file")] + HelpMessage = "Greppable output file")] [String] $oG, [Parameter(Mandatory = $False, - HelpMessage = "output in xml")] + HelpMessage = "output in xml")] [String] $oX, [Parameter(Mandatory = $False, - HelpMessage = "output in 'readable' format")] + HelpMessage = "output in 'readable' format")] [String] $oN, [Parameter(Mandatory = $False, - HelpMessage = "output in readable and xml format in addition to greppable.")] + HelpMessage = "output in readable and xml format in addition to greppable.")] [String] $oA, [Parameter(Mandatory = $False, - HelpMessage = "gives a progress meter")] + HelpMessage = "gives a progress meter")] [Switch] $v, [Parameter(Mandatory = $False, - HelpMessage = "supresses output")] + HelpMessage = "supresses output")] [Switch] $q, [Parameter(Mandatory = $False, - HelpMessage = "Force Overwrite if output Files exist. Otherwise it throws exception")] + HelpMessage = "Force Overwrite if output Files exist. Otherwise it throws exception")] [Switch] $F - + #TODO add script parameter #TODO add resume parameter ) PROCESS { - $version = .11 + $version = .12 $hostList = New-Object System.Collections.ArrayList - [int[]]$portList = @() - [int[]]$hostPortList = @() + $portList = New-Object System.Collections.ArrayList + $hostPortList = New-Object System.Collections.ArrayList function Parse-Hosts { @@ -179,57 +179,96 @@ http://webstersprodigy.net { continue } - + if($iHost.contains("/")) { $netPart = $iHost.split("/")[0] [uint32]$maskPart = $iHost.split("/")[1] $address = [System.Net.IPAddress]::Parse($netPart) - + if ($maskPart -ge $address.GetAddressBytes().Length * 8) { throw "Bad host mask" } - #For ps 2.0 compatability, use math pow rather than shl - $numhosts = [System.math]::Pow(2,(($address.GetAddressBytes().Length *8) - $maskPart)) + $numhosts = [System.math]::Pow(2,(($address.GetAddressBytes().Length *8) - $maskPart)) - #Get start address - $startAddress = $address.GetAddressBytes() - $numbits = $startAddress.Length * 8 - [array]::Reverse($startAddress) + #if address is ipv4 then parse cidr the easy way + #Once 3.0 support is more universal, this can be taken out and go directly to the 'else' + if ($address.AddressFamily -eq "InterNetwork") + { - $startAddress = ([System.Numerics.BigInteger] [byte[]]$startAddress) + $startaddress = $address.GetAddressBytes() + [array]::Reverse($startaddress) - $startMask = ([System.Numerics.BigInteger]::Pow(2, $maskPart)-1) * ([System.Math]::Pow(2,($numbits - $maskPart))) - $startAddress = $startAddress -band $startMask + $startaddress = [System.BitConverter]::ToUInt32($startaddress, 0) + [uint32]$startMask = ([System.math]::Pow(2, $maskPart)-1) * ([System.Math]::Pow(2,(32 - $maskPart))) + $startAddress = $startAddress -band $startMask - $startAddress = $startAddress.ToByteArray() - [array]::Reverse($startAddress) + #in powershell 2.0 there are 4 0 bytes padded, so the [0..3] is necessary + $startAddress = [System.BitConverter]::GetBytes($startaddress)[0..3] + [array]::Reverse($startaddress) - #strip out leading 0 put in by BigIneger, if any - if ($startAddress[0] -eq 0) - { - $startAddress = $startAddress[1..$startAddress.Length] - } + $address = [System.Net.IPAddress] [byte[]] $startAddress + + $hostList.Add($address.IPAddressToString) + + for ($i=0; $i -lt $numhosts-1; $i++) + { + + $nextAddress = $address.GetAddressBytes() + [array]::Reverse($nextAddress) + $nextAddress = [System.BitConverter]::ToUInt32($nextAddress, 0) + $nextAddress ++ + $nextAddress = [System.BitConverter]::GetBytes($nextAddress)[0..3] + [array]::Reverse($nextAddress) + + $address = [System.Net.IPAddress] [byte[]] $nextAddress + $hostList.Add($address.IPAddressToString) + + } - $address = [System.Net.IPAddress] [byte[]] $startAddress - $hostList.Add($address.IPAddressToString) + } - - for ($i=0; $i -lt $numhosts-1; $i++) + #if ipv6 CIDR notation, then there's a ps 3.0 requirement due to biginteger + else { - $nextAddress = $address.GetAddressBytes() - [array]::Reverse($nextAddress) - $nextAddress = ([System.Numerics.BigInteger] [byte[]]$nextAddress) + 1 - $nextAddress = $nextAddress.ToByteArray() - [array]::Reverse($nextAddress) - $address = [System.Net.IPAddress] [byte[]] $nextAddress + #Get start address + $startAddress = $address.GetAddressBytes() + $numbits = $startAddress.Length * 8 + [array]::Reverse($startAddress) + + $startAddress = ([System.Numerics.BigInteger] [byte[]]$startAddress) + + $startMask = ([System.Numerics.BigInteger]::Pow(2, $maskPart)-1) * ([System.Math]::Pow(2,(128 - $maskPart))) + $startAddress = $startAddress -band $startMask + + $startAddress = $startAddress.ToByteArray() + [array]::Reverse($startAddress) + #strip out leading 0 put in by BigIneger, if any + if ($startAddress[0] -eq 0) + { + $startAddress = $startAddress[1..$startAddress.Length] + } + + $address = [System.Net.IPAddress] [byte[]] $startAddress $hostList.Add($address.IPAddressToString) + for ($i=0; $i -lt $numhosts-1; $i++) + { + $nextAddress = $address.GetAddressBytes() + [array]::Reverse($nextAddress) + $nextAddress = ([System.Numerics.BigInteger] [byte[]]$nextAddress) + 1 + $nextAddress = $nextAddress.ToByteArray() + [array]::Reverse($nextAddress) + + $address = [System.Net.IPAddress] [byte[]] $nextAddress + $hostList.Add($address.IPAddressToString) + + } } } else @@ -354,23 +393,23 @@ http://webstersprodigy.net 5905,5909,5914,5918,5938,5940,5968,5981,6051,6060,6068,6203,6247,6500,6504,6520, 6550,6600) $numPorts-- - return $topPortList[0..$numPorts] + $portList.AddRange($topPortList[0..$numPorts]) } function Parse-Ports { Param ( - [Parameter(Mandatory = $True)] [String] $Ports + [Parameter(Mandatory = $True)] [String] $Ports, + [Parameter(Mandatory = $True)] $pList ) - [int[]] $iPorts = @() - + foreach ($pRange in $Ports.Split(",")) { #-1 is a special case for ping - if ($pRange -eq "-1") + if ($pRange -eq "-1") { - [int[]] $portsToAdd = $pRange + $pList.Add([int]$pRange) } elseif ($pRange.Contains("-")) { @@ -380,27 +419,23 @@ http://webstersprodigy.net throw "Invalid port range" } - [int[]] $portsToAdd = $range[0]..$range[1] + $pList.AddRange($range[0]..$range[1]) } else { - [int[]] $portsToAdd = $pRange + $pList.Add([int]$pRange) } - foreach ($p in $portsToAdd) - { - - [int] $p = $p - if ($p -lt -1 -or $p -gt 65535) - { - throw "Port $p out of range" - } - $iPorts += $p + } + foreach ($p in $pList) + { + if ($p -lt -1 -or $p -gt 65535) + { + throw "Port $p out of range" } } - return $iPorts } function Parse-IpPorts @@ -409,30 +444,23 @@ http://webstersprodigy.net [Parameter(Mandatory = $True)] [String] $PortFile ) - [int[]] $PortList = @() - Get-Content $PortFile | ForEach-Object { - $PortList += @(Parse-Ports $_) + Parse-Ports -Ports $_ -pList $portList } - return $PortList } function Remove-Ports { Param ( - [Parameter(Mandatory = $True)] [String] $xPorts, - [Parameter(Mandatory = $True)] [int[]] $portList + [Parameter(Mandatory = $True)] [String] $xPorts ) - [int[]] $iPorts = @() + [int[]] $xPorts = $xPorts.Split(",") - foreach ($p in $portList) + + foreach ($x in $xPorts) { - if (!$xPorts.Contains($p)) - { - $iPorts += $p - } + $portList.Remove($x) } - return $iPorts } function Write-PortscanOut @@ -558,10 +586,10 @@ http://webstersprodigy.net } if ($isUp -or $Pn) { - + $readableStream.writeline(("{0,-10}{1,0}" -f "PORT", "STATE")) - [int[]]$allports = $openPorts + $closedPorts + $filteredPorts + [int[]]$allports = $openPorts + $closedPorts + $filteredPorts foreach($p in ($allports| Sort-Object)) { if ($openPorts.Contains($p)) { @@ -584,10 +612,28 @@ http://webstersprodigy.net } } } - - + + #function for Powershell v2.0 to work + function Convert-SwitchtoBool + { + Param ( + [Parameter(Mandatory = $True)] $switchValue + ) + If ($switchValue) { + return $True + } + return $False + } + + try { + + [bool] $Pn = Convert-SwitchtoBool ($Pn) + $sn = Convert-SwitchtoBool ($sn) + $q = Convert-SwitchtoBool ($q) + $F = Convert-SwitchtoBool ($F) + ######### #parse arguments ######### @@ -607,35 +653,33 @@ http://webstersprodigy.net { Exclude-Hosts($exclude) } - - if (($topPorts -and $Ports) -or ($topPorts -and $iP)) { throw "Cannot set topPorts with other specific ports" } if($Ports) { - $portList += @(Parse-Ports($Ports)) + Parse-Ports -Ports $Ports -pList $portList | Out-Null } if($iP) { - $portList += @(Parse-IpPorts($iP)) + Parse-IpPorts($iP) | Out-Null } - if($portList.Length -eq 0) + if($portList.Count -eq 0) { if ($topPorts) { - $portList += @(Get-TopPort($topPorts)) + Get-TopPort($topPorts) | Out-Null } else { #if the ports still aren't set, give the deftault, top 50 ports - $portList += @(Get-TopPort(50)) + Get-TopPort(50) | Out-Null } } if ($xPorts) { - $portList = Remove-Ports -xPorts $xPorts -portList $portList + Remove-Ports -xPorts $xPorts | Out-Null } if($T) @@ -690,14 +734,13 @@ http://webstersprodigy.net } - $hostPortList += @(Parse-Ports($PS)) + Parse-Ports -Ports $PS -pList $hostPortList | Out-Null [Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath - + $startdate = Get-Date $myInvocationLine = $PSCmdlet.MyInvocation.Line $startMsg = "Invoke-Portscan.ps1 v$version scan initiated $startdate as: $myInvocationLine" - #$grepStream = $null Write-PortscanOut -comment $startMsg -quiet $q -grepStream $grepStream -xmlStream $xmlStream -readableStream $readableStream @@ -715,8 +758,8 @@ http://webstersprodigy.net [Parameter( Mandatory = $True)][bool] $Pn, [Parameter( Mandatory = $True)][bool] $sn, [Parameter( Mandatory = $True)][int] $Timeout, - [Parameter( Mandatory = $True)][int[]] $PortList, - [Parameter( Mandatory = $True)][int[]] $hostPortList, + [Parameter( Mandatory = $True)] $PortList, + [Parameter( Mandatory = $True)] $hostPortList, [Parameter( Mandatory = $True)][int] $maxthreads) Process { @@ -744,23 +787,23 @@ http://webstersprodigy.net if (-not ("CallbackEventBridge" -as [type])) { Add-Type @" using System; - + public sealed class CallbackEventBridge { public event AsyncCallback CallbackComplete = delegate { }; - + private CallbackEventBridge() {} - + private void CallbackInternal(IAsyncResult result) { CallbackComplete(result); } - + public AsyncCallback Callback { get { return new AsyncCallback(CallbackInternal); } } - + public static CallbackEventBridge Create() { return new CallbackEventBridge(); @@ -794,10 +837,10 @@ http://webstersprodigy.net `$timeouts[$p].Dispose() } - `$status = `$sockets[$p].Connected; + `$status = `$sockets[$p].Connected; if (`$status -eq `$True) { - #write-host "$p is open" + #write-host "$p is open" `$openPorts.Add($p) } else @@ -859,7 +902,7 @@ http://webstersprodigy.net if ($Port -ne -1) { Test-Port -h $h -p $Port -timeout $Timeout - } + } } do { @@ -869,7 +912,7 @@ http://webstersprodigy.net Start-Sleep -Milli 100 } While ($sockets.Count -gt 0) - + } Catch { @@ -906,6 +949,7 @@ http://webstersprodigy.net } } } + [bool] $hostResult = $False if(!$Pn) { @@ -919,11 +963,11 @@ http://webstersprodigy.net Start-Sleep -Milli 500 } - return @($hostResult, $openPorts, $closedPorts, $filteredPorts) - } + } } + # the outer loop is to flush the loop. # Otherwise Get-Job | Wait-Job could clog, etc @@ -949,11 +993,10 @@ http://webstersprodigy.net $computersDone++ if($v) { - Write-Progress -Activity "Port Scan" -CurrentOperation "starting computer $computersDone" -PercentComplete ($computersDone / $hostList.Count * 100) + Write-Progress -status "Port Scanning" -Activity "Port Scan" -CurrentOperation "starting computer $computersDone" -PercentComplete ($computersDone / $hostList.Count * 100) } Start-Job -ScriptBlock $portScanCode -Name $iHost -ArgumentList @($iHost, $Pn, $sn, $Timeout, $portList, $hostPortList, $Threads) | Out-Null - } Get-Job | Wait-Job | Out-Null @@ -971,9 +1014,7 @@ http://webstersprodigy.net if($hostUp) { $upHosts ++ } - Write-PortscanOut -outhost $jobName -isUp $hostUp -openPorts $openPorts -closedPorts $closedPorts -filteredPorts $filteredPorts -grepStream $grepStream -xmlStream $xmlStream -readableStream $readableStream -quiet $q -Pn $Pn - } if ($grepStream) { -- cgit v1.2.3 From af49f5cfaf656597a687c54498d6811b103d2751 Mon Sep 17 00:00:00 2001 From: Rich Lundeen Date: Tue, 11 Jun 2013 10:48:12 -0700 Subject: small style update --- Recon/Invoke-Portscan.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Recon/Invoke-Portscan.ps1 b/Recon/Invoke-Portscan.ps1 index d0e3fcf..d227293 100644 --- a/Recon/Invoke-Portscan.ps1 +++ b/Recon/Invoke-Portscan.ps1 @@ -630,9 +630,9 @@ http://webstersprodigy.net { [bool] $Pn = Convert-SwitchtoBool ($Pn) - $sn = Convert-SwitchtoBool ($sn) - $q = Convert-SwitchtoBool ($q) - $F = Convert-SwitchtoBool ($F) + [bool] $sn = Convert-SwitchtoBool ($sn) + [bool] $q = Convert-SwitchtoBool ($q) + [bool] $F = Convert-SwitchtoBool ($F) ######### #parse arguments -- cgit v1.2.3 From 223527d4cdf1fd227dda53ea3768fc57aa1552ce Mon Sep 17 00:00:00 2001 From: Rich Lundeen Date: Tue, 18 Jun 2013 13:17:06 -0700 Subject: Addressed mattifestation feedback See https://github.com/mattifestation/PowerSploit/pull/6#issuecomment-19289063 1) I like this feedback a lot and took it. 2) I tried going thread only but it got messed up with very large scans. Eventually, I didn't think it was worth the amount of effort to make it reliable with only threads 3) Tried to do this 4) Did this 5) I like the idea in general and I took this one place (top-ports), but not for the two examples you gave. The reasoning is, I want people to be able to specify various options and arrays aren't that flexible. For example, I want people to specify a port list like "80,90,8080-8090". Similar with CIDR, since that's one option, but they could also be specifying hostnames e.g. "google.com,192.168.1.1/24,10.0.0.1" --- Recon/Invoke-Portscan.ps1 | 510 +++++++++++++++++++++++++--------------------- 1 file changed, 275 insertions(+), 235 deletions(-) diff --git a/Recon/Invoke-Portscan.ps1 b/Recon/Invoke-Portscan.ps1 index d227293..bba5821 100644 --- a/Recon/Invoke-Portscan.ps1 +++ b/Recon/Invoke-Portscan.ps1 @@ -17,15 +17,115 @@ Does a simple port scan using regular sockets, based (pretty) loosely on nmap .NOTES -version .12 +version .13 + + +.PARAMETER Hosts + +Include these comma seperated hosts (supports IPv4 CIDR notation) or pipe them in + +.PARAMETER HostFile + +Input hosts from file rather than commandline + +.PARAMETER ExcludeHosts + +Exclude these comma seperated hosts + +.PARAMETER Ports + +Include these comma seperated ports (can also be a range like 80-90) + +.PARAMETER PortFile + +Input ports from a file + +.PARAMETER TopPorts + +Include the x top ports - only goes to 1000, default is top 50 + +.PARAMETER ExcludedPorts + +Exclude these comma seperated ports + +.PARAMETER SkipDiscovery + +Treat all hosts as online, skip host discovery + +.PARAMETER PingOnly + +Ping scan only (disable port scan) + +.PARAMETER DiscoveryPorts + +Comma separated ports used for host discovery. -1 is a ping + +.PARAMETER Threads + +number of max threads for the thread pool (per host) + +.PARAMETER nHosts + +number of hosts to concurrently scan + +.PARAMETER Timeout + +Timeout time on a connection in miliseconds before port is declared filtered + +.PARAMETER SleepTimer + +Wait before thread checking, in miliseconds + +.PARAMETER SyncFreq + +How often (in terms of hosts) to sync threads and flush output + +.PARAMETER T + +[0-5] shortcut performance options. Default is 3. higher is more aggressive. Sets (nhosts, threads,timeout) + 5 {$nHosts=30; $Threads = 1000; $Timeout = 750 } + 4 {$nHosts=25; $Threads = 1000; $Timeout = 1200 } + 3 {$nHosts=20; $Threads = 100; $Timeout = 2500 } + 2 {$nHosts=15; $Threads = 32; $Timeout = 3000 } + 1 {$nHosts=10; $Threads = 32; $Timeout = 5000 } + + +.PARAMETER GrepOut + +Greppable output file + +.PARAMETER XmlOut + +output XML file + +.PARAMETER ReadableOut + +output file in 'readable' format + +.PARAMETER AllformatsOut + +output in readable (.nmap), xml (.xml), and greppable (.gnmap) formats + +.PARAMETER noProgressMeter + +Suppresses the progress meter + +.PARAMETER quiet + +supresses returned output and don't store hosts in memory - useful for very large scans + +.PARAMETER ForceOverwrite + +Force Overwrite if output Files exist. Otherwise it throws exception + .EXAMPLE -C:\PS> Invoke-Portscan -v -Hosts "webstersprodigy.net,google.com,microsoft.com" -topPorts 30 +C:\PS> Invoke-Portscan -Hosts "webstersprodigy.net,google.com,microsoft.com" -TopPorts 50 Description ----------- -Scans the top 30 ports for hosts found for webstersprodigy.net,google.com, and microsoft.com +Scans the top 50 ports for hosts found for webstersprodigy.net,google.com, and microsoft.com .EXAMPLE @@ -39,7 +139,7 @@ Does a portscan of "webstersprodigy.net", and writes a greppable output file .EXAMPLE -C:\PS> Invoke-Portscan -Hosts 192.168.1.1/24 -T 4 -topPorts 25 -v -oA localnet +C:\PS> Invoke-Portscan -Hosts 192.168.1.1/24 -T 4 -TopPorts 25 -oA localnet Description ----------- @@ -55,102 +155,92 @@ http://webstersprodigy.net #Host, Ports [Parameter(ParameterSetName="cmdHosts", ValueFromPipeline=$True, - Mandatory = $True, - HelpMessage = "include these comma seperated hosts (supports IPv4 CIDR notation), or pipe them in" )] + Mandatory = $True)] [String[]] $Hosts, [Parameter(ParameterSetName="fHosts", - Mandatory = $True, - HelpMessage = "input hosts from file")] - [String] $iL, + Mandatory = $True)] + [Alias("iL")] + [String] $HostFile, - [Parameter(Mandatory = $False, - HelpMessage = "exclude these comma seperated hosts")] - [String] $exclude, + [Parameter(Mandatory = $False)] + [Alias("exclude")] + [String] $ExcludeHosts, - [Parameter(Mandatory = $False, - HelpMessage = "include these comma seperated ports (can also be a range like 80-90)")] + [Parameter(Mandatory = $False)] + [Alias("p")] [String] $Ports, - [Parameter(Mandatory = $False, - HelpMessage = "input ports from a file")] - [String] $iP, + [Parameter(Mandatory = $False)] + [Alias("iP")] + [String] $PortFile, - [Parameter(Mandatory = $False, - HelpMessage = "include the x top ports - only goes to 1000, default is top 50")] - [String] $topPorts, + [Parameter(Mandatory = $False)] + [String] $TopPorts, - [Parameter(Mandatory = $False, - HelpMessage = "exclude these comma seperated ports")] - [String] $xPorts, + [Parameter(Mandatory = $False)] + [Alias("xPorts")] + [String] $ExcludedPorts, #Host Discovery - [Parameter(Mandatory = $False, - HelpMessage = "treat all hosts as online, skip host discovery")] - [Switch] $Pn, + [Parameter(Mandatory = $False)] + [Alias("Pn")] + [Switch] $SkipDiscovery, - [Parameter(Mandatory = $False, - HelpMessage = "Ping scan only (disable port scan)")] - [Switch] $sn, + [Parameter(Mandatory = $False)] + [Alias("sn")] + [Switch] $PingOnly, - [Parameter(Mandatory = $False, - HelpMessage = "comma separated ports for discovery. -1 is a ping")] - [string] $PS = "-1,445,80,443", + [Parameter(Mandatory = $False)] + [Alias("PS")] + [string] $DiscoveryPorts = "-1,445,80,443", #Timing and Performance - [Parameter(Mandatory = $False, - HelpMessage = "number of max threads for the thread pool (per host)")] + [Parameter(Mandatory = $False)] [int] $Threads = 100, - [Parameter(Mandatory = $False, - HelpMessage = "number of hosts to concurrently scan")] + [Parameter(Mandatory = $False)] [int] $nHosts = 25, - [Parameter(Mandatory = $False, - HelpMessage = "timeout time on a connection in miliseconds")] + [Parameter(Mandatory = $False)] [int] $Timeout = 2000, - [Parameter(Mandatory = $False, - HelpMessage = "wait before thread checking, in miliseconds")] - [int] $sleepTimer = 500, + [Parameter(Mandatory = $False)] + [int] $SleepTimer = 500, - [Parameter(Mandatory = $False, - HelpMessage = "how often (in terms of hosts) to sync threads and flush output")] - [int] $syncFreq = 1024, + [Parameter(Mandatory = $False)] + [int] $SyncFreq = 1024, - [Parameter(Mandatory = $False, - HelpMessage = "[0-5] shortcut performance options. Default is 3. higher is more aggressive. Sets (nhosts, threads,timeout) - 5: (40,1000,750) 4: (30,1000,1200) 3: (25,100,2000) 2:(20,32,2500) 1:(10,32,5000)")] + [Parameter(Mandatory = $False)] [int] $T, #Output - [Parameter(Mandatory = $False, - HelpMessage = "Greppable output file")] - [String] $oG, + [Parameter(Mandatory = $False)] + [Alias("oG")] + [String] $GrepOut, - [Parameter(Mandatory = $False, - HelpMessage = "output in xml")] - [String] $oX, + [Parameter(Mandatory = $False)] + [Alias("oX")] + [String] $XmlOut, - [Parameter(Mandatory = $False, - HelpMessage = "output in 'readable' format")] - [String] $oN, + [Parameter(Mandatory = $False)] + [Alias("oN")] + [String] $ReadableOut, - [Parameter(Mandatory = $False, - HelpMessage = "output in readable and xml format in addition to greppable.")] - [String] $oA, + [Parameter(Mandatory = $False)] + [Alias("oA")] + [String] $AllformatsOut, - [Parameter(Mandatory = $False, - HelpMessage = "gives a progress meter")] - [Switch] $v, + [Parameter(Mandatory = $False)] + [Switch] $noProgressMeter, - [Parameter(Mandatory = $False, - HelpMessage = "supresses output")] - [Switch] $q, + [Parameter(Mandatory = $False)] + [Alias("q")] + [Switch] $quiet, - [Parameter(Mandatory = $False, - HelpMessage = "Force Overwrite if output Files exist. Otherwise it throws exception")] - [Switch] $F + [Parameter(Mandatory = $False)] + [Alias("F")] + [Switch] $ForceOverwrite #TODO add script parameter #TODO add resume parameter @@ -158,11 +248,13 @@ http://webstersprodigy.net PROCESS { - $version = .12 + $version = .13 $hostList = New-Object System.Collections.ArrayList $portList = New-Object System.Collections.ArrayList $hostPortList = New-Object System.Collections.ArrayList + $scannedHostList = @() + function Parse-Hosts { Param ( @@ -194,82 +286,36 @@ http://webstersprodigy.net $numhosts = [System.math]::Pow(2,(($address.GetAddressBytes().Length *8) - $maskPart)) - #if address is ipv4 then parse cidr the easy way - #Once 3.0 support is more universal, this can be taken out and go directly to the 'else' - if ($address.AddressFamily -eq "InterNetwork") - { - - $startaddress = $address.GetAddressBytes() - [array]::Reverse($startaddress) - - $startaddress = [System.BitConverter]::ToUInt32($startaddress, 0) - [uint32]$startMask = ([System.math]::Pow(2, $maskPart)-1) * ([System.Math]::Pow(2,(32 - $maskPart))) - $startAddress = $startAddress -band $startMask - - #in powershell 2.0 there are 4 0 bytes padded, so the [0..3] is necessary - $startAddress = [System.BitConverter]::GetBytes($startaddress)[0..3] - [array]::Reverse($startaddress) - - $address = [System.Net.IPAddress] [byte[]] $startAddress + $startaddress = $address.GetAddressBytes() + [array]::Reverse($startaddress) - $hostList.Add($address.IPAddressToString) - - for ($i=0; $i -lt $numhosts-1; $i++) - { + $startaddress = [System.BitConverter]::ToUInt32($startaddress, 0) + [uint32]$startMask = ([System.math]::Pow(2, $maskPart)-1) * ([System.Math]::Pow(2,(32 - $maskPart))) + $startAddress = $startAddress -band $startMask - $nextAddress = $address.GetAddressBytes() - [array]::Reverse($nextAddress) - $nextAddress = [System.BitConverter]::ToUInt32($nextAddress, 0) - $nextAddress ++ - $nextAddress = [System.BitConverter]::GetBytes($nextAddress)[0..3] - [array]::Reverse($nextAddress) + #in powershell 2.0 there are 4 0 bytes padded, so the [0..3] is necessary + $startAddress = [System.BitConverter]::GetBytes($startaddress)[0..3] + [array]::Reverse($startaddress) - $address = [System.Net.IPAddress] [byte[]] $nextAddress - $hostList.Add($address.IPAddressToString) + $address = [System.Net.IPAddress] [byte[]] $startAddress - } + $hostList.Add($address.IPAddressToString) - } - - #if ipv6 CIDR notation, then there's a ps 3.0 requirement due to biginteger - else + for ($i=0; $i -lt $numhosts-1; $i++) { - #Get start address - $startAddress = $address.GetAddressBytes() - $numbits = $startAddress.Length * 8 - [array]::Reverse($startAddress) - - $startAddress = ([System.Numerics.BigInteger] [byte[]]$startAddress) + $nextAddress = $address.GetAddressBytes() + [array]::Reverse($nextAddress) + $nextAddress = [System.BitConverter]::ToUInt32($nextAddress, 0) + $nextAddress ++ + $nextAddress = [System.BitConverter]::GetBytes($nextAddress)[0..3] + [array]::Reverse($nextAddress) - $startMask = ([System.Numerics.BigInteger]::Pow(2, $maskPart)-1) * ([System.Math]::Pow(2,(128 - $maskPart))) - $startAddress = $startAddress -band $startMask - - $startAddress = $startAddress.ToByteArray() - [array]::Reverse($startAddress) - - #strip out leading 0 put in by BigIneger, if any - if ($startAddress[0] -eq 0) - { - $startAddress = $startAddress[1..$startAddress.Length] - } - - $address = [System.Net.IPAddress] [byte[]] $startAddress + $address = [System.Net.IPAddress] [byte[]] $nextAddress $hostList.Add($address.IPAddressToString) - for ($i=0; $i -lt $numhosts-1; $i++) - { - $nextAddress = $address.GetAddressBytes() - [array]::Reverse($nextAddress) - $nextAddress = ([System.Numerics.BigInteger] [byte[]]$nextAddress) + 1 - $nextAddress = $nextAddress.ToByteArray() - [array]::Reverse($nextAddress) - - $address = [System.Net.IPAddress] [byte[]] $nextAddress - $hostList.Add($address.IPAddressToString) - - } } + } else { @@ -316,13 +362,11 @@ http://webstersprodigy.net function Get-TopPort { Param ( - [Parameter(Mandatory = $True)] [int] $numPorts + [Parameter(Mandatory = $True)] + [ValidateRange(1,1000)] + [int] $numPorts ) - if ($numPorts -gt 1000 -or $numPorts -lt 0) - { - throw "Topports out of range - only supports top 1000" - } #list of top 1000 ports from nmap from Jun 2013 [int[]] $topPortList = @(80,23,443,21,3389,110,445,139,143,53,135,3306,8080,22 @@ -413,7 +457,7 @@ http://webstersprodigy.net } elseif ($pRange.Contains("-")) { - [int[]] $range = $pRange.Split("-").Trim() + [int[]] $range = $pRange.Split("-") if ($range.Count -ne 2 -or $pRange.Split("-")[0] -eq "" -or $pRange.split("-")[1] -eq "") { throw "Invalid port range" @@ -426,7 +470,6 @@ http://webstersprodigy.net $pList.Add([int]$pRange) } - } foreach ($p in $pList) { @@ -435,7 +478,6 @@ http://webstersprodigy.net throw "Port $p out of range" } } - } function Parse-IpPorts @@ -452,12 +494,12 @@ http://webstersprodigy.net function Remove-Ports { Param ( - [Parameter(Mandatory = $True)] [String] $xPorts + [Parameter(Mandatory = $True)] [string] $ExcludedPorts ) - [int[]] $xPorts = $xPorts.Split(",") + [int[]] $ExcludedPorts = $ExcludedPorts.Split(",") - foreach ($x in $xPorts) + foreach ($x in $ExcludedPorts) { $portList.Remove($x) } @@ -472,8 +514,7 @@ http://webstersprodigy.net [Parameter(Mandatory = $True, ParameterSetName="HostOut")] $openPorts, [Parameter(Mandatory = $True, ParameterSetName="HostOut")] $closedPorts, [Parameter(Mandatory = $True, ParameterSetName="HostOut")] $filteredPorts, - [Parameter()] [bool] $quiet, - [Parameter()] [bool] $Pn, + [Parameter()] [bool] $SkipDiscovery, [Parameter()] [System.IO.StreamWriter] $grepStream, [Parameter()] [System.Xml.XmlWriter] $xmlStream, [Parameter()] [System.IO.StreamWriter] $readableStream @@ -483,9 +524,9 @@ http://webstersprodigy.net { "Comment" { - if (!$quiet) { - Write-Output $comment - } + + Write-Verbose $comment + if ($grepStream) { $grepStream.WriteLine("# " + $comment) } @@ -502,32 +543,12 @@ http://webstersprodigy.net $cPort = [string]::join(",", $closedPorts.ToArray()) $fPort = [string]::join(",", $filteredPorts.ToArray()) - if (!$quiet) { - if ($isUp -and !$Pn) { - Write-Output ("Host: {0,-25} Status: Up" -f $outhost) - } - if ($isUp -or $Pn) { - if ($oPort -ne "") { - Write-Output ("Host: {0,-25} Open Ports: {1,0}" -f $outhost, $oPort) - } - if ($cPort -ne "") { - Write-Output ("Host: {0,-25} Closed Ports: {1,0}" -f $outhost, $cPort) - } - if ($fPort -ne "") { - Write-Output ("Host: {0,-25} Filtered Ports: {1,0}" -f $outhost, $fPort) - } - } - elseif (!$Pn) { - Write-Output ("Host: {0,-25} Status: Down" -f $outhost) - } - - } if ($grepStream) { #for grepstream use tabs - can be ugly, but easier for regex - if ($isUp -and !$Pn) { + if ($isUp -and !$SkipDiscovery) { $grepStream.writeline("Host: $outhost`tStatus: Up") } - if ($isUp -or $Pn) { + if ($isUp -or $SkipDiscovery) { if ($oPort -ne "") { $grepStream.writeline("Host: $outhost`tOpen Ports: $oPort") } @@ -538,7 +559,7 @@ http://webstersprodigy.net $grepStream.writeline("Host: $outhost`tFiltered Ports: $fPort") } } - elseif (!$Pn) { + elseif (!$SkipDiscovery) { $grepStream.writeline("Host: $outhost`tStatus: Down") } } @@ -546,7 +567,7 @@ http://webstersprodigy.net $xmlStream.WriteStartElement("Host") $xmlStream.WriteAttributeString("id", $outhost) - if (!$PN) { + if (!$SkipDiscovery) { if ($isUp) { $xmlStream.WriteAttributeString("Status", "Up") } @@ -585,7 +606,7 @@ http://webstersprodigy.net $readableStream.writeline("Host is up") } - if ($isUp -or $Pn) { + if ($isUp -or $SkipDiscovery) { $readableStream.writeline(("{0,-10}{1,0}" -f "PORT", "STATE")) @@ -604,7 +625,7 @@ http://webstersprodigy.net } } - elseif(!$Pn) { + elseif(!$SkipDiscovery) { $readableStream.writeline("Host is Down") } $readableStream.writeline("") @@ -629,15 +650,18 @@ http://webstersprodigy.net try { - [bool] $Pn = Convert-SwitchtoBool ($Pn) - [bool] $sn = Convert-SwitchtoBool ($sn) - [bool] $q = Convert-SwitchtoBool ($q) - [bool] $F = Convert-SwitchtoBool ($F) + [bool] $SkipDiscovery = Convert-SwitchtoBool ($SkipDiscovery) + [bool] $PingOnly = Convert-SwitchtoBool ($PingOnly) + [bool] $quiet = Convert-SwitchtoBool ($quiet) + [bool] $ForceOverwrite = Convert-SwitchtoBool ($ForceOverwrite) ######### #parse arguments ######### + [Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath + + if ($Hosts) { foreach($h in $Hosts) @@ -645,15 +669,15 @@ http://webstersprodigy.net Parse-Hosts($h) | Out-Null } } - elseif ($iL) + elseif ($HostFile) { - Parse-ILHosts($iL) | Out-Null + Parse-ILHosts($HostFile) | Out-Null } - if($exclude) + if($ExcludeHosts) { - Exclude-Hosts($exclude) + Exclude-Hosts($ExcludeHosts) } - if (($topPorts -and $Ports) -or ($topPorts -and $iP)) + if (($TopPorts -and $Ports) -or ($TopPorts -and $PortFile)) { throw "Cannot set topPorts with other specific ports" } @@ -661,15 +685,15 @@ http://webstersprodigy.net { Parse-Ports -Ports $Ports -pList $portList | Out-Null } - if($iP) + if($PortFile) { - Parse-IpPorts($iP) | Out-Null + Parse-IpPorts($PortFile) | Out-Null } if($portList.Count -eq 0) { - if ($topPorts) + if ($TopPorts) { - Get-TopPort($topPorts) | Out-Null + Get-TopPort($TopPorts) | Out-Null } else { @@ -677,19 +701,19 @@ http://webstersprodigy.net Get-TopPort(50) | Out-Null } } - if ($xPorts) + if ($ExcludedPorts) { - Remove-Ports -xPorts $xPorts | Out-Null + Remove-Ports -ExcludedPorts $ExcludedPorts | Out-Null } if($T) { switch ($T) { - 5 {$nHosts=40; $Threads = 1000; $Timeout = 750 } - 4 {$nHosts=30; $Threads = 1000; $Timeout = 1200 } - 3 {$nHosts=25; $Threads = 100; $Timeout = 2000 } - 2 {$nHosts=20; $Threads = 32; $Timeout = 2500 } + 5 {$nHosts=30; $Threads = 1000; $Timeout = 750 } + 4 {$nHosts=25; $Threads = 1000; $Timeout = 1200 } + 3 {$nHosts=20; $Threads = 100; $Timeout = 2500 } + 2 {$nHosts=15; $Threads = 32; $Timeout = 3000 } 1 {$nHosts=10; $Threads = 32; $Timeout = 5000 } default { throw "Invalid T parameter" @@ -701,48 +725,47 @@ http://webstersprodigy.net $xmlStream = $null $readableStream = $null - if($oA) + if($AllformatsOut) { - if ($oG -or $oX -or $oN) { + if ($GrepOut -or $XmlOut -or $ReadableOut) { Write-Warning "Both -oA specified with other output... going to ignore -oG/-oN/-oX" } - $oG = $oA + ".gnmap" - $oX = $oA + ".xml" - $oN = $oA + ".nmap" + $GrepOut = $AllformatsOut + ".gnmap" + $XmlOut = $AllformatsOut + ".xml" + $ReadableOut = $AllformatsOut + ".nmap" } - if ($oG) { - if (!$F -and (Test-Path $oG)) { - throw "Error: $oA already exists. Either delete the file or specify the -f flag" + if ($GrepOut) { + if (!$ForceOverwrite -and (Test-Path $GrepOut)) { + throw "Error: $AllformatsOut already exists. Either delete the file or specify the -f flag" } - $grepStream = [System.IO.StreamWriter] $oG + $grepStream = [System.IO.StreamWriter] $GrepOut } - if ($oN) { - if (!$F -and (Test-Path $oN)) { - throw "Error: $oN already exists. Either delete the file or specify the -f flag" + if ($ReadableOut) { + if (!$ForceOverwrite -and (Test-Path $ReadableOut)) { + throw "Error: $ReadableOut already exists. Either delete the file or specify the -f flag" } - $readableStream = [System.IO.StreamWriter] $oN + $readableStream = [System.IO.StreamWriter] $ReadableOut } - if ($oX) { - if (!$F -and (Test-Path $oX)) { - throw "Error: $oX already exists. Either delete the file or specify the -f flag" + if ($XmlOut) { + if (!$ForceOverwrite -and (Test-Path $XmlOut)) { + throw "Error: $XmlOut already exists. Either delete the file or specify the -f flag" } - $xmlStream = [System.xml.xmlwriter]::Create([string]$oX) + $xmlStream = [System.xml.xmlwriter]::Create([string]$XmlOut) $xmlStream.WriteStartDocument() $xmlStream.WriteStartElement("Portscanrun") $xmlStream.WriteAttributeString("version", $version) } - Parse-Ports -Ports $PS -pList $hostPortList | Out-Null - - [Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath + Parse-Ports -Ports $DiscoveryPorts -pList $hostPortList | Out-Null $startdate = Get-Date $myInvocationLine = $PSCmdlet.MyInvocation.Line $startMsg = "Invoke-Portscan.ps1 v$version scan initiated $startdate as: $myInvocationLine" - Write-PortscanOut -comment $startMsg -quiet $q -grepStream $grepStream -xmlStream $xmlStream -readableStream $readableStream + #TODO deal with output + Write-PortscanOut -comment $startMsg -grepStream $grepStream -xmlStream $xmlStream -readableStream $readableStream #converting back from int array gives some argument error checking $sPortList = [string]::join(",", $portList) @@ -755,8 +778,8 @@ http://webstersprodigy.net $portScanCode = { param ( [Parameter( Mandatory = $True)] [string] $thost, - [Parameter( Mandatory = $True)][bool] $Pn, - [Parameter( Mandatory = $True)][bool] $sn, + [Parameter( Mandatory = $True)][bool] $SkipDiscovery, + [Parameter( Mandatory = $True)][bool] $PingOnly, [Parameter( Mandatory = $True)][int] $Timeout, [Parameter( Mandatory = $True)] $PortList, [Parameter( Mandatory = $True)] $hostPortList, @@ -906,10 +929,10 @@ http://webstersprodigy.net } do { + Start-Sleep -Milli 100 if (($openPorts.Count -gt 0) -or ($closedPorts.Count -gt 0)) { return $True } - Start-Sleep -Milli 100 } While ($sockets.Count -gt 0) @@ -929,10 +952,6 @@ http://webstersprodigy.net [Parameter(Mandatory = $True)] [String] $h ) - $openPorts.clear() - $closedPorts.clear() - $filteredPorts.Clear() - [string[]]$Ports = @() @@ -951,11 +970,14 @@ http://webstersprodigy.net } [bool] $hostResult = $False - if(!$Pn) + if(!$SkipDiscovery) { [bool] $hostResult = PortScan-Alive $thost + $openPorts.clear() + $closedPorts.clear() + $filteredPorts.Clear() } - if((!$sn) -and ($hostResult -or $Pn)) + if((!$PingOnly) -and ($hostResult -or $SkipDiscovery)) { Portscan-Port $thost } @@ -974,29 +996,29 @@ http://webstersprodigy.net [int]$saveIteration = 0 [int]$computersDone=0 [int]$upHosts=0 - while (($saveIteration * $syncFreq) -lt $hostList.Count) + while (($saveIteration * $SyncFreq) -lt $hostList.Count) { Get-Job | Remove-Job -Force - $sIndex = ($saveIteration*$syncFreq) - $eIndex = (($saveIteration+1)*$syncFreq)-1 + $sIndex = ($saveIteration*$SyncFreq) + $eIndex = (($saveIteration+1)*$SyncFreq)-1 foreach ($iHost in $hostList[$sIndex..$eIndex]) { $ctr = @(Get-Job -state Running) while ($ctr.Count -ge $nHosts) { - Start-Sleep -Milliseconds $sleepTimer + Start-Sleep -Milliseconds $SleepTimer $ctr = @(Get-Job -state Running) } $computersDone++ - if($v) + if(!$noProgressMeter) { - Write-Progress -status "Port Scanning" -Activity "Port Scan" -CurrentOperation "starting computer $computersDone" -PercentComplete ($computersDone / $hostList.Count * 100) + Write-Progress -status "Port Scanning" -Activity $startMsg -CurrentOperation "starting computer $computersDone" -PercentComplete ($computersDone / $hostList.Count * 100) } - Start-Job -ScriptBlock $portScanCode -Name $iHost -ArgumentList @($iHost, $Pn, $sn, $Timeout, $portList, $hostPortList, $Threads) | Out-Null + Start-Job -ScriptBlock $portScanCode -Name $iHost -ArgumentList @($iHost, $SkipDiscovery, $PingOnly, $Timeout, $portList, $hostPortList, $Threads) | Out-Null } Get-Job | Wait-Job | Out-Null @@ -1014,7 +1036,22 @@ http://webstersprodigy.net if($hostUp) { $upHosts ++ } - Write-PortscanOut -outhost $jobName -isUp $hostUp -openPorts $openPorts -closedPorts $closedPorts -filteredPorts $filteredPorts -grepStream $grepStream -xmlStream $xmlStream -readableStream $readableStream -quiet $q -Pn $Pn + + if (!$quiet) + { + $hostDate = Get-Date + $hostObj = New-Object System.Object + $hostObj | Add-Member -MemberType Noteproperty -Name Hostname -Value $jobName + $hostObj | Add-Member -MemberType Noteproperty -Name alive -Value $hostUp + $hostObj | Add-Member -MemberType Noteproperty -Name openPorts -Value $openPorts + $hostObj | Add-Member -MemberType Noteproperty -Name closedPorts -Value $closedPorts + $hostObj | Add-Member -MemberType Noteproperty -Name filteredPorts -Value $filteredPorts + $hostObj | Add-Member -MemberType NoteProperty -Name finishTime -Value $hostDate + + $scannedHostList += $hostobj + } + + Write-PortscanOut -outhost $jobName -isUp $hostUp -openPorts $openPorts -closedPorts $closedPorts -filteredPorts $filteredPorts -grepStream $grepStream -xmlStream $xmlStream -readableStream $readableStream -SkipDiscovery $SkipDiscovery } if ($grepStream) { @@ -1033,11 +1070,11 @@ http://webstersprodigy.net $enddate = Get-Date $totaltime = ($enddate - $startdate).TotalSeconds $endMsg = "Port scan complete at $enddate ($totaltime seconds)" - if (!$Pn) { + if (!$SkipDiscovery) { $endMsg += ", $upHosts hosts are up" } - Write-PortscanOut -comment $endMsg -quiet $q -grepStream $grepStream -xmlStream $xmlStream -readableStream $readableStream + Write-PortscanOut -comment $endMsg -grepStream $grepStream -xmlStream $xmlStream -readableStream $readableStream if($grepStream) { $grepStream.Close() @@ -1048,6 +1085,9 @@ http://webstersprodigy.net if($readableStream) { $readableStream.Close() } + + return $scannedHostList + } Catch { -- cgit v1.2.3 From 60a6044d36b0014ec896ed0052dbbb36342a54ee Mon Sep 17 00:00:00 2001 From: Rich Lundeen Date: Tue, 18 Jun 2013 15:10:54 -0700 Subject: fixing EOL spaces --- Recon/Invoke-Portscan.ps1 | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/Recon/Invoke-Portscan.ps1 b/Recon/Invoke-Portscan.ps1 index bba5821..a6b1338 100644 --- a/Recon/Invoke-Portscan.ps1 +++ b/Recon/Invoke-Portscan.ps1 @@ -19,7 +19,6 @@ Does a simple port scan using regular sockets, based (pretty) loosely on nmap version .13 - .PARAMETER Hosts Include these comma seperated hosts (supports IPv4 CIDR notation) or pipe them in @@ -89,7 +88,6 @@ How often (in terms of hosts) to sync threads and flush output 2 {$nHosts=15; $Threads = 32; $Timeout = 3000 } 1 {$nHosts=10; $Threads = 32; $Timeout = 5000 } - .PARAMETER GrepOut Greppable output file @@ -104,7 +102,7 @@ output file in 'readable' format .PARAMETER AllformatsOut -output in readable (.nmap), xml (.xml), and greppable (.gnmap) formats +output in readable (.nmap), xml (.xml), and greppable (.gnmap) formats .PARAMETER noProgressMeter @@ -118,7 +116,6 @@ supresses returned output and don't store hosts in memory - useful for very larg Force Overwrite if output Files exist. Otherwise it throws exception - .EXAMPLE C:\PS> Invoke-Portscan -Hosts "webstersprodigy.net,google.com,microsoft.com" -TopPorts 50 @@ -127,7 +124,6 @@ Description ----------- Scans the top 50 ports for hosts found for webstersprodigy.net,google.com, and microsoft.com - .EXAMPLE C:\PS> echo webstersprodigy.net | Invoke-Portscan -oG test.gnmap -f -ports "80,443,8080" @@ -136,7 +132,6 @@ Description ----------- Does a portscan of "webstersprodigy.net", and writes a greppable output file - .EXAMPLE C:\PS> Invoke-Portscan -Hosts 192.168.1.1/24 -T 4 -TopPorts 25 -oA localnet @@ -145,7 +140,6 @@ Description ----------- Scans the top 20 ports for hosts found in the 192.168.1.1/24 range, outputs all file formats - .LINK http://webstersprodigy.net @@ -153,10 +147,12 @@ http://webstersprodigy.net [CmdletBinding()]Param ( #Host, Ports - [Parameter(ParameterSetName="cmdHosts", + [Parameter(ParameterSetName="cmdHosts", + ValueFromPipeline=$True, - Mandatory = $True)] - [String[]] $Hosts, + Mandatory = $True)] + + [String[]] $Hosts, [Parameter(ParameterSetName="fHosts", Mandatory = $True)] @@ -363,11 +359,11 @@ http://webstersprodigy.net { Param ( [Parameter(Mandatory = $True)] - [ValidateRange(1,1000)] + [ValidateRange(1,1000)] + [int] $numPorts ) - #list of top 1000 ports from nmap from Jun 2013 [int[]] $topPortList = @(80,23,443,21,3389,110,445,139,143,53,135,3306,8080,22 1723,111,995,993,5900,1025,1720,548,113,81,6001,179,1026,2000,8443, @@ -646,7 +642,6 @@ http://webstersprodigy.net return $False } - try { @@ -661,7 +656,6 @@ http://webstersprodigy.net [Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath - if ($Hosts) { foreach($h in $Hosts) @@ -771,7 +765,6 @@ http://webstersprodigy.net $sPortList = [string]::join(",", $portList) $sHostPortList = [string]::join(",", $hostPortList) - ######## #Port Scan Code - run on a per host basis ######## @@ -887,7 +880,6 @@ http://webstersprodigy.net `$sockets.Remove($p) "@ - $timeoutCallback = [scriptblock]::Create($timeoutCallback) $timeouts[$p] = New-Object System.Timers.Timer @@ -895,7 +887,6 @@ http://webstersprodigy.net $timeouts[$p].Interval = $timeout $timeouts[$p].Enabled = $true - $myscriptblock = [scriptblock]::Create($scriptBlockAsString) $x = $sockets[$p].beginConnect($h, $p,(New-ScriptBlockCallback($myscriptblock)) , $null) @@ -954,7 +945,6 @@ http://webstersprodigy.net [string[]]$Ports = @() - foreach($Port in $Portlist) { Try @@ -989,7 +979,6 @@ http://webstersprodigy.net } } - # the outer loop is to flush the loop. # Otherwise Get-Job | Wait-Job could clog, etc @@ -1037,17 +1026,19 @@ http://webstersprodigy.net $upHosts ++ } - if (!$quiet) + if (!$quiet) + { $hostDate = Get-Date $hostObj = New-Object System.Object - $hostObj | Add-Member -MemberType Noteproperty -Name Hostname -Value $jobName + $hostObj | Add-Member -MemberType Noteproperty -Name Hostname -Value $jobName + $hostObj | Add-Member -MemberType Noteproperty -Name alive -Value $hostUp $hostObj | Add-Member -MemberType Noteproperty -Name openPorts -Value $openPorts $hostObj | Add-Member -MemberType Noteproperty -Name closedPorts -Value $closedPorts $hostObj | Add-Member -MemberType Noteproperty -Name filteredPorts -Value $filteredPorts $hostObj | Add-Member -MemberType NoteProperty -Name finishTime -Value $hostDate - + $scannedHostList += $hostobj } @@ -1095,5 +1086,3 @@ http://webstersprodigy.net } } } - - -- cgit v1.2.3 From 05ab35a3af55a5b28cdbc2db73f26ada044bb6d3 Mon Sep 17 00:00:00 2001 From: Rich Lundeen Date: Tue, 18 Jun 2013 15:15:40 -0700 Subject: fixing EOL spaces (again, sorry) --- Recon/Invoke-Portscan.ps1 | 3 --- 1 file changed, 3 deletions(-) diff --git a/Recon/Invoke-Portscan.ps1 b/Recon/Invoke-Portscan.ps1 index a6b1338..7805e13 100644 --- a/Recon/Invoke-Portscan.ps1 +++ b/Recon/Invoke-Portscan.ps1 @@ -151,7 +151,6 @@ http://webstersprodigy.net ValueFromPipeline=$True, Mandatory = $True)] - [String[]] $Hosts, [Parameter(ParameterSetName="fHosts", @@ -360,7 +359,6 @@ http://webstersprodigy.net Param ( [Parameter(Mandatory = $True)] [ValidateRange(1,1000)] - [int] $numPorts ) @@ -1027,7 +1025,6 @@ http://webstersprodigy.net } if (!$quiet) - { $hostDate = Get-Date $hostObj = New-Object System.Object -- cgit v1.2.3 From 98510d80973cc46462cdfe6bd18fe3ec5f64d4bc Mon Sep 17 00:00:00 2001 From: Rich Lundeen Date: Tue, 25 Jun 2013 22:07:36 -0700 Subject: IPv6 support in hosts param --- Recon/Invoke-Portscan.ps1 | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Recon/Invoke-Portscan.ps1 b/Recon/Invoke-Portscan.ps1 index 7805e13..46a5337 100644 --- a/Recon/Invoke-Portscan.ps1 +++ b/Recon/Invoke-Portscan.ps1 @@ -243,6 +243,8 @@ http://webstersprodigy.net PROCESS { + Set-StrictMode -Version 2.0 + $version = .13 $hostList = New-Object System.Collections.ArrayList $portList = New-Object System.Collections.ArrayList @@ -314,16 +316,7 @@ http://webstersprodigy.net } else { - try - { - $address = [System.Net.IPAddress]::Parse($iHost) - $hostList.Add($address.IPAddressToString) - } - catch - { - #we're assuming this is a host name - $hostList.Add($iHost) - } + $hostList.Add($iHost) } } } @@ -841,7 +834,17 @@ http://webstersprodigy.net [Parameter(Mandatory = $True)] [int] $timeout ) - $sockets[$p] = new-object System.Net.Sockets.TcpClient + try { + $pAddress = [System.Net.IPAddress]::Parse($h) + $sockets[$p] = new-object System.Net.Sockets.TcpClient $pAddress.AddressFamily + + } + catch { + #we're assuming this is a host name + $sockets[$p] = new-object System.Net.Sockets.TcpClient + } + + $scriptBlockAsString = @" #somewhat of a race condition with the timeout, but I don't think it matters -- cgit v1.2.3 From b507290d78e495efe54fb90d71a4b41a502a7fb5 Mon Sep 17 00:00:00 2001 From: Matt Graeber Date: Sat, 6 Jul 2013 13:38:35 -0400 Subject: Added Invoke-Portscan to README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index c075e87..0411546 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,10 @@ Generates a full-memory minidump of a process. **Tools to aid in the reconnaissance phase of a penetration test.** +#### `Invoke-Portscan` + +Does a simple port scan using regular sockets, based (pretty) loosely on nmap. + #### `Get-HttpStatus` Returns the HTTP Status Codes and full URL for specified paths when provided with a dictionary file. -- cgit v1.2.3