I wrote a function a while back as a quick means to not only check for an open port, but also to see if a header is sent back on the initial connection. The reasoning behind this was to help troubleshoot an ESXi host by looking at port 902, which would return a header response if a connection was made. Typically this would be done using the Telnet client, but this is not installed by default. Enter PowerShell to provide a better solution to this issue.
Rather than dive into everything that I have done previously, I will direct you to the following blog that I wrote on scanning ports.
The part that I really haven’t talked much about is what to do if there is a response back from the server. First I will make the connection and if there is data available, begin processing it.
$Computer='DC1' $_Port=21 $stringBuilder = New-Object Text.StringBuilder $tcpClient = New-Object System.Net.Sockets.TCPClient $connect = $tcpClient.BeginConnect($Computer,$_port,$null,$null) $wait = $connect.AsyncWaitHandle.WaitOne($TCPtimeout,$false) Write-Verbose "Bytes available: $($tcpClient.Available)" -Verbose
Looks like I have 27 bytes of some data awaiting me at this point in time, but there could be more depending on how much is buffering (there will actually be 127 bytes in this example).
The first thing that I need to do is connect to the Stream using GetStream(). Once I have that, I want to make sure that I create a byte buffer which is large enough to hold the data stream.
$stream = $TcpClient.GetStream() $bindResponseBuffer = New-Object Byte[] -ArgumentList $tcpClient.Available
If I look at the $bindResponseBuffer, it will be nothing but 0s. This is because I have not added anything to it just yet, it is just an empty buffer. To make better use of this buffer, I will begin reading the data via the stream. This is done using the Read() method of the stream object and giving my empty buffer, setting the starting location to the beginning of the stream (0) and then lastly the maximum number of bytes to read from the stream.
[Int]$response = $stream.Read($bindResponseBuffer, 0, $bindResponseBuffer.count)
Now let’s take another look at the buffer.
That looks more like it. Although, this really doesn’t help us see what the actual data is being sent from the remote port.
I do this by casting the byte into something more readable by using [char] type accelerator. Let’s just use this on the first byte to see what we get.
[char]50
The 50 byte is actually a 2. Now, using my stringbuilder, I will convert all of the bytes and then display the output.
$Null = $stringBuilder.Append(($bindResponseBuffer | ForEach { [char]$_ }) -join '') $stringBuilder.ToString()
As you can see, the output is very similar to what you would see if you attempted to connect to an FTP server using the FTP client.
I’ve got a function which I wrote to make this process a little easier. An example of it in action is below.
Get-TCPResponse -Computername dc1 -Port 21,25 | Format-List
Download Get-TCPResponse
How can we modify this script to post TCP data stream on a remote server socket before we can expect a response back from the server side?