【问题标题】:How to send a custom 'TCP' packet, without sudo - without three-way handshake如何在没有 sudo 的情况下发送自定义的“TCP”数据包 - 没有三次握手
【发布时间】:2025-12-07 19:40:01
【问题描述】:

我正在尝试发送一个不使用原始套接字、不经过三次握手且不使用 sudo 的 TCP(以及后来的 ICMP)数据包。我在 python 的 scapy 模块和 python 的 socket 模块中尝试了各种方法,但没有成功。

我知道如果没有三次握手,TCP 不一定是 TCP - 它基本上是 UDP,但我正在测试从网络中窃取数据的各种方法,这些方法可能未被检测到。

基本上这是工作的 UDP 版本,我需要工作的 ICMP 和 TCP 版本,它们不使用原始套接字,因此不需要管理员/root 权限。

最好使用 GO 或 Python 解决方案,理想情况下我需要在 MacOS、Linux 和(主要是)Windows 上运行。

UDP_IP = "127.0.0.1"
UDP_PORT = 5005
MESSAGE = "Data to exfiltrate"

sock = socket.socket(socket.AF_INET, # Internet
             socket.SOCK_DGRAM) # UDP
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))

【问题讨论】:

    标签: python sockets networking go tcp


    【解决方案1】:

    简而言之——你不能,至少在 Linux 下不能。

    您正试图在不遵守 TCP 状态机的情况下发送数据包。如果不使用数据包套接字(直接或通过诸如pcapscapy 之类的库),内核将不允许您这样做,并且原始套接字需要CAP_NET_RAW 功能,通常只授予超级用户.

    【讨论】:

    • 所以要明确一点,据您所知,没有管理员/sudo 权限就无法发送自定义的十六进制数据包?没有函数调用只是说'不要打开等待响应的原始套接字,只需将这个十六进制数据包发送出去'?
    【解决方案2】:

    TCP 是一种面向连接的协议。为了建立 TCP 连接,您必须执行三次握手。在建立连接之前,您操作系统中的 TCP 模块不会发送数据,任何接收到不存在连接的 TCP 段的设备都会忽略它。

    没有连接的 TCP 不是 TCP,但也不是 UDP。 TCP 和 UDP 有不同的协议头。您会注意到 TCP 标头比 UDP 标头具有更多字段,其中许多字段将由握手信息填充。

    RFC 793, Transmission Control Protocol:

    TCP 头格式

     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |          Source Port          |       Destination Port        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                        Sequence Number                        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                    Acknowledgment Number                      |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |  Data |           |U|A|P|R|S|F|                               |
    | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
    |       |           |G|K|H|T|N|N|                               |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |           Checksum            |         Urgent Pointer        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                    Options                    |    Padding    |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                             data                              |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    
                            TCP Header Format
    

    RFC 768, User Datagram Protocol:

    格式

                  0      7 8     15 16    23 24    31
                 +--------+--------+--------+--------+
                 |     Source      |   Destination   |
                 |      Port       |      Port       |
                 +--------+--------+--------+--------+
                 |                 |                 |
                 |     Length      |    Checksum     |
                 +--------+--------+--------+--------+
                 |
                 |          data octets ...
                 +---------------- ...
    
                      User Datagram Header Format
    

    【讨论】:

    • 就像我在描述中所说的那样 - 我知道它不是典型的 TCP,甚至在技术上根本不是“TCP”,但如果网络锁定了 UDP 和 ICMP,它是一种合法的渗漏方法使用防火墙规则,并监控已建立的 TCP 连接。如果我手动制作十六进制而不打开原始套接字(这需要管理员),我需要知道是否可以只发送一个数据包
    • 正如我所写,“在建立连接之前,您操作系统中的 TCP 模块不会发送数据
    • 我不想要一个 TCP 模块,我想发送一个没有原始套接字的数据包。使用 scapy,我可以使用:scapy.send(scapy.IP(dst="x.x.x.x") / scapy.TCP(dport=n) / scapy.Raw(load=data) 这个命令正好给了我我需要的东西,但是,这对所有东西都使用了原始套接字——这需要 sudo。它不需要建立连接来发送带有有效负载的数据包。
    最近更新 更多