Multithreading 如何加速PowerShell端口扫描程序
出于各种原因,我开始编写PowerShell portscanner,不仅仅是为了开始学习它 使用的第一次迭代Multithreading 如何加速PowerShell端口扫描程序,multithreading,powershell,sockets,Multithreading,Powershell,Sockets,出于各种原因,我开始编写PowerShell portscanner,不仅仅是为了开始学习它 使用的第一次迭代测试网络连接。这似乎太慢了;所以我降低了一个级别来使用套接字,特别是System.Net.sockets.TcpClient。(我们已经开始研究System.Net.Sockets.Socket,因为MS文档提到了Socket.BeginConnect(),它可以启动远程连接的异步请求,但不确定这是否有帮助。) 这看起来还是太慢了,所以我看了看乔布斯。所有这些都是为了不增加太多的速度而消
测试网络连接
。这似乎太慢了;所以我降低了一个级别来使用套接字,特别是System.Net.sockets.TcpClient
。(我们已经开始研究System.Net.Sockets.Socket
,因为MS文档提到了Socket.BeginConnect()
,它可以启动远程连接的异步请求,但不确定这是否有帮助。)
这看起来还是太慢了,所以我看了看乔布斯。所有这些都是为了不增加太多的速度而消耗更多的资源,所以在谷歌搜索了很多次之后,我设法通过使用RunSpacePools
使线程(或者PowerShell称之为线程)工作。我认为这已经基本完成了,如果您查看的是一个包含5个IP地址的输入文件,那么性能还可以。然而,今天早上用CIDR/24进行了试验,大约需要20-30分钟
[Edit]我应该补充一点,该脚本将采用“线程”值,但如果没有提供,则使用默认线程值核心数+1
,以利用RunSpacePool多线程
因此,我开始研究Fyodor是如何提高速度的,在他所在州的扫描艺术中(同时谈到TCP Connect()扫描):
同时对中的每个目标端口进行单独的connect()调用
线性时尚比慢速连接要花很多时间,你可以加快速度
通过并行使用多个套接字进行扫描
这显然是可以进行一些优化的地方
那么,有没有人能为我指明如何实现这一点的方向?正如我所说,对PoSH来说还是很陌生的,所以我用RunSpacePools
来突破我理解的极限。
具体地说,我想要一些建议:a)如果我的直觉正确,可以提高扫描速度以提高套接字并行性;b)如何做到这一点;c)如果System.Net.Sockets.socket
更合适
function doConnect {
$ipLoopCount = 0
$portLoopCount = 0
# check for randomise switch
if ($randomise) {
$ipArray = makeRange | Sort-Object {Get-Random}
$portArray = makePortRange | Sort-Object {Get-Random}
} else {
# Connects to IPs in order
$ipArray = makeRange
$portArray = makePortRange
}
# initialise runspaces
if ($threads) {
$useThreads = $threads
} else {
$useThreads = ([int]$env:NUMBER_OF_PROCESSORS + 1)
}
$pool = [RunspaceFactory]::CreateRunspacePool(1, $useThreads)
$pool.ApartmentState = "MTA"
$pool.Open()
$runspaces = @()
# set higher priority for powershell process
if ($priority) {
$proc = Get-Process -Id $pid;
$proc.PriorityClass = 'High'
} else{
$proc = Get-Process -Id $pid;
$proc.PriorityClass = 'Normal'
}
# info object
$infoDisplay = @{
InputFile = $inFile
Target_IPs = $ipArray
Target_Ports = $portArray
Process_Priority = $proc.PriorityClass
Threads = $useThreads
}
[PSCustomObject]$infoDisplay
# set up scriptblock to pass to runspaces
$scriptblock = {
Param (
[IPAddress]$sb_ip,
[int]$sb_port
)
# This progress bar doesn't work yet
Write-Progress -Activity "Scan range $StartIPaddress - $EndIPAddress" -Status "% Complete:" -PercentComplete((($portLoopCount)/($ipArray.Length*$portArray.Length))*100)
if ($delay) {
$delay = Get-Random -Maximum 1000 -Minimum 1;
Start-Sleep -m $delay
}
$socket = New-Object System.Net.Sockets.TcpClient
$socket.Connect($sb_ip, $sb_Port)
if ($socket.Connected) {
Write-Output "Connected to $sb_port on $sb_ip"
#} else {
# Write-Output "Failed to connect to port $sb_port on $sb_ip"
}
$socket.Close()
}
foreach ($nIP in $ipArray) {
$ipLoopCount++
foreach ($nPort in $portArray) {
$portLoopCount++
$runspace = [PowerShell]::Create()
$null = $runspace.AddScript($scriptblock)
$null = $runspace.AddArgument($nIP)
$null = $runspace.AddArgument($nPort)
$runspace.RunspacePool = $pool
$runspaces += [PSCustomObject]@{
Pipe = $runspace;
Status = $runspace.BeginInvoke()
}
}
}
while ($runspaces.Status -ne $null) {
$completed = $runspaces | Where-Object { $_.Status.IsCompleted -eq $true }
foreach ($runspace in $completed) {
$runspace.Pipe.EndInvoke($runspace.Status)
$runspace.Status = $null
}
}
$pool.Close()
$pool.Dispose()
}
在PowerShell中尝试这一点可能是完全错误的,但这是一个有用的练习,因为环境已完全锁定,并且不可能安装“适当”的端口扫描程序(即nmap)
[Edit 2]我不认为减少超时并将其导入逻辑是我所追求的解决方案
[Edit 3]并联开关没有帮助
[Edit 4]一直在考虑异步套接字连接,因为这可能有助于提高总体连接速度,但随后必须有另一个线程/进程来处理传入的通信量。不确定疗效。您能否详细说明您需要帮助的具体内容?“我有点卡住了”并不是很具体:)这是一个公正的评论。完成!您是否尝试过在工作流中实现foreach-parallel?不知道它能给你多大的速度,但值得一试<代码>只能在工作流中使用“-parallel”参数
。我必须理解这个概念,而不是以前遇到的。这似乎是相当基本的知识:/workflow往往是可靠的,但速度很慢,因此切换到workflow可能不是最好的选择。