├── .github └── FUNDING.yml ├── README.md └── Invoke-Piper.psm1 /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [p3nt4] 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Piper 2 | Forward local or remote tcp ports through SMB pipes. 3 | 4 | ## EXAMPLES 5 | 6 | ### Local port forwarding through pipe testPipe: -L 33389:127.0.0.1:3389 7 | ``` 8 | SERVER: Invoke-PiperServer -bindPipe testPipe -destHost 127.0.0.1 -destPort 3389 9 | CLIENT: net use \\serverIP /USER:User (OPTIONAL) 10 | CLIENT: Invoke-PiperClient -destPipe testPipe -pipeHost serverIP -bindPort 33389 11 | ``` 12 | 13 | ### Admin only remote port forwarding through pipe testPipe: -R 33389:127.0.0.1:3389 14 | ``` 15 | SERVER: Invoke-PiperServer -remote -bindPipe testPipe -bindPort 33389 -security Administrators 16 | CLIENT: net use \\serverIP /USER:User (OPTIONAL) 17 | CLIENT: Invoke-PiperClient -remote -destPipe testPipe -pipeHost serverIP -destHost 127.0.0.1 -destPort 3389 18 | ``` 19 | 20 | ### Dynamic port forwarding (using https://github.com/p3nt4/Invoke-SocksProxy): -D 1234 21 | 22 | ``` 23 | SERVER: Invoke-SocksProxy -bindPort 1234 24 | SERVER: Invoke-PiperServer -bindPipe testPipe -destHost 127.0.0.1 -destPort 1234 25 | CLIENT: net use \\serverIP /USER:User (OPTIONAL) 26 | CLIENT: Invoke-PiperClient -destPipe testPipe -pipeHost serverIP -bindPort 1234 27 | ``` 28 | 29 | ## Issues 30 | Protocols requiring a big amount of parallel connections may exhaust all named pipes available to the system. 31 | -------------------------------------------------------------------------------- /Invoke-Piper.psm1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | 4 | Creates a local or remote port forwarding through named pipes. 5 | 6 | Author: p3nt4 (https://twitter.com/xP3nt4) 7 | License: MIT 8 | 9 | .DESCRIPTION 10 | 11 | Creates a local or remote port forwarding through named pipes. 12 | 13 | .EXAMPLE 14 | 15 | Invoke-PiperServer -bindPipe testPipe -destHost 127.0.0.1 -destPort 3389 16 | Invoke-PiperClient -destPipe testPipe -pipeHost 192.168.1.1 -bindPort 33389 17 | 18 | Creates a local port forwarding through pipe testPipe: -L 33389:127.0.0.1:3389 19 | 20 | Invoke-PiperServer -remote -bindPipe testPipe -bindPort 33389 -security Administrators 21 | Invoke-PiperClient -remote -destPipe testPipe -pipeHost 192.168.1.1 -destHost 127.0.0.1 -destPort 3389 22 | 23 | Creates an admin only remote port forwarding through pipe testPipe: -R 33389:127.0.0.1:3389 24 | #> 25 | 26 | [ScriptBlock]$CliConnectionMgr = { 27 | param($vars) 28 | $destPipe=$vars.destPipe 29 | $tcpConnection=$vars.tcpConnection 30 | $pipeHost=$vars.pipeHost 31 | $Script = { 32 | param($vars) 33 | try{ 34 | $vars.inStream.CopyTo($vars.outStream) 35 | } 36 | catch{} 37 | finally{ 38 | $vars.pipe.Close() 39 | $vars.pipe.Dispose() 40 | } 41 | } 42 | try{ 43 | $inPipeName= -Join($destPipe,'.in') 44 | $outPipeName= -Join($destPipe,'.out') 45 | $inPipe= new-object System.IO.Pipes.NamedPipeClientStream($pipeHost, $inPipeName, [System.IO.Pipes.PipeDirection]::InOut, 46 | [System.IO.Pipes.PipeOptions]::None, 47 | [System.Security.Principal.TokenImpersonationLevel]::Impersonation) 48 | $inPipe.connect() 49 | $outPipe= new-object System.IO.Pipes.NamedPipeClientStream($pipeHost, $outPipeName, [System.IO.Pipes.PipeDirection]::InOut, 50 | [System.IO.Pipes.PipeOptions]::None, 51 | [System.Security.Principal.TokenImpersonationLevel]::Impersonation) 52 | $outPipe.connect() 53 | $tcpStream = $tcpConnection.GetStream() 54 | $vars2 = [PSCustomObject]@{"inStream"=$outPipe;"outStream"=$tcpStream;"pipe"=$outPipe} 55 | $PS = [PowerShell]::Create() 56 | $PS.AddScript($Script).AddArgument($vars2) | Out-Null 57 | [System.IAsyncResult]$AsyncJobResult = $null 58 | $AsyncJobResult = $PS.BeginInvoke() 59 | try{ 60 | $tcpStream.CopyTo($inPipe) 61 | } 62 | catch{} 63 | finally{ 64 | $inPipe.Close() 65 | $inPipe.Dispose() 66 | } 67 | } 68 | catch {} 69 | } 70 | 71 | 72 | [ScriptBlock]$SrvConnectionMgr = { 73 | param($vars) 74 | $bindPipe=$vars.bindPipe 75 | $PipeSecurity=$vars.pipeSecurity 76 | $tcpConnection=$vars.tcpConnection 77 | $Script = { 78 | param($vars) 79 | try{ 80 | $vars.inStream.CopyTo($vars.outStream) 81 | } 82 | catch{} 83 | finally{ 84 | $vars.pipe.Disconnect() 85 | $vars.pipe.Close() 86 | $vars.pipe.Dispose() 87 | } 88 | } 89 | try 90 | { 91 | $inPipeName= -Join($bindPipe,'.in') 92 | $inPipe= new-object System.IO.Pipes.NamedPipeServerStream($inPipeName,"InOut",100, "Byte", "Asynchronous", 32768, 32768, $PipeSecurity) 93 | $inPipe.WaitForConnection() 94 | $outPipeName= -Join($bindPipe,'.out') 95 | $outPipe= new-object System.IO.Pipes.NamedPipeServerStream($outPipeName, "InOut",100, "Byte", "Asynchronous", 32768, 32768, $PipeSecurity) 96 | $outPipe.WaitForConnection() 97 | $srvStream= $tcpConnection.GetStream() 98 | $vars = [PSCustomObject]@{"inStream"=$srvStream;"outStream"=$outPipe;"pipe"=$outPipe} 99 | $PS = [PowerShell]::Create() 100 | $PS.AddScript($Script).AddArgument($vars) | Out-Null 101 | [System.IAsyncResult]$AsyncJobResult = $null 102 | $AsyncJobResult = $PS.BeginInvoke() 103 | try{ 104 | $inPipe.CopyTo($srvStream) 105 | } 106 | catch{} 107 | finally{ 108 | $inPipe.Disconnect() 109 | $inPipe.Close() 110 | $inPipe.Dispose() 111 | $inPipe = $null 112 | } 113 | } 114 | catch { 115 | } 116 | } 117 | 118 | 119 | function Invoke-PiperServer{ 120 | param ( 121 | [String]$bindPipe, 122 | 123 | [String]$destHost, 124 | 125 | [String]$security = "Everyone", 126 | 127 | [Int]$destPort, 128 | 129 | [String]$bindIP = "0.0.0.0", 130 | 131 | [Int]$bindPort, 132 | 133 | [switch]$remote = $false 134 | 135 | ) 136 | try{ 137 | $enc = [system.Text.Encoding]::UTF8 138 | $clientBuffer = new-object System.Byte[] 16 139 | $PipeSecurity = new-object System.IO.Pipes.PipeSecurity 140 | $AccessRule = New-Object System.IO.Pipes.PipeAccessRule( $security, "FullControl", "Allow" ) 141 | $PipeSecurity.AddAccessRule($AccessRule) 142 | $pipe= new-object System.IO.Pipes.NamedPipeServerStream($bindPipe,"InOut",100, "Byte", "Asynchronous", 32768, 32768, $PipeSecurity) 143 | write-host "Waiting for a connection on management pipe: $bindPipe..." 144 | $pipe.WaitForConnection() 145 | write-host "Client Connected" 146 | if ($remote -eq $false){ 147 | while($pipe.IsConnected){ 148 | $pipe.read($clientBuffer,0,16) | Out-Null 149 | $tempPipe = [System.Text.Encoding]::ASCII.GetString($clientBuffer, 0, 16) 150 | Write-Host "New Connection" 151 | $serv = New-Object System.Net.Sockets.TcpClient($destHost, $destPort) 152 | $vars = [PSCustomObject]@{"tcpConnection"=$serv;"bindPipe"=$tempPipe;"pipeSecurity"=$PipeSecurity} 153 | $PS3 = [PowerShell]::Create() 154 | $PS3.AddScript($SrvConnectionMgr).AddArgument($vars) | Out-Null 155 | [System.IAsyncResult]$AsyncJobResult3 = $null 156 | $AsyncJobResult3 = $PS3.BeginInvoke() 157 | } 158 | }else{ 159 | $listener = new-object System.Net.Sockets.TcpListener([System.Net.IPAddress]::Parse($bindIP), $bindPort) 160 | $listener.start() 161 | write-host "Listening on port $bindPort..." 162 | while($pipe.IsConnected){ 163 | $client = $listener.AcceptTcpClient() 164 | $tempPipe = Get-RandomPipeName 165 | $clientBuffer = $enc.GetBytes($tempPipe) 166 | Write-Host "New Connection" 167 | $pipe.Write($clientBuffer,0,16) 168 | $vars = [PSCustomObject]@{"tcpConnection"=$client;"bindPipe"=$tempPipe;"security"=$security} 169 | $PS3 = [PowerShell]::Create() 170 | $PS3.AddScript($SrvConnectionMgr).AddArgument($vars) | Out-Null 171 | [System.IAsyncResult]$AsyncJobResult3 = $null 172 | $AsyncJobResult3 = $PS3.BeginInvoke() 173 | } 174 | } 175 | } 176 | catch{ 177 | write-host $_.Exception 178 | } 179 | finally{ 180 | if ($listener -ne $null) { 181 | $listener.Stop() 182 | } 183 | if ($pipe -ne $null) { 184 | $pipe.Close() 185 | $pipe.Dispose() 186 | $pipe = $null 187 | } 188 | if ($PS3 -ne $null -and $AsyncJobResult3 -ne $null) { 189 | $PS3.EndInvoke($AsyncJobResult3) | Out-Null 190 | $PS3.Dispose() 191 | } 192 | write-host "Management Connection closed." 193 | } 194 | 195 | } 196 | 197 | function Invoke-PiperClient{ 198 | param ( 199 | 200 | [String]$pipeHost, 201 | 202 | [String]$destPipe, 203 | 204 | [switch]$remote = $false, 205 | 206 | [String]$bindIP = "0.0.0.0", 207 | 208 | [Int]$bindPort, 209 | 210 | [String]$destHost, 211 | 212 | [Int]$destPort 213 | 214 | ) 215 | $clientBuffer = new-object System.Byte[] 16 216 | $enc = [system.Text.Encoding]::UTF8 217 | try{ 218 | write-host "Attempting to connect to $pipeHost through management pipe: $destPipe" 219 | $pipe= new-object System.IO.Pipes.NamedPipeClientStream($pipeHost, $destPipe, [System.IO.Pipes.PipeDirection]::InOut, 220 | [System.IO.Pipes.PipeOptions]::None, 221 | [System.Security.Principal.TokenImpersonationLevel]::Impersonation) 222 | $pipe.connect() 223 | write-host "Connected to $pipeHost through management pipe: $destPipe" 224 | if ($remote -eq $false){ 225 | $listener = new-object System.Net.Sockets.TcpListener([System.Net.IPAddress]::Parse($bindIP), $bindPort) 226 | $listener.start() 227 | write-host "Listening on port $bindPort..." 228 | while($pipe.IsConnected){ 229 | $client = $listener.AcceptTcpClient() 230 | $tempPipe = Get-RandomPipeName 231 | $clientBuffer = $enc.GetBytes($tempPipe) 232 | Write-Host "New Connection" 233 | $pipe.Write($clientBuffer,0,16) 234 | $vars = [PSCustomObject]@{"tcpConnection"=$client;"destPipe"= $tempPipe;"pipeHost"=$pipeHost} 235 | $PS3 = [PowerShell]::Create() 236 | $PS3.AddScript($CliConnectionMgr).AddArgument($vars) | Out-Null 237 | [System.IAsyncResult]$AsyncJobResult3 = $null 238 | $AsyncJobResult3 = $PS3.BeginInvoke() 239 | } 240 | } 241 | else{ 242 | while($pipe.IsConnected){ 243 | $pipe.read($clientBuffer,0,16) | Out-Null 244 | Write-Host "New Connection" 245 | $tempPipe = [System.Text.Encoding]::ASCII.GetString($clientBuffer, 0, 16) 246 | $serv = New-Object System.Net.Sockets.TcpClient($destHost, $destPort) 247 | $vars = [PSCustomObject]@{"tcpConnection"=$serv;"destPipe"= $tempPipe;"pipeHost"=$pipeHost} 248 | $PS3 = [PowerShell]::Create() 249 | $PS3.AddScript($CliConnectionMgr).AddArgument($vars) | Out-Null 250 | [System.IAsyncResult]$AsyncJobResult3 = $null 251 | $AsyncJobResult3 = $PS3.BeginInvoke() 252 | } 253 | } 254 | }catch { 255 | write-host $_.Exception 256 | } 257 | finally { 258 | if ($listener -ne $null) { 259 | $listener.Stop() 260 | } 261 | if ($pipe -ne $null) { 262 | $pipe.Close() 263 | $pipe.Dispose() 264 | $pipe = $null 265 | } 266 | if ($PS3 -ne $null -and $AsyncJobResult3 -ne $null) { 267 | $PS3.EndInvoke($AsyncJobResult3) | Out-Null 268 | $PS3.Dispose() 269 | } 270 | write-host "Management Connection closed." 271 | } 272 | 273 | } 274 | 275 | 276 | function Get-RandomPipeName{ 277 | $text = -join ((48..57) + (65..90) + (97..122) | Get-Random -Count 16 | % {[char]$_}) 278 | return $text 279 | } 280 | 281 | export-modulemember -function Invoke-PiperServer 282 | export-modulemember -function Invoke-PiperClient 283 | --------------------------------------------------------------------------------