Socket Dateidownload wird langsamer

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
EiSiMo
User
Beiträge: 15
Registriert: Freitag 16. Juni 2017, 17:05

Moin,
Ich programmiere schon seit längerer Zeit eine Python Backdoor jedoch habe ich immer noch das Problem, dass sich die Geschwindigkeit beim Dateidownload drastisch mit dem fortschreiten des Downloads verringert. Ich habe schon sehr viel gegoogelt, bisher aber nichts gefunden.

Dann habe ich auf Server-Seite die Zeit gemessen, welche die sock.recv() Funktion pro Paket braucht, diese Werte dann gerundet, für 100 Pakete gemittelt und in folgendem Diagramm dargestellt: https://drive.google.com/open?id=13fFuX ... 1CzazxR8zx
Man erkennt, dass die Geschwindigkeit linear abnimmt. Wenn ich den Download neu starte ist es am Anfang wieder sehr schnell und wird zum Ende hin sehr langsam.
Ich verwende TCP und habe über localhost herunter geladen. Das Problem tritt aber auch direkt übers Internet auf.
Hier der Code von der Downloadfunktion auf Server-Seite:

Code: Alles auswählen

def download_file(self, path_to_open, path_to_save, connections):
        request = {"cmd": "d",
                   "open_path": path_to_open}
        for connection in connections:
            try:
                self.connection.send(self.enc_request(request), connection)
                response = self.dec_response(self.connection.recv(connection))
                if response["error"]:
                    print("[-] " + response["error"])
                else:
                    len_data_total = int(response["length"])
                    data = bytes()
                    while not data.endswith(self.connection.END_MARKER):
                        data += connection.recv(self.connection.PACKET_SIZE)
                        len_data_current = len(data)
                        self.update_line("\r[*] " + str(int(len_data_current / (len_data_total / 100))) + "% complete")
                    data = base64.b64decode(data[:-(len(self.connection.END_MARKER))])
                    with open(path_to_save, "wb") as file:
                        # TODO error handling
                        file.write(data)
            except socket.error as error:
                self.update_line("\r[-] SocketError: " + str(error) + ": " + str(self.get_index_by_connection(connection)))
            except KeyboardInterrupt:
                self.update_line("\r[*] download canceled")
            print()
Der ganze Code: https://github.com/EiSiMo/PythonBackdoor

Also meine Fragen:
Wieso wird der Download immer langsamer?
Wie kann ich den Fehler beheben?

Ich habe natürlich nicht vor, die Backdoor an fremden Systemen zu verwenden, finde es nur ein schönes Projekt, da es so vielseitig ist und man viele Bibliotheken ausprobieren kann.

Vielen Dank für alle Antworten!
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Socket-Programmierung ist nicht ganz einfach. Es ist zwar nicht so komplett falsch, wie bei vielen anderen Beispielen, die man im Netz findet, aber auch nicht ganz richtig. Es kann immer noch sein, dass der Marker irgendwo mitten im Bytestrom kommt. TCP kennt 8bit, alles Base64 zu kodieren ist unnötig. Die Klassen sind irgendwie keine richtigen Klassen. __init__ ist zum Initialisieren da und nicht um ewig zu laufen. Wenn man ständig größere Bytestrings im Speicher hin und her kopiert, könnte es langsamer werden.
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

``data += …`` ist auf jeden Fall schon mal so überhaupt keine gute Idee. `bytes`-Objekte kann man nicht verändern, das heisst für jedes empfangene Paket wird ein neues `bytes`-Objekt erstellt, der Inhalt des alten dort hinein kopiert und das empfangene Paket ans ende kopiert. Je mehr Pakete empfangen werden um so grösser wird die Datenmenge die da immer mehr sinnlos im Speicher herum kopiert wird. Nimm dafür mal ein `bytearray()` und statt ``+=`` die `extend()`-Methode.

Falls `enc_` und `dec_` für `encode_` und `decode_` stehen sollen, dann nenn das doch auch so!

`self.connection` vs. `connections`/`connection` finde ich ein bisschen verwirrend.

Das zusammenstückeln von Zeichenketten und Werten mit ``+`` und `str()` ist eher BASIC als Python. In Python gibt es dafür Zeichenkettenformatierung mit der `format()`-Methode und ab Python 3.6 f-Zeichenkettenliterale.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
EiSiMo
User
Beiträge: 15
Registriert: Freitag 16. Juni 2017, 17:05

Vielen Dank für eure Antworten!
Den Bytearray mit .extend() zu erweitern verhindert nicht nur, dass sich der Download verlangsamt, sondern hat auch die gesammte Downloadzeit bei 8Mb Daten von 120 auf ca. 2 Sekunden verringert. Auch die anderen Tipps bezüglich Variablennamen und String-Formatierung sowie die richtige Nutzung der __init__ Methode werde ich umsetzen.
Antworten