self._logger.info("Starting DHCP listener") self._socket = scapy.conf.L2listen(type=scapy.ETH_P_ALL, iface=self._interface, filter="udp and (port 67 or 68)") scapy.sniff(opened_socket=self._socket, prn=self._proc_packet, store=False, stop_filter=lambda bool: self._stop_event.isSet()) self._logger.info("DHCP listener stopped")
I also have a L2 socket for sending broadcast discover trames. Implementation below.
result_list, unanswered = self._l2socket.sr(scapy.Ether(dst="ff:ff:ff:ff:ff:ff")/scapy.ARP(pdst=cidr), timeout=20, verbose=True)
The problem is that when I receive a DHCP request callback & when a network discovery is running at the same time, I get the following error:
File "app/lib/network_discoverer.py", line 87, in _discover_network_devices result_list, unanswered = self._l2socket.sr(scapy.Ether(dst="ff:ff:ff:ff:ff:ff")/scapy.ARP(pdst=cidr), timeout=20, verbose=True) File "usr/lib/python3.8/site-packages/scapy/supersocket.py", line 95, in sr File "usr/lib/python3.8/site-packages/scapy/sendrecv.py", line 261, in sndrcv File "usr/lib/python3.8/site-packages/scapy/sendrecv.py", line 136, in __init__ File "usr/lib/python3.8/site-packages/scapy/sendrecv.py", line 243, in _sndrcv_rcv File "usr/lib/python3.8/site-packages/scapy/sendrecv.py", line 925, in _run File "usr/lib/python3.8/site-packages/scapy/sessions.py", line 47, in on_packet_received File "usr/lib/python3.8/site-packages/scapy/sendrecv.py", line 212, in _process_packet File "usr/lib/python3.8/site-packages/scapy/layers/l2.py", line 166, in hashret TypeError: can't concat str to bytes
It occurs only (I'm almost certain) when I'm receiving a DHCP frame while discovering the network.
Any input on why this is happening ? Please :)
Thanks for your time.
Let me start with saying:
Is there anyway to pass a variable when initializing a layer?
Here is my use-case:
Mypacket is a header followed by an encrypted payload.
A field of the header indicates the certificate fingerprint of the public key used to cipher the payload.
In post_dissect(), I would like to be able to: match the cert fingerprint and uncipher the payload.
To avoid hardcoding the fingerprint/cert in my packet description, I was thinking of initializing the layer as follow:
class Mypacket(Packet): name = "Mypacket" fields_desc = [ LenField("mylen", None, fmt="I"), # 4 bytes XNBytesField("fingerprint", 0, 20), ] def post_dissect(self, s): for c in self.credentials: if c.hash == self.fingerprint: return crypto.uncipher(c.private_key, s) return s p = Mypacket(bytes, credentials=credentials)
Is "post_dissect()" the right place for unciphering?
Is there anyway to pass a variable when initializing a layer? if no is there a work-around (maybe a 0 byte field containing some information?) ?
Thanks a lot !
__init__function of your packet to store an extra argument. Have a look online. You can copy the signature of
__init__(*args, credentials=None, **kwargs). Remember to call super
Thanks Gabriel that is super useful !
One additionnal questions here:
Some of the fields within my packet are meant to be manipulated as "bytes field".
Is there a better field than
XNBytesField/NBytesField to manipulate them? By digging, I realize that
NBytesField internal representation is a large int. So comparing
self.fingerprint needs some sugar syntax to either:
c.hashto a NBytesField to make the comparison in the internal format
Oh, nevermind I was reading the doc and realized that XStrLenField is probably the field that I am looking for.
I think it would be worth mentioning "raw" or "raw bytes" in XStrLenField to make it more searchable.
RawPcapNgReader / read_packet(size=x), but without success