[PYTHON] Scapy Tips

Overview

scapy Tips Collection (Sequentially added)

Official documentation

https://scapy.readthedocs.io/en/latest/

Scapy API reference https://scapy.readthedocs.io/en/latest/api/scapy.html

Tips

I want to know the interface name of the Ethernet adapter

Use get_windows_if_list ().

It can be set to iface in the parameter of each API.

reference

[Scapy can't see_use some Ethernet interfaces on Windows · Issue #1542 · secdev_scapy · GitHub]( Written in gpotter2 commented on 7 Aug 2018d at https://webcache.googleusercontent.com/search?q=cache:qS0tKu17dBoJ: https://github.com/secdev/scapy/issues/1542)

code

from scapy.all import *
get_windows_if_list()

result

The value of name can be set in the argument iface of each API. In the example below, 'Ethernet 6', 'Ethernet 2', etc. Find the desired Ethernet adapter by MAC or IP address. You can set the name to iface.

In [6]: from scapy.all import *
   ...: get_windows_if_list()
Out[6]: 
[{'name': 'Ethernet 6',
  'win_index': 15,
  'description': 'ASIX AX88179 USB 3.0 to Gigabit Ethernet Adapter #2',
  'guid': '{93E3CFB5-11A7-43F4-9BE0-E42AD69529A3}',
  'mac': '74:03:bd:7f:83:21',
  'ipv4_metric': 5,
  'ipv6_metric': 5,
  'ips': ['fe80::b964:9105:342:b0e1', '192.168.51.123']},
 ...
 {'name': 'Ethernet 2',
  'win_index': 11,
  'description': 'Intel(R) Ethernet Connection (5) I219-LM',
  'guid': '{6091155D-A8EA-491C-BA3D-CD5CB22B29BE}',
  'mac': '40:b0:34:1a:78:6f',
  'ipv4_metric': 25,
  'ipv6_metric': 0,
  'ips': ['10.168.38.67']},
   ...

Note

~~ Nmap Loopback Adapter (a virtual adapter for checking communication between 127.0.0.1) also appears here, but when I try to pcap the packet obtained by sniff () with wrpcap (), it fails. investigating. ~~

It also occurred on the real interface. What happened in the real interface is that the packet obtained by sniff () is stored in the list. It was because I was passing it to wrpcap (). In terms of image, it was as follows.

[<Sniffed: TCP:0 UDP:5 ICMP:0 Other:5>, <Sniffed: TCP:0 UDP:5 ICMP:0 Other:5>, ...]

(I was creating a list of instances of scapy.plist.PacketList)

Although append () etc. were not supported, + = could be used, so the following writing method was possible.

all_packets = None
#loop
...
    pkts = scpy.sniff(iface="Ethernet 4", count=10)
    if all_packets :
        all_packets += pkts #After the first time+=I will add it with.
    else:
        all_packets = pkts #First time
wrpcap(fname, all_packets )

It seems that it is useless if Loopback Pseudo-Interface 1 is selected when you want to see loopback ("127.0.0.1").

  File "C:\Python37\lib\site-packages\scapy\arch\windows\__init__.py", line 706, in dev_from_pcapname
    raise ValueError("Unknown pypcap network interface %r" % pcap_name)
ValueError: Unknown pypcap network interface 'Loopback Pseudo-Interface 1'

When I set "Npcap Loopback Adapter" to ifcace, I was able to get the pcap of "127.0.0.1". However, if you measure the "Npcap Loopback Adapter" directly with wireshark, you can analyze the packet properly, When I open the acquired pcap, N / A is displayed even though the data is the same.

image.png

Since you can get the actual interface, is there any problem? .. .. Would you like to do QA with github or stack overflow? .. ..

https://github.com/nmap/nmap/issues/200 By https://wiki.wireshark.org/NullLoopback It has become?

I want to easily put out a summary (IP address, port) of received packets to the console for the time being.

reference

scapy.sendrecv.sniff(*args, **kwargs) https://scapy.readthedocs.io/en/latest/api/scapy.sendrecv.html#scapy.sendrecv.sniff

code

The following is a synchronous method, so you need to stop it with Ctrl + C. It is also possible to set stop conditions based on the number of received packets and timeout.

from scapy.all import *
sniff(iface='Ethernet 4', prn=lambda x: x.summary())

result

In [7]: from scapy.all import *
   ...: sniff(iface='Ethernet 4', prn=lambda x: x.summary())
Ether / IP / UDP 192.168.50.12:30490 > 237.50.0.1:30490 / Raw
Ether / IP / UDP 192.168.50.12:30490 > 237.50.0.1:30490 / Raw
Ether / IP / UDP 192.168.50.12:30490 > 237.50.0.1:30490 / Raw
Ether / IP / UDP 192.168.50.12:30490 > 237.50.0.1:30490 / Raw
Ether / IP / UDP 192.168.50.12:30490 > 237.50.0.1:30490 / Raw
Ether / IP / UDP 192.168.50.12:30490 > 237.50.0.1:30490 / Raw
Ether / IP / UDP 192.168.50.12:30490 > 237.50.0.1:30490 / Raw
Ether / ARP who has 192.168.51.2 says 192.168.51.1 / Padding
Ether / IP / UDP 192.168.50.12:30490 > 237.50.0.1:30490 / Raw
Ether / ARP who has 192.168.51.2 says 192.168.51.1 / Padding
Ether / ARP who has 192.168.51.2 says 192.168.51.1 / Padding
Ether / IP / UDP 192.168.50.12:30490 > 237.50.0.1:30490 / Raw
Ether / ARP who has 192.168.51.2 says 192.168.51.1 / Padding
Ether / ARP who has 192.168.51.2 says 192.168.51.1 / Padding
Ether / IP / UDP 192.168.50.12:30490 > 237.50.0.1:30490 / Raw
Ether / ARP who has 192.168.51.2 says 192.168.51.1 / Padding
Ether / ARP who has 192.168.51.2 says 192.168.51.1 / Padding
Out[7]: <Sniffed: TCP:0 UDP:10 ICMP:0 Other:7>

I want to receive a packet in another thread and output it to the log + pcap.

AsyncSniffer will be written separately.

Here is an example of a class that adds a method to make pcap based on the article Network programming using Python Scapy --Qiita.

code

import threading
import scapy.all as scpy
import datetime
from logging import getLogger, basicConfig, NullHandler,DEBUG, INFO, WARNING
mylogger = getLogger(__name__)
mylogger.addHandler(NullHandler())

class Sniffer(threading.Thread):
    def __init__(self, iface, count=20, timeout=3, logger=None):
        self.stop_event = threading.Event() #Flag to stop
        self.thread = threading.Thread(target = self._sniffer_main_loop)
        self.iface = iface
        self.count = count
        self.timeout = timeout
        self.packets = None
        if logger:
            self.log = logger
        else:
            self.log = mylogger
        
    def start(self):
        self.log.debug(f"try to start thread.")
        self.packets = None
        self.stop_event.clear()
        self.thread.start()

    def stop(self):
        self.log.debug(f"try to stop thread.")
        self.stop_event.set()
        self.thread.join()

    def _sniffer_main_loop(self):
        self.log.debug(f"start thread.")

        try:
            while not self.stop_event.is_set():
                pkts = scpy.sniff(iface=self.iface, count=self.count, timeout=self.timeout)
                if self.packets:
                    self.packets += pkts
                else:
                    self.packets = pkts
        except Exception as e:
            self.log.error(f"exception occurred. stop sniffer main loop. {e}")
            self.stop_event.set()
        
        self.log.debug(f"end thread.")

    def create_pcap(self, fname=datetime.datetime.now().strftime("doip_test_%H%M%S.cap")):
        self.stop() if not self.stop_event.is_set() else None
        scpy.wrpcap(fname, self.packets)

result

How to use is added separately.

Recommended Posts

Scapy Tips
python tips
Jupyter Tips 4
numpy tips
python tips
Jupyter Tips 5
Jupyter Tips 3
Jupyter Tips 2
scapy IPv6
Python Tips
Python tips
Python Conda Tips
Django's personal tips
Python debugging tips
Python click tips
[pandas] GroupBy Tips
Unexpectedly (?) Python tips
Tensorflow personal tips
Django Template Tips
fabric Writing Tips
LTTng Tracing Tips
Choregraphe Tips Collection