Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to connect to tcp socket with powershell to send and receive data?

I have written a little Powershell script.

It uses .Net System.IO.StreamReader and System.IO.StreamWriter to read and write data from/to the TCP socket.

I would like to connect to a socket telnet style with it and send/receive commands.

I am trying to read the lines with the ReadLine() method from the System.IO.StreamReader but the data from the server maybe does not arrive in time(?) or IDK. I am not using async commands. Please help me with that!

Here is my script:

$FTPServer = "localhost"
$FTPPort = "21"

$tcpConnection = New-Object System.Net.Sockets.TcpClient($FTPServer, $FTPPort)
$tcpStream = $tcpConnection.GetStream()
$reader = New-Object System.IO.StreamReader($tcpStream)
$writer = New-Object System.IO.StreamWriter($tcpStream)
$writer.AutoFlush = $true

while ($tcpConnection.Connected)
{
    while ($tcpStream.DataAvailable)
    {
        $reader.ReadLine()
    }

    if ($tcpConnection.Connected)
    {
        Write-Host -NoNewline "prompt> "
        $command = Read-Host

        if ($command -eq "escape")
        {
            break
        }

        $writer.WriteLine($command) | Out-Null
    }
}

$reader.Close()
$writer.Close()
$tcpConnection.Close()

And here is the output:

PS C:\Windows\System32\WindowsPowerShell\v1.0> test.ps1
220 Microsoft FTP Service
prompt> user username
331 Password required
prompt> pass password
230-Directory has 58,145,996,800 bytes of disk space available.
prompt> 
230 User logged in.
500 Command not understood.
prompt> help
214-The following commands are recognized (* ==>'s unimplemented).
    ABOR 
    ACCT 
    ADAT *
    ALLO 
    APPE 
    AUTH 
    CCC 
    CDUP 
    CWD 
    DELE 
    ENC *
    EPRT 
    EPSV 
    FEAT 
    HELP 
    HOST 
    LANG 
    LIST 
    MDTM 
    MIC *
    MKD 
    MODE 
    NLST 
    NOOP 
    OPTS 
    PASS 
    PASV 
    PBSZ 
    PORT 
    PROT 
    PWD 
    QUIT 
    REIN 
    REST 
    RETR 
    RMD 
    RNFR 
    RNTO 
    SITE 
prompt> escape

PS C:\Windows\System32\WindowsPowerShell\v1.0>
like image 226
gazsiazasz Avatar asked Apr 20 '15 22:04

gazsiazasz


3 Answers

Try using a buffer to read in response. The code would look like this:

$tcpConnection = New-Object System.Net.Sockets.TcpClient($FTPServer, $FTPPort)
$tcpStream = $tcpConnection.GetStream()
$reader = New-Object System.IO.StreamReader($tcpStream)
$writer = New-Object System.IO.StreamWriter($tcpStream)
$writer.AutoFlush = $true

$buffer = new-object System.Byte[] 1024
$encoding = new-object System.Text.AsciiEncoding 

while ($tcpConnection.Connected)
{
    while ($tcpStream.DataAvailable)
    {

        $rawresponse = $reader.Read($buffer, 0, 1024)
        $response = $encoding.GetString($buffer, 0, $rawresponse)   
    }

    if ($tcpConnection.Connected)
    {
        Write-Host -NoNewline "prompt> "
        $command = Read-Host

        if ($command -eq "escape")
        {
            break
        }

        $writer.WriteLine($command) | Out-Null
    }
    start-sleep -Milliseconds 500
}

$reader.Close()
$writer.Close()
$tcpConnection.Close()
like image 186
Jan Chrbolka Avatar answered Nov 13 '22 00:11

Jan Chrbolka


I found that the NetworkStream DataAvailable property wasn't enough on its own, and that it needed a little nudge before entering the second while loop. I've tested this and it works like a charm when connected to a CISCO device over telnet.

$routerAddress = "192.168.10.126"
$port = "23"
$tcp = New-Object System.Net.Sockets.TcpClient($routerAddress,$Port)
$tcpstream = $tcp.GetStream()
$reader = New-Object System.IO.StreamReader($tcpStream)
$writer = New-Object System.IO.StreamWriter($tcpStream)
$writer.AutoFlush = $true

while ($tcp.Connected)
{       
write-host ([char]$reader.Read()) -NoNewline
while(($reader.Peek() -ne -1) -or ($tcp.Available)){        
    write-host ([char]$reader.Read()) -NoNewline
}
if ($tcp.Connected)
{
    Write-Host -NoNewline "_"
    $command = Read-Host

    if ($command -eq "escape")
    {
        break
    }
    $writer.WriteLine($command) | Out-Null
}     
}
$reader.Close()
$writer.Close()
$tcp.Close()
like image 21
Chris Horan Avatar answered Nov 13 '22 00:11

Chris Horan


I have tried all the solutions.. Chris's suggestion helped, it is needed to check if there's something coming from the reader also. Now it is working fine.

$FTPServer = "localhost"
$FTPPort = "21"

$tcpConnection = New-Object System.Net.Sockets.TcpClient($FTPServer, $FTPPort)
$tcpStream = $tcpConnection.GetStream()
$reader = New-Object System.IO.StreamReader($tcpStream)
$writer = New-Object System.IO.StreamWriter($tcpStream)
$writer.AutoFlush = $true

while ($tcpConnection.Connected) {
    while ($tcpStream.DataAvailable -or $reader.Peek() -ne -1 ) {
        $reader.ReadLine()
    }

    if ($tcpConnection.Connected) {
        Write-Host -NoNewline "prompt> "
        $command = Read-Host

        if ($command -eq "escape") {
            break
        }

        $writer.WriteLine($command) | Out-Null
        Start-Sleep -Milliseconds 10
    }
}

$reader.Close()
$writer.Close()
$tcpConnection.Close()

And here is the output:

220 Microsoft FTP Service
prompt> user username
331 Password required
prompt> pass password
230 User logged in.
prompt> help
214-The following commands are recognized (* ==>'s unimplemented).
    ABOR 
    ACCT 
    ADAT *
    ALLO 
    APPE 
    AUTH 
    CCC 
    CDUP 
    CWD 
    DELE 
    ENC *
    EPRT 
    EPSV 
    FEAT 
    HELP 
    HOST 
    LANG 
    LIST 
    MDTM 
    MIC *
    MKD 
    MODE 
    NLST 
    NOOP 
    OPTS 
    PASS 
    PASV 
    PBSZ 
    PORT 
    PROT 
    PWD 
    QUIT 
    REIN 
    REST 
    RETR 
    RMD 
    RNFR 
    RNTO 
    SITE 
    SIZE 
    SMNT 
    STAT 
    STOR 
    STOU 
    STRU 
    SYST 
    TYPE 
    USER 
    XCUP 
    XCWD 
    XMKD 
    XPWD 
    XRMD 
214 HELP command successful.
prompt> list
150 Opening ASCII mode data connection.
425 Cannot open data connection.
prompt> escape

PS C:\Users\gazsiazasz>
like image 1
gazsiazasz Avatar answered Nov 13 '22 02:11

gazsiazasz