我正在尝试使用套接字库创建一个端口扫描程序(使用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()
函数进行此类输入?或者我使用了错误的功能?
任何帮助表示赞赏,我是套接字库的新手。感谢。
答案 0 :(得分:0)
下面是我在套接字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。这些都是我的应用程序的自定义。您需要根据特定用例中的数据包数据来解释数据包。
答案 1 :(得分:0)
Black Hat Python这本书使用套接字库来创建扫描程序,遗憾的是它不是端口扫描程序。他们检查主机是否已启动,并使用原始套接字接收数据。代码可用here。
他们在新线程中发送带有一个套接字对象的SYN数据包,并使用另一个套接字对象嗅探回复。
在示例中,他们使用socket.IPPROTO_IP
或socket.IPPROTO_ICMP
代替socket.IPPROTO_RAW
,具体取决于它是否为Windows。
对于嗅探器,他们使用函数setsockopt(socket.IPPROTO_IP,
socket.IP_HDRINCL , 1)
进行嗅探,其中IPPROTO_IP
是TCP的虚拟协议,IP_HDRINCL
是包含头部的IP数据包,1映射到代码中的ICMP协议。