如何从Python的RAW套接字接收数据



我正在尝试使用插座库来创建一个端口扫描仪(使用SYN数据包)(是的,我知道Scapy会变得更加容易,但是我主要是为了进行学习练习。)我制作了数据包并成功发送了它,但是我遇到了麻烦的接收和解析。到目前为止,我尝试了s.recv(1024)和4096以及recvfrom()

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
s.sendto(packet, (dstip, 80))
r = s.recv(1024)
print(r)

但是,我在收到响应方面遇到困难,我可以看到该数据包是通过Wireshark正确发送的,并且Syn-Ack被发送到我的计算机,但是我无法正确接收和打印。我可以将s.recv()函数用于此类输入有更好的方法吗?还是我正在使用错误的功能?任何帮助都将受到赞赏,我是插座库的新手。谢谢。

这本书Black Hat Python的示例使用了插座库来创建扫描仪,不幸的是不是端口扫描仪。他们检查主机是否已启动,并使用原始插座接收数据。该代码可在此处提供。

他们在新线程中以一个套接字对象发送Syn-packet,并使用另一个套接字对象嗅探答复。

在示例中,他们使用socket.IPPROTO_IPsocket.IPPROTO_ICMP而不是socket.IPPROTO_RAW,具体取决于Windows。

对于sniffer,他们使用函数 setsockopt(socket.IPPROTO_IP, socket.ip_hdrincl , 1)进行嗅探,其中 IPPROTO_IP是tcp的虚拟协议, IP_HDRINCL将包括IP数据包中的标题,而1个映射到ICMP-protocol中的ICMP-protocol中的代码中的标题。

祝你好运!

以下是我在插座IO的各种来源的帮助下写的一个模块,从中拿走您想要的东西。

import socket
import threading
import time    
import pygogo as gogo    
from icentralsimulator.bridgeio.read_packets import PacketFactory
from icentralsimulator.bridgeio.write_packets import WritePacket
from icentralsimulator.configurations.interfaces import IServerInfoProvider
logger = gogo.Gogo(__name__).logger
send_lock = threading.Lock()

class BridgeConnection:
    def __init__(self, bridge_info_provider: IServerInfoProvider):
        info = bridge_info_provider.get_bridge_server_info()
        self.callback = None
        self.bridge_ip = info.IpAddress
        self.bridge_port = info.Port
        self._connection = None
        self._terminate_wait_for_incoming = False

    @property
    def is_connected(self):
        return self._connection is not None

    def connect(self, callback):
        """
        The purpose of this method is to create (and hold) a connection to the server. At the same time,
        it creates a new thread for the purpose of waiting on incoming packets.
        """
        if self._connection is not None: return
        self._connection = socket.create_connection((self.bridge_ip, self.bridge_port))
        self._connection.settimeout(0.5)
        self.callback = callback
        t = threading.Thread(target=self._wait_for_incoming)
        t.start()
        time.sleep(5)

    def disconnect(self):
        """
        Breaks existing connection to the server if one is currently made and cancels the thread that is waiting
        for incoming packets. If the connection is not currently open, simply returns silently -- thus it is safe
        to call this method repeatedly.
        """
        self._terminate_wait_for_incoming = True
        while self._terminate_wait_for_incoming:
            time.sleep(0.1)
        self._connection.close()
        self._connection = None

    def send_packet(self, packet: WritePacket):
        """
        Sends an arbitrary packet to the server.
        """
        with send_lock:
            logger.debug(f"Sending packet: {packet.payload_plain_text}")
            payload = packet.payload
            self._connection.sendall(payload)

    def _wait_for_incoming(self):
        """
        Continually runs a loop to wait for incoming data on the open socket. If data is received, it is converted
        to a receive packet and forwarded to the consumer as part of a callback.
        """
        self._terminate_wait_for_incoming = False
        buf_len = 4096
        try:
            while not self._terminate_wait_for_incoming:
                data = None
                try:
                    _cnx = self._connection
                    if _cnx is None: break
                    data = _cnx.recv(buf_len)
                    if data is not None and len(data) > 0:
                        while True:
                            new_data = _cnx.recv(buf_len)
                            if new_data is None or len(new_data) == 0:
                                break
                            data = data + new_data
                except socket.timeout:
                    if data is not None and self.callback is not None:
                        packet = PacketFactory.get_packet(data)
                        self.callback(packet)
                        logger.debug(f"Received packet: {data}")
                    time.sleep(0.5)
                except OSError:  # Happens when stopping the application
                    logger.info("Application aborted")
                    return
        finally:
            self._terminate_wait_for_incoming = False

请注意,我不包括Iserverinfoprovider或此处的PacketFactory。这些是我应用程序的习惯。您需要根据到达特定用例中的数据包数据来解释数据包。

最新更新