通過PowerShell傳送TCP請求

@天行健中國元素發表於2013-10-03

很多時候我們需要通過Socket傳送特定的TCP請求給伺服器的特定埠來實現探測伺服器的指定埠所開啟的服務。很多語言都有相應的方法實現上述需求,當然,PowerShell也不例外,比如我們要傳送一個簡單的http請求到指定的web伺服器:

GET / HTTP/1.1
Host:cn.bing.com

這裡我們想請求微軟必應的中文首頁,如果需要通過PowerShell向cn.bing.com伺服器傳送get請求,就需要建立一個System.Net.Sockets.TcpClient物件,向指定的伺服器和埠傳送請求。

具體程式碼如下:

        =====檔名:Send-TcpRequest.ps1=====
######################################## 
# Send-TcpRequest.ps1 
## Send a TCP request to a remote computer, and return the response. 
## If you do not supply input to this script (via either the pipeline, or the 
## -InputObject parameter,) the script operates in interactive mode. 
## 
## Example: 
## 
## $http = @" 
## GET / HTTP/1.1 
## Host:cn.bing.com  
## `n`n 
## "@ 
## 
## $http | .\Send-TcpRequest cn.bing.com  80 
######################################## 
param( 
        [string] $remoteHost = "localhost", 
        [int] $port = 80, 
        [switch] $UseSSL, 
        [string] $inputObject, 
        [int] $commandDelay = 100 
     ) 

[string] $output = "" 

## Store the input into an array that we can scan over. If there was no input, 
## then we will be in interactive mode. 
$currentInput = $inputObject 
if(-not $currentInput) 
{ 
    $SCRIPT:currentInput = @($input) 
} 
$scriptedMode = [bool] $currentInput 

function Main 
{ 
    ## Open the socket, and connect to the computer on the specified port 
    if(-not $scriptedMode) 
    { 
        write-host "Connecting to $remoteHost on port $port" 
    } 

    trap { Write-Error "Could not connect to remote computer: $_"; exit } 
    $socket = new-object System.Net.Sockets.TcpClient($remoteHost, $port) 

    if(-not $scriptedMode) 
    { 
        write-host "Connected. Press ^D followed by [ENTER] to exit.`n" 
    } 

    $stream = $socket.GetStream() 

    if($UseSSL) 
    { 
        $sslStream = New-Object System.Net.Security.SslStream $stream,$false 
        $sslStream.AuthenticateAsClient($remoteHost) 
        $stream = $sslStream 
    } 

    $writer = new-object System.IO.StreamWriter $stream 

    while($true) 
    { 
        ## Receive the output that has buffered so far 
        $SCRIPT:output += GetOutput 

        ## If we're in scripted mode, send the commands, 
        ## receive the output, and exit. 
        if($scriptedMode) 
        { 
            foreach($line in $currentInput) 
            { 
                $writer.WriteLine($line) 
                $writer.Flush() 
                Start-Sleep -m $commandDelay 
                $SCRIPT:output += GetOutput 
            } 

            break 
        } 
        ## If we're in interactive mode, write the buffered 
        ## output, and respond to input. 
        else 
        { 
            if($output)  
            { 
                foreach($line in $output.Split("`n")) 
                { 
                    write-host $line 
                } 
                $SCRIPT:output = "" 
            } 

            ## Read the user's command, quitting if they hit ^D 
            $command = read-host 
            if($command -eq ([char] 4)) { break; } 

            ## Otherwise, Write their command to the remote host 
            $writer.WriteLine($command) 
            $writer.Flush() 
        } 
    } 

    ## Close the streams 
    $writer.Close() 
    $stream.Close() 

    ## If we're in scripted mode, return the output 
    if($scriptedMode) 
    { 
        $output 
    } 
} 

## Read output from a remote host 
function GetOutput 
{ 
    ## Create a buffer to receive the response 
    $buffer = new-object System.Byte[] 1024 
    $encoding = new-object System.Text.AsciiEncoding 

    $outputBuffer = "" 
    $foundMore = $false 

    ## Read all the data available from the stream, writing it to the 
    ## output buffer when done. 
    do 
    { 
        ## Allow data to buffer for a bit 
        start-sleep -m 1000 

        ## Read what data is available 
        $foundmore = $false 
        $stream.ReadTimeout = 1000 

        do 
        { 
            try 
            { 
                $read = $stream.Read($buffer, 0, 1024) 

                if($read -gt 0) 
                { 
                    $foundmore = $true 
                    $outputBuffer += ($encoding.GetString($buffer, 0, $read)) 
                } 
            } catch { $foundMore = $false; $read = 0 } 
        } while($read -gt 0) 
    } while($foundmore) 

    $outputBuffer 
} 
. Main 

該指令碼使用方法如下:

$http = @"
GET / HTTP/1.1
Host:cn.bing.com
`n`n
"@

$http | .\Send-TcpRequest cn.bing.com 80

執行效果如圖所示:

image

需要說明的是,由於頁面返回的內容太長了,這裡至少是將返回的內容快取在一個變數裡,並只輸出了變數的頭10行。

有了這個指令碼,我們就可以向指定的web伺服器傳送特定的請求,來實現模擬登陸和操作的功能了。

 

作者: 付海軍
出處:http://fuhj02.cnblogs.com
版權:本文版權歸作者和部落格園共有
轉載:歡迎轉載,為了儲存作者的創作熱情,請按要求【轉載】,謝謝
要求:未經作者同意,必須保留此段宣告;必須在文章中給出原文連線且保證內容完整!否則必究法律責任!
個人網站: http://www.fuhaijun.com/

相關文章