It’s hard to believe, how easy it is to capture (and to craft) LAN-Data using Python Scapy.
I need to capture CDP-Packets and to extract information like the hostname of the sender and it’s IP-Address.
As an modification of the „ARP-Monitor“-example taken from the manual Using scapy in your tools.
- Scapy Installation
nothing special: pip install
C:\RH>pip install scapy
Collecting scapy
Downloading https://files.pythonhosted.org/packages/68/01/b9943984447e7ea6f8948e90c1729b78161c2bb3eef908430638ec3f7296/scapy-2.4.0.tar.gz (3.1MB)
100% |████████████████████████████████| 3.1MB 420kB/s
In the tar file C:\Users\RONALD~1.HEI\AppData\Local\Temp\pip-unpack-4jm9kde1\scapy-2.4.0.tar.gz the member scapy-2.4.0/README is invalid: unable to resolve link inside archive
Installing collected packages: scapy
Running setup.py install for scapy ... done
Successfully installed scapy-2.4.0
- Python: Install Scapy
C:\RH>python
Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from scapy.all import *
- Example: List all Interfaces of my Laptop
>>> ifaces
INDEX IFACE IP MAC
20 VirtualBox Host-Only Ethernet Adapter 192.168.56.1 0A:00:27:00:00:14
22 Intel(R) Dual Band Wireless-AC 8265 172.20.10.2 IntelCor:BD:10:37
4 Intel(R) Ethernet Connection (4) I219-LM 47.11.17.10 BayNetwo:00:DE:11
>>> for i in ifaces.data.keys():
... iface = ifaces.data[i]
... name = str(iface.name)
... wname = iface.data['netid']
... mac = str(iface.mac)
... ip = str(iface.ip)
... print("DESCR:{0}, NAME:{1}, MAC:{2}, IP:{3}".format(wname,name,mac,ip))
...
DESCR:Wi-Fi, NAME:Intel(R) Dual Band Wireless-AC 8265, MAC:74:70:FD:BD:10:37, IP:172.20.10.2
DESCR:VirtualBox Host-Only Network, NAME:VirtualBox Host-Only Ethernet Adapter, MAC:0A:00:27:00:00:14, IP:192.168.56.1
DESCR:ETH_DELL, NAME:Intel(R) Ethernet Connection (4) I219-LM, MAC:00:00:81:00:DE:11, IP:47.11.17.10
- Capture 10 Packets on a specific interface
The "NAME" is needed as interface-handle
>>> interface="VirtualBox Host-Only Ethernet Adapter"
>>> p=sniff(iface=interface, count=10)
>>> p.display()
0000 Ether / IP / UDP 192.168.56.1:17500 > 255.255.255.255:17500 / Raw
0001 Ether / IP / UDP 192.168.56.1:17500 > 255.255.255.255:17500 / Raw
0002 Ether / IP / UDP 192.168.56.1:17500 > 192.168.56.255:17500 / Raw
0003 Ether / IP / UDP 192.168.56.1:17500 > 255.255.255.255:17500 / Raw
0004 Ether / IP / UDP 192.168.56.1:17500 > 255.255.255.255:17500 / Raw
0005 Ether / IP / UDP 192.168.56.100:bootps > 255.255.255.255:bootpc / BOOTP / DHCP
0006 Ether / IP / UDP 192.168.56.102:50472 > 255.255.255.255:10067 / Raw
0007 Ether / IP / UDP 192.168.56.103:49580 > 255.255.255.255:10067 / Raw
0008 Ether / IP / UDP 192.168.56.1:17500 > 255.255.255.255:17500 / Raw
0009 Ether / IP / UDP 192.168.56.1:17500 > 255.255.255.255:17500 / Raw
- Capture CDP-Packets
Capture CDP
>>> p=sniff(iface=interface, count=2, filter="ether dst 01:00:0c:cc:cc:cc")
>>> p
<Sniffed: TCP:0 UDP:0 ICMP:0 Other:2>
>>> p.display()
0000 802.3 08:00:27:c9:d5:7e > 01:00:0c:cc:cc:cc / LLC / SNAP / Raw
0001 802.3 08:00:27:c9:d5:7e > 01:00:0c:cc:cc:cc / LLC / SNAP / Raw
- Decode CDP (with inactive dissector)
>>> p[0].display()
###[ 802.3 ]###
dst = 01:00:0c:cc:cc:cc
src = 08:00:27:c9:d5:7e
len = 386
###[ LLC ]###
dsap = 0xaa
ssap = 0xaa
ctrl = 3
###[ SNAP ]###
OUI = 0xc
code = 0x2000
###[ Raw ]###
load = '\x02\xb4\x91\x18\x00\x01\x00\x13CSR-A.lab.local\x00\x05\x01\x05Cisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.9.1, RELEASE SOFTWARE (fc2)\nTechnical Support: http://www.cisco.com/techsupport\nCopyright (c) 1986-2018 by Cisco Systems, Inc.\nCompiled Tue 17-Jul-18 16:57 by mcpre\x00\x06\x00\x12cisco CSR1000V\x00\x02\x00\x11\x00\x00\x00\x01\x01\x01\xcc\x00\x04\xc0\xa88e\x00\x03\x00\x14GigabitEthernet2\x00\x04\x00\x08\x00\x00\x00!\x00\x07\x00\t\n\x00\x02\x00\x18\x00\x0b\x00\x05\x01\x00\x16\x00\x11\x00\x00\x00\x01\x01\x01\xcc\x00\x04\xc0\xa88e'
- Activate the CDP-Parser
>>> list_contrib()
avs : AVS WLAN Monitor Header status=loads
bgp : BGP v0.1 status=loads
carp : CARP status=loads
cdp : Cisco Discovery Protocol status=loads
chdlc : Cisco HDLC and SLARP status=loads
coap : Constrained Application Protocol (CoAP) status=loads
diameter : Diameter status=loads
dtp : DTP status=loads
eigrp : EIGRP status=loads
etherip : EtherIP status=loads
gsm_um : PPI status=loads
gtp : GTP status=loads
gtp_v2 : GTPv2 status=loads
homeplugav : HomePlugAV Layer status=loads
http2 : HTTP/2 (RFC 7540, RFC 7541) status=loads
icmp_extensions : ICMP Extensions status=loads
igmp : IGMP/IGMPv2 status=loads
igmpv3 : IGMPv3 status=loads
ikev2 : IKEv2 status=loads
isis : ISIS status=loads
ldp : Label Distribution Protocol (LDP) status=loads
lldp : LLDP status=loads
macsec : - status=?
modbus : ModBus Protocol status=loads
mpls : MPLS status=loads
mqtt : - status=?
nsh : NSH Protocol status=loads
openflow : Openflow v1.0 status=loads
openflow3 : Openflow v1.3 status=loads
ospf : OSPF status=loads
pnio : ProfinetIO base layer status=loads
pnio_rtc : ProfinetIO Real-Time Cyclic (RTC) status=loads
ppi : PPI status=loads
ppi_cace : PPI CACE status=loads
ppi_geotag : PPI GEOLOCATION status=loads
ripng : RIPng status=loads
rsvp : RSVP status=loads
sebek : Sebek status=loads
send : Secure Neighbor Discovery (SEND) (ICMPv6) status=loads
skinny : Skinny Call Control Protocol (SCCP) status=loads
spbm : SBPM status=loads
tacacs : TACACS+ Protocol status=loads
tzsp : TZSP status=loads
ubberlogger : Ubberlogger dissectors status=loads
vqp : VLAN Query Protocol status=loads
vtp : VLAN Trunking Protocol (VTP) status=loads
wpa_eapol : WPA EAPOL dissector status=loads
>>> load_contrib("cdp")
- Capture again and display CDP-Information as cleartext
>>> load_contrib("cdp")
>>> p=sniff(iface=interface, count=1, filter=capturefilter)
>>>
>>>
>>> p[0].show()
###[ 802.3 ]###
dst = 01:00:0c:cc:cc:cc
src = 08:00:27:c9:d5:7e
len = 386
###[ LLC ]###
dsap = 0xaa
ssap = 0xaa
ctrl = 3
###[ SNAP ]###
OUI = 0xc
code = 0x2000
###[ Cisco Discovery Protocol version 2 ]###
vers = 2
ttl = 180
cksum = 0x9118
\msg \
|###[ Device ID ]###
| type = Device ID
| len = 19
| val = 'CSR-A.lab.local'
|###[ Software Version ]###
| type = Software Version
| len = 261
| val = 'Cisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.9.1, RELEASE SOFTWARE (fc2)\nTechnical Support: http://www.cisco.com/techsupport\nCopyright (c) 1986-2018 by Cisco Systems, Inc.\nCompiled Tue 17-Jul-18 16:57 by mcpre'
|###[ Platform ]###
| type = Platform
| len = 18
| val = 'cisco CSR1000V'
|###[ Addresses ]###
| type = Addresses
| len = 17
| naddr = 1
| \addr \
| |###[ CDP Address IPv4 ]###
| | ptype = NLPID
| | plen = 1
| | proto = '\xcc'
| | addrlen = 4
| | addr = 192.168.56.101
|###[ Port ID ]###
| type = Port ID
| len = 20
| iface = 'GigabitEthernet2'
|###[ Capabilities ]###
| type = Capabilities
| len = 8
| cap = Router+IGMPCapable
|###[ IP Prefix ]###
| type = IP Prefix
| len = 9
| defaultgw = 10.0.2.0
|###[ CDP Generic Message ]###
| type = 0x1800
| len = 2816
| val = '\x05\x01\x00\x16\x00\x11\x00\x00\x00\x01\x01\x01\xcc\x00\x04\xc0\xa88e'
- Decode CDP-Hostname
>>> device=p[0]["CDPMsgDeviceID"].val.decode()
>>> device
'CSR-A.lab.local'
>>> hostname=device.split(".")[0]
>>> hostname
'CSR-A'
- Decode CDP-Management-IP-Address
>>> ip=p[0]["CDPAddrRecordIPv4"]
>>> ip.addr
'192.168.56.101'