如何从pyqt5服务器发送命令到多个已连接的客户端(基于它们的client.id),然后将响应接收回服务器?

时间:2019-06-01 02:54:03

标签: python pyqt pyqt5 qtcpsocket qtcpserver

我创建了一个pyqt5应用程序,我希望将其用于渗透测试。我有一个带有PyqtServer的主gui,并且我有pyqt5客户端(没有gui的),它们可以连接回服务器并接收客户端ID。首先,主gui启动服务器,然后可以部署客户端并连接回服务器。为客户端分配了一个客户端ID和一个套接字(ipaddress:port)。接下来,我想从服务器向客户端发送命令,并从客户端收到包含请求信息的响应。这些命令可以是我定义的任意数量的基于文本的命令,但是客户端需要访问Windows计算机上的命令外壳,然后能够使用请求的信息回复给服务器。

我请求协助以帮助完成我的代码,以允许我的服务器和客户端按照我所描述的方法进行通信。请参阅下面的代码示例。

我在做三件事时遇到问题。

  1. 向客户端ID发送命令,以断开客户端与主机的连接并阻止其发送数据。

  2. 发送命令到客户端,以检查客户端的主机环境,然后将请求的信息回复给服务器。

  3. 我想从服务器向客户端发送命令,并从客户端接收回响应。

我已经尝试了多种方法,并且已经进行了几个月的研究。我创建了一个更深入的控制台版本,但是此处提供了一个非常基本的控制台版本演示。 https://github.com/jinverar/TCP-ReverseShell,并且控制台版本是仅python代码。

我看了多个pyqt5培训视频,并尝试使用许多由讲师教的聊天程序,但是似乎没有任何效果。我的客户端确实连接了,但是我无法向客户端发送信号以执行简单的操作,例如检查主机环境(如下面的代码所示,getenv)。

我尝试发送简单的打印命令,如果客户端和服务器正确通信,则会发生这些命令。我尝试使用pydbg进行错误检查。

我最新的pyqt5客户端代码如下

下面的代码来自tcp_client.py

import os
import platform
import sys
from PyQt5.QtWidgets import QApplication, QDialog
from PyQt5.QtNetwork import QTcpSocket
from PyQt5.QtNetwork import QTcpServer, QHostAddress, QTcpSocket
from PyQt5.QtCore import QDataStream, QByteArray, QIODevice
from gui import *

class Client():
    def __init__(self, lineEdit=None, events_textEdit=None):
        super().__init__()
        HOST = 'x.x.x.x'
        PORT = 12345
        self.tcpSocket = QTcpSocket()
        self.tcpSocket.connectToHost(HOST, PORT, QIODevice.ReadWrite)
        self.tcpSocket.error.connect(self.displayError)
        stream = QDataStream(self.tcpSocket)
        stream.setVersion(QDataStream.Qt_5_12)

        while True:

            #if self.tcpSocket.bytesAvailable() <= 0:
             #   break
            data_byte_array = QByteArray()
            stream = QDataStream(data_byte_array, QIODevice.ReadWrite)
            stream.readUInt32()
            text_from_server = stream.readQString()
            #if App.commands:
            if 'kill' in text_from_server:
                print('display_text')
                print(text_from_server)
                break
            elif 'getenv' in text_from_server:
                print( "[+] Platform Is " + platform.platform())
                print(text_from_server)


    def displayError(self):
        print(self, "The following error occurred: %s." % self.tcpSocket.errorString())

if __name__ == '__main__':

    import sys
    client = Client()

下面是位于maingui中的我的服务器代码的一些摘要。主要的gui有1000行以上的代码。

下面的代码来自Gui.py

import os
import sys
import socket
from PyQt5.QtWidgets import QMainWindow, QMenu, QApplication
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMenu
from PyQt5.QtGui import QPixmap, QIcon
from PyQt5.QtCore import Qt, QObject
import threading

from HandlerDialog import Handler_Dialog
from BuilderDialog import Builder_Dialog
import resources

from PyQt5.QtNetwork import QTcpServer, QHostAddress, QTcpSocket
from PyQt5.QtCore import QDataStream, QByteArray, QIODevice
from tcp_client import *

# globals
SERVER_ADDRESS = "localhost"
SERVER_PORT = 12345

# Snip...snip....snip...setup the main gui and do geometry. Set up lineEdits and TextEdits and VisualDisplays. 

    # ----------------------------------------------------------
    def start_server(self):
        self.tcp_server = QTcpServer()
        self.tcpSocket = QTcpSocket(self)
        self.tcp_server.listen(QHostAddress(SERVER_ADDRESS), SERVER_PORT)
        self.tcp_server.newConnection.connect(self.connect_client)
        self.clients = []

    #----------------------------------------------------------------
    def server_disconnect(self):
        self.tcpSocket.close(client_socket)

    # ----------------------------------------------------------
    def connect_client(self):
        client_socket = (self.tcp_server.nextPendingConnection())  # Returns the next pending connection as a connected QTcpSocket object
        self.clients.append(client_socket)
        self.host_label_1 = QtWidgets.QLabel(self.widget1)
        self.host_label_1.setText("")
        self.host_label_1.setPixmap(QtGui.QPixmap(":/my/image.jpg"))
        self.host_label_1.setObjectName("host_label_1") 
        self.host_label_1.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.host_label_1.customContextMenuRequested.connect(self.on_context_menu)
        self.horizontalLayout.addWidget(self.host_label_1)
        self.events_textEdit.setText(" [**] hello I am a connected client and my id is %s" % self.clients)
        self.events_textEdit.append(' [**] hello I am a connected client')
        client_socket.readyRead.connect(self.read_data)
    # ----------------------------------------------------------
    def read_data(self):
        for client_id, client_socket in enumerate(self.clients):
            if client_socket.bytesAvailable() > 0:
                stream = QDataStream(client_socket)
                stream.setVersion(QDataStream.Qt_5_12)
                stream.readUInt32()
                self.client_data = stream.readQString()
                self.events_textEdit.append('working')
                self.events_textEdit.append(self.client_data)
    # ----------------------------------------------------------
    def send_data(self):
        try: self.write_data()
        except: pass 
    # ----------------------------------------------------------
    def write_data(self, client_id, data):
        for client_socket in self.clients:
            send_data_string = str(self.lineEdit.text())
            data_byte_array = QByteArray()
            stream = QDataStream(data_byte_array, QIODevice.WriteOnly)
            stream.setVersion(QDataStream.Qt_5_12)   
            stream.writeUInt32(0)
            stream.writeQString(send_data_string)     
            self.socket.write(data_byte_array)

下面的代码来自命令功能,该功能允许用户发布命令。

    def commands(self):
        # below is the code to do STDOUT STDERR for lineeditTab1
        command = str(self.lineEdit.text())
        stdouterr = os.popen(command).read()
        self.events_textEdit.setText(stdouterr)

        try:
                if "help" in command:
                    #This is the program menu
                    self.events_textEdit.setText("[**] below are the main window help commands ")

               if 'exit' in command:
                    app.exit()

                if 'listclients' in command:
                    self.events_textEdit.setText(" [**] clients are connected and their ids are %s" % self.clients)


                if 'getenv' in command:
                    self.send_data(getenv)

                if 'tcpserver shutdown' in command:
                    self.tcp_server.close()
                    self.events_textEdit.setText( " [**] the tcp server has been shutdown ")

                if 'kill' in command:
                    self.tcpSocket.disconnectFromHost()
                    self.tcpSocket.close()
                    self.events_textEdit.setText( " [**] the clients are disconnected ")


                if 'test' in command:
                    self.events_textEdit.setText( " [**] this is a test to see if we can print ")
            except:
                self.events_textEdit.append(" [**] commands not valid, try again or try help ")

我想做的主要事情是以反向shell方法将信息从客户端发送到服务器,但是服务器是发送命令的服务器,然后客户端将信息发送回服务器端的操作员(例如,像netcat反向shell)。我想仅使用pyqt5网络和一些python代码来执行此操作。

我请求协助以帮助完成我的代码,以允许服务器和客户端以上述方法进行通信。

0 个答案:

没有答案
相关问题